private void syncWithService() {
    int color = mService.getColor();
    Drawable drawable = mService.getDrawable();

    if (DEBUG)
      Log.v(TAG, "syncWithService color " + Integer.toHexString(color) + " drawable " + drawable);

    if (drawable != null) {
      drawable = drawable.getConstantState().newDrawable(mContext.getResources()).mutate();
    }

    mBackgroundColor = color;
    mBackgroundDrawable = drawable;

    updateImmediate();
  }
  /**
   * Set the background to the given color. The timing for when this becomes visible in the app is
   * undefined and may take place after a small delay.
   */
  public void setColor(int color) {
    if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color));

    mBackgroundColor = color;
    mService.setColor(mBackgroundColor);

    if (mColorWrapper != null) {
      mColorWrapper.setColor(mBackgroundColor);
    }
  }
 /** Synchronizes state when the owning Activity is resumed. */
 void onActivityResume() {
   if (mService == null) {
     return;
   }
   if (mLayerDrawable == null) {
     if (DEBUG) Log.v(TAG, "onActivityResume: released state, syncing with service");
     syncWithService();
   } else {
     if (DEBUG)
       Log.v(
           TAG,
           "onActivityResume: updating service color "
               + mBackgroundColor
               + " drawable "
               + mBackgroundDrawable);
     mService.setColor(mBackgroundColor);
     mService.setDrawable(mBackgroundDrawable);
   }
 }
  /**
   * Release references to Drawables and put the BackgroundManager into the detached state. Called
   * when the associated Activity is destroyed.
   *
   * @hide
   */
  void detach() {
    if (DEBUG) Log.v(TAG, "detach");
    release();

    if (mWindowManager != null && mBgView != null) {
      mWindowManager.removeViewImmediate(mBgView);
    }

    mWindowManager = null;
    mWindow = null;
    mBgView = null;
    mAttached = false;

    if (mService != null) {
      mService.unref();
      mService = null;
    }
  }
  /**
   * Construct a BackgroundManager instance. The Initial background is set from the continuity
   * service.
   *
   * @deprecated Use getInstance(Activity).
   */
  @Deprecated
  public BackgroundManager(Activity activity) {
    mContext = activity;
    mService = BackgroundContinuityService.getInstance();
    mHeightPx = mContext.getResources().getDisplayMetrics().heightPixels;
    mWidthPx = mContext.getResources().getDisplayMetrics().widthPixels;
    mHandler = new Handler();

    TypedArray ta =
        activity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
    mThemeDrawableResourceId = ta.getResourceId(0, -1);
    if (mThemeDrawableResourceId < 0) {
      if (DEBUG) Log.v(TAG, "BackgroundManager no window background resource!");
    }
    ta.recycle();

    createFragment(activity);
  }
  /**
   * Set the given bitmap into the background. When using setBitmap to set the background, the
   * provided bitmap will be scaled and cropped to correctly fit within the dimensions of the view.
   * The timing for when this becomes visible in the app is undefined and may take place after a
   * small delay.
   */
  public void setBitmap(Bitmap bitmap) {
    if (DEBUG) {
      Log.v(TAG, "setBitmap " + bitmap);
    }

    if (bitmap == null) {
      setDrawableInternal(null);
      return;
    }

    if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
      if (DEBUG) {
        Log.v(TAG, "invalid bitmap width or height");
      }
      return;
    }

    if (mBackgroundDrawable instanceof BitmapDrawable
        && ((BitmapDrawable) mBackgroundDrawable).getBitmap() == bitmap) {
      if (DEBUG) {
        Log.v(TAG, "same bitmap detected");
      }
      mService.setDrawable(mBackgroundDrawable);
      return;
    }

    if (SCALE_BITMAPS_TO_FIT
        && (bitmap.getWidth() != mWidthPx || bitmap.getHeight() != mHeightPx)) {
      // Scale proportionately to fit width and height.

      Matrix matrix = new Matrix();

      int dwidth = bitmap.getWidth();
      int dheight = bitmap.getHeight();
      float scale;
      int dx;

      if (DEBUG) {
        Log.v(TAG, "original image size " + dwidth + "x" + dheight);
      }

      if (dwidth * mHeightPx > mWidthPx * dheight) {
        scale = (float) mHeightPx / (float) dheight;
      } else {
        scale = (float) mWidthPx / (float) dwidth;
      }

      matrix.setScale(scale, scale);

      if (DEBUG) {
        Log.v(TAG, "original image size " + bitmap.getWidth() + "x" + bitmap.getHeight());
      }
      int subX = Math.min((int) (mWidthPx / scale), dwidth);
      int subY = Math.min((int) (mHeightPx / scale), dheight);
      dx = Math.max(0, (dwidth - subX) / 2);

      bitmap = Bitmap.createBitmap(bitmap, dx, 0, subX, subY, matrix, true);
      if (DEBUG) {
        Log.v(TAG, "new image size " + bitmap.getWidth() + "x" + bitmap.getHeight());
      }
    }

    BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap);

    setDrawableInternal(bitmapDrawable);
  }