@Override
  public boolean dispatchTouchEvent(MotionEvent event) {
    if (!onFilterTouchEventForSecurity(event)) return false;

    int action = event.getAction();

    double dx = event.getX() - mCenterX;
    double dy = mCenterY - event.getY();
    double radius = Math.sqrt(dx * dx + dy * dy);

    // Check if the event should be dispatched to the shutter button.
    if (radius <= mShutterButtonRadius) {
      if (mIndicatorControlWheel.getVisibility() == View.VISIBLE) {
        mIndicatorControlWheel.onTouchOutBound();
      }
      if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
        return mShutterButton.dispatchTouchEvent(event);
      }
      return false;
    }

    if (mShutterButton.isPressed()) {
      // Send cancel to the shutter button if it was pressed.
      event.setAction(MotionEvent.ACTION_CANCEL);
      mShutterButton.dispatchTouchEvent(event);
      return true;
    }

    return mIndicatorControlWheel.dispatchTouchEvent(event);
  }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

    // Layout the shutter button.
    int shutterButtonWidth = mShutterButton.getMeasuredWidth();
    int shutterButtonHeight = mShutterButton.getMeasuredHeight();
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
      mCenterX = right - left - Util.dpToPixel(WHEEL_CENTER_TO_SECANT);
      mCenterY = (bottom - top) / 2;
      mShutterButton.layout(
          right - left - shutterButtonWidth,
          mCenterY - shutterButtonHeight / 2,
          right - left,
          mCenterY + shutterButtonHeight / 2);
    } else {
      mCenterX = (right - left) / 2;
      mCenterY = bottom - top - Util.dpToPixel(WHEEL_CENTER_TO_SECANT);
      mShutterButton.layout(
          mCenterX - shutterButtonWidth / 2,
          bottom - top - shutterButtonHeight,
          mCenterX + shutterButtonWidth / 2,
          bottom - top);
    }

    // Layout the control wheel.
    mIndicatorControlWheel.layout(0, 0, right - left, bottom - top);
  }
  @Override
  protected void onMeasure(int widthSpec, int heightSpec) {
    // Measure all children.
    int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    mShutterButton.measure(freeSpec, freeSpec);
    mIndicatorControlWheel.measure(freeSpec, freeSpec);

    // Measure myself. Add some buffer for highlight arc.
    int desiredWidth =
        mShutterButton.getMeasuredWidth() + IndicatorControlWheel.HIGHLIGHT_WIDTH * 4;
    int desiredHeight =
        mShutterButton.getMeasuredHeight() + IndicatorControlWheel.HIGHLIGHT_WIDTH * 4;
    int widthMode = MeasureSpec.getMode(widthSpec);
    int heightMode = MeasureSpec.getMode(heightSpec);
    int measuredWidth, measuredHeight;
    if (widthMode == MeasureSpec.UNSPECIFIED) {
      measuredWidth = desiredWidth;
    } else if (widthMode == MeasureSpec.AT_MOST) {
      measuredWidth = Math.min(desiredWidth, MeasureSpec.getSize(widthSpec));
    } else { // MeasureSpec.EXACTLY
      measuredWidth = MeasureSpec.getSize(widthSpec);
    }
    if (heightMode == MeasureSpec.UNSPECIFIED) {
      measuredHeight = desiredHeight;
    } else if (heightMode == MeasureSpec.AT_MOST) {
      measuredHeight = Math.min(desiredHeight, MeasureSpec.getSize(heightSpec));
    } else { // MeasureSpec.EXACTLY
      measuredHeight = MeasureSpec.getSize(heightSpec);
    }
    setMeasuredDimension(measuredWidth, measuredHeight);
  }
 @Override
 public void replace(
     String key,
     ListPreference pref,
     ArrayList<CharSequence[]> entries,
     ArrayList<CharSequence[]> entryValues) {
   mIndicatorControlWheel.replace(key, pref, entries, entryValues);
 }
 @Override
 public void initialize(
     Context context,
     PreferenceGroup group,
     boolean isZoomSupported,
     boolean isCPcamSlidersSupported,
     String[] keys,
     String[] otherSettingKeys) {
   mIndicatorControlWheel.initialize(context, group, isZoomSupported, keys, otherSettingKeys);
 }
 @Override
 public void stopTimeLapseAnimation() {
   mIndicatorControlWheel.stopTimeLapseAnimation();
 }
 @Override
 public void enableFilter(boolean enabled) {
   mIndicatorControlWheel.setupFilter(enabled);
 }
 @Override
 public void dismissSecondLevelIndicator() {
   mIndicatorControlWheel.dismissSecondLevelIndicator();
 }
 @Override
 public void overrideSettings(final String... keyvalues) {
   mIndicatorControlWheel.overrideSettings(keyvalues);
 }
 @Override
 public void enableZoom(boolean enabled) {
   mIndicatorControlWheel.enableZoom(enabled);
 }
 @Override
 public void setEnabled(boolean enabled) {
   mIndicatorControlWheel.setEnabled(enabled);
 }
 @Override
 public void startTimeLapseAnimation(int timeLapseInterval, long startTime) {
   mIndicatorControlWheel.startTimeLapseAnimation(timeLapseInterval, startTime);
 }
 @Override
 public void setOrientation(int orientation, boolean animation) {
   mIndicatorControlWheel.setOrientation(orientation, animation);
 }
 @Override
 public boolean dismissSettingPopup() {
   return mIndicatorControlWheel.dismissSettingPopup();
 }
 @Override
 public View getActiveSettingPopup() {
   return mIndicatorControlWheel.getActiveSettingPopup();
 }
 @Override
 public void reloadPreferences() {
   mIndicatorControlWheel.reloadPreferences();
 }
 @Override
 public void setListener(OnPreferenceChangedListener listener) {
   mIndicatorControlWheel.setListener(listener);
 }