public ScreenRotationAnimation(
      Context context,
      SurfaceSession session,
      boolean inTransaction,
      int originalWidth,
      int originalHeight,
      int originalRotation) {
    mContext = context;

    // Screenshot does NOT include rotation!
    // Allow for abnormal hardware orientation
    mSnapshotRotation = (4 - android.os.SystemProperties.getInt("ro.sf.hwrotation", 0) / 90) % 4;
    if (mSnapshotRotation == Surface.ROTATION_0 || mSnapshotRotation == Surface.ROTATION_180) {
      if (originalRotation == Surface.ROTATION_90 || originalRotation == Surface.ROTATION_270) {
        mWidth = originalHeight;
        mHeight = originalWidth;
      } else {
        mWidth = originalWidth;
        mHeight = originalHeight;
      }
    } else {
      if (originalRotation == Surface.ROTATION_90 || originalRotation == Surface.ROTATION_270) {
        mWidth = originalWidth;
        mHeight = originalHeight;
      } else {
        mWidth = originalHeight;
        mHeight = originalWidth;
      }
    }

    mOriginalRotation = originalRotation;
    mOriginalWidth = originalWidth;
    mOriginalHeight = originalHeight;

    if (!inTransaction) {
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
        Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation");
      Surface.openTransaction();
    }

    try {
      try {
        mSurface =
            new Surface(
                session,
                0,
                "FreezeSurface",
                -1,
                mWidth,
                mHeight,
                PixelFormat.OPAQUE,
                Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
        if (mSurface == null || !mSurface.isValid()) {
          // Screenshot failed, punt.
          mSurface = null;
          return;
        }
        mSurface.setLayer(FREEZE_LAYER + 1);
        mSurface.show();
      } catch (Surface.OutOfResourcesException e) {
        Slog.w(TAG, "Unable to allocate freeze surface", e);
      }

      if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.SHOW_SURFACE_ALLOC)
        Slog.i(WindowManagerService.TAG, "  FREEZE " + mSurface + ": CREATE");

      setRotation(originalRotation);
    } finally {
      if (!inTransaction) {
        Surface.closeTransaction();
        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
          Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION ScreenRotationAnimation");
      }
    }
  }
  /** Returns true if animating. */
  public boolean dismiss(
      SurfaceSession session,
      long maxAnimationDuration,
      float animationScale,
      int finalWidth,
      int finalHeight) {
    if (mSurface == null) {
      // Can't do animation.
      return false;
    }

    // Figure out how the screen has moved from the original rotation.
    int delta = deltaRotation(mCurRotation, mOriginalRotation);

    switch (delta) {
      case Surface.ROTATION_0:
        mExitAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_0_exit);
        mEnterAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_0_enter);
        break;
      case Surface.ROTATION_90:
        mExitAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_plus_90_exit);
        mEnterAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_plus_90_enter);
        break;
      case Surface.ROTATION_180:
        mExitAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_180_exit);
        mEnterAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_180_enter);
        break;
      case Surface.ROTATION_270:
        mExitAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_minus_90_exit);
        mEnterAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_minus_90_enter);
        break;
    }

    // Initialize the animations.  This is a hack, redefining what "parent"
    // means to allow supplying the last and next size.  In this definition
    // "%p" is the original (let's call it "previous") size, and "%" is the
    // screen's current/new size.
    mEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    mExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    mStarted = false;

    mExitAnimation.restrictDuration(maxAnimationDuration);
    mExitAnimation.scaleCurrentDuration(animationScale);
    mEnterAnimation.restrictDuration(maxAnimationDuration);
    mEnterAnimation.scaleCurrentDuration(animationScale);

    if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
      Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation.dismiss");
    Surface.openTransaction();

    try {
      Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2);
      Rect inner = new Rect(0, 0, finalWidth, finalHeight);
      mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
    } catch (Surface.OutOfResourcesException e) {
      Slog.w(TAG, "Unable to allocate black surface", e);
    } finally {
      Surface.closeTransaction();
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
        Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION ScreenRotationAnimation.dismiss");
    }

    return true;
  }
  public ScreenRotationAnimation(
      Context context,
      Display display,
      SurfaceSession session,
      boolean inTransaction,
      int originalWidth,
      int originalHeight,
      int originalRotation,
      int exitAnim,
      int enterAnim) {
    mContext = context;
    mDisplay = display;
    mExitAnimId = exitAnim;
    mEnterAnimId = enterAnim;

    // Screenshot does NOT include rotation!
    if (originalRotation == Surface.ROTATION_90 || originalRotation == Surface.ROTATION_270) {
      mWidth = originalHeight;
      mHeight = originalWidth;
    } else {
      mWidth = originalWidth;
      mHeight = originalHeight;
    }

    mOriginalRotation = originalRotation;
    mOriginalWidth = originalWidth;
    mOriginalHeight = originalHeight;

    if (!inTransaction) {
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
        Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation");
      Surface.openTransaction();
    }

    try {
      try {
        if (WindowManagerService.DEBUG_SURFACE_TRACE) {
          mSurface =
              new SurfaceTrace(
                  session,
                  "FreezeSurface",
                  mWidth,
                  mHeight,
                  PixelFormat.OPAQUE,
                  Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
        } else {
          mSurface =
              new Surface(
                  session,
                  "FreezeSurface",
                  mWidth,
                  mHeight,
                  PixelFormat.OPAQUE,
                  Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
        }
        if (!mSurface.isValid()) {
          // Screenshot failed, punt.
          mSurface = null;
          return;
        }
        mSurface.setLayerStack(mDisplay.getLayerStack());
        mSurface.setLayer(FREEZE_LAYER + 1);
        mSurface.setAlpha(0);
        mSurface.show();
      } catch (Surface.OutOfResourcesException e) {
        Slog.w(TAG, "Unable to allocate freeze surface", e);
      }

      /// M: Add systrace for orientation chagnge performance analysis
      Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "ScreenRotationAnimation:Create");
      Slog.i(WindowManagerService.TAG, "  FREEZE " + mSurface + ": CREATE");
      Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);

      setRotationInTransaction(originalRotation);
    } finally {
      if (!inTransaction) {
        Surface.closeTransaction();
        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS)
          Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION ScreenRotationAnimation");
      }
    }
  }
  /** Returns true if animating. */
  private boolean startAnimation(
      SurfaceSession session,
      long maxAnimationDuration,
      float animationScale,
      int finalWidth,
      int finalHeight,
      boolean dismissing) {
    if (mSurface == null) {
      // Can't do animation.
      return false;
    }
    if (mStarted) {
      return true;
    }

    mStarted = true;

    boolean firstStart = false;

    // Figure out how the screen has moved from the original rotation.
    int delta = deltaRotation(mCurRotation, mOriginalRotation);

    if (TWO_PHASE_ANIMATION
        && mFinishExitAnimation == null
        && (!dismissing || delta != Surface.ROTATION_0)) {
      if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations");
      firstStart = true;
      mStartExitAnimation =
          AnimationUtils.loadAnimation(
              mContext, com.android.internal.R.anim.screen_rotate_start_exit);
      mStartEnterAnimation =
          AnimationUtils.loadAnimation(
              mContext, com.android.internal.R.anim.screen_rotate_start_enter);
      if (USE_CUSTOM_BLACK_FRAME) {
        mStartFrameAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_start_frame);
      }
      mFinishExitAnimation =
          AnimationUtils.loadAnimation(
              mContext, com.android.internal.R.anim.screen_rotate_finish_exit);
      mFinishEnterAnimation =
          AnimationUtils.loadAnimation(
              mContext, com.android.internal.R.anim.screen_rotate_finish_enter);
      if (USE_CUSTOM_BLACK_FRAME) {
        mFinishFrameAnimation =
            AnimationUtils.loadAnimation(
                mContext, com.android.internal.R.anim.screen_rotate_finish_frame);
      }
    }

    if (DEBUG_STATE)
      Slog.v(
          TAG,
          "Rotation delta: "
              + delta
              + " finalWidth="
              + finalWidth
              + " finalHeight="
              + finalHeight
              + " origWidth="
              + mOriginalWidth
              + " origHeight="
              + mOriginalHeight);

    final boolean customAnim;
    if (mExitAnimId != 0 && mEnterAnimId != 0) {
      customAnim = true;
      mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, mExitAnimId);
      mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, mEnterAnimId);
    } else {
      customAnim = false;
      switch (delta) {
        case Surface.ROTATION_0:
          mRotateExitAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_0_exit);
          mRotateEnterAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_0_enter);
          if (USE_CUSTOM_BLACK_FRAME) {
            mRotateFrameAnimation =
                AnimationUtils.loadAnimation(
                    mContext, com.android.internal.R.anim.screen_rotate_0_frame);
          }
          break;
        case Surface.ROTATION_90:
          mRotateExitAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_plus_90_exit);
          mRotateEnterAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_plus_90_enter);
          if (USE_CUSTOM_BLACK_FRAME) {
            mRotateFrameAnimation =
                AnimationUtils.loadAnimation(
                    mContext, com.android.internal.R.anim.screen_rotate_plus_90_frame);
          }
          break;
        case Surface.ROTATION_180:
          mRotateExitAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_180_exit);
          mRotateEnterAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_180_enter);
          if (USE_CUSTOM_BLACK_FRAME) {
            mRotateFrameAnimation =
                AnimationUtils.loadAnimation(
                    mContext, com.android.internal.R.anim.screen_rotate_180_frame);
          }
          break;
        case Surface.ROTATION_270:
          mRotateExitAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_minus_90_exit);
          mRotateEnterAnimation =
              AnimationUtils.loadAnimation(
                  mContext, com.android.internal.R.anim.screen_rotate_minus_90_enter);
          if (USE_CUSTOM_BLACK_FRAME) {
            mRotateFrameAnimation =
                AnimationUtils.loadAnimation(
                    mContext, com.android.internal.R.anim.screen_rotate_minus_90_frame);
          }
          break;
      }
    }

    // Initialize the animations.  This is a hack, redefining what "parent"
    // means to allow supplying the last and next size.  In this definition
    // "%p" is the original (let's call it "previous") size, and "%" is the
    // screen's current/new size.
    if (TWO_PHASE_ANIMATION && firstStart) {
      // Compute partial steps between original and final sizes.  These
      // are used for the dimensions of the exiting and entering elements,
      // so they are never stretched too significantly.
      final int halfWidth = (finalWidth + mOriginalWidth) / 2;
      final int halfHeight = (finalHeight + mOriginalHeight) / 2;

      if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
      mStartEnterAnimation.initialize(finalWidth, finalHeight, halfWidth, halfHeight);
      mStartExitAnimation.initialize(halfWidth, halfHeight, mOriginalWidth, mOriginalHeight);
      mFinishEnterAnimation.initialize(finalWidth, finalHeight, halfWidth, halfHeight);
      mFinishExitAnimation.initialize(halfWidth, halfHeight, mOriginalWidth, mOriginalHeight);
      if (USE_CUSTOM_BLACK_FRAME) {
        mStartFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
        mFinishFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
      }
    }
    mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    if (USE_CUSTOM_BLACK_FRAME) {
      mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    }
    mAnimRunning = false;
    mFinishAnimReady = false;
    mFinishAnimStartTime = -1;

    if (TWO_PHASE_ANIMATION && firstStart) {
      mStartExitAnimation.restrictDuration(maxAnimationDuration);
      mStartExitAnimation.scaleCurrentDuration(animationScale);
      mStartEnterAnimation.restrictDuration(maxAnimationDuration);
      mStartEnterAnimation.scaleCurrentDuration(animationScale);
      mFinishExitAnimation.restrictDuration(maxAnimationDuration);
      mFinishExitAnimation.scaleCurrentDuration(animationScale);
      mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
      mFinishEnterAnimation.scaleCurrentDuration(animationScale);
      if (USE_CUSTOM_BLACK_FRAME) {
        mStartFrameAnimation.restrictDuration(maxAnimationDuration);
        mStartFrameAnimation.scaleCurrentDuration(animationScale);
        mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
        mFinishFrameAnimation.scaleCurrentDuration(animationScale);
      }
    }
    mRotateExitAnimation.restrictDuration(maxAnimationDuration);
    mRotateExitAnimation.scaleCurrentDuration(animationScale);
    mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
    mRotateEnterAnimation.scaleCurrentDuration(animationScale);
    if (USE_CUSTOM_BLACK_FRAME) {
      mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
      mRotateFrameAnimation.scaleCurrentDuration(animationScale);
    }

    final int layerStack = mDisplay.getLayerStack();
    if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
        Slog.i(
            WindowManagerService.TAG,
            ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
      Surface.openTransaction();

      // Compute the transformation matrix that must be applied
      // the the black frame to make it stay in the initial position
      // before the new screen rotation.  This is different than the
      // snapshot transformation because the snapshot is always based
      // of the native orientation of the screen, not the orientation
      // we were last in.
      createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);

      try {
        Rect outer =
            new Rect(
                -mOriginalWidth * 1, -mOriginalHeight * 1, mOriginalWidth * 2, mOriginalHeight * 2);
        Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
        mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3, layerStack);
        mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
      } catch (Surface.OutOfResourcesException e) {
        Slog.w(TAG, "Unable to allocate black surface", e);
      } finally {
        Surface.closeTransaction();
        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
          Slog.i(
              WindowManagerService.TAG,
              "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
      }
    }

    if (!customAnim && mExitingBlackFrame == null) {
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
        Slog.i(
            WindowManagerService.TAG,
            ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
      Surface.openTransaction();
      try {
        // Compute the transformation matrix that must be applied
        // the the black frame to make it stay in the initial position
        // before the new screen rotation.  This is different than the
        // snapshot transformation because the snapshot is always based
        // of the native orientation of the screen, not the orientation
        // we were last in.
        createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);

        Rect outer =
            new Rect(
                -mOriginalWidth * 1, -mOriginalHeight * 1, mOriginalWidth * 2, mOriginalHeight * 2);
        Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
        mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2, layerStack);
        mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
      } catch (Surface.OutOfResourcesException e) {
        Slog.w(TAG, "Unable to allocate black surface", e);
      } finally {
        Surface.closeTransaction();
        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
          Slog.i(
              WindowManagerService.TAG,
              "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
      }
    }

    if (customAnim && mEnteringBlackFrame == null) {
      if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
        Slog.i(
            WindowManagerService.TAG,
            ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
      Surface.openTransaction();

      try {
        Rect outer = new Rect(-finalWidth * 1, -finalHeight * 1, finalWidth * 2, finalHeight * 2);
        Rect inner = new Rect(0, 0, finalWidth, finalHeight);
        mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER, layerStack);
      } catch (Surface.OutOfResourcesException e) {
        Slog.w(TAG, "Unable to allocate black surface", e);
      } finally {
        Surface.closeTransaction();
        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE)
          Slog.i(
              WindowManagerService.TAG,
              "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
      }
    }

    return true;
  }
Пример #5
0
  synchronized void animate() {
    mPendingLayoutChanges = 0;
    mCurrentTime = SystemClock.uptimeMillis();
    mBulkUpdateParams = 0;
    boolean wasAnimating = mAnimating;
    mAnimating = false;
    if (WindowManagerService.DEBUG_WINDOW_TRACE) {
      Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
    }

    // Update animations of all applications, including those
    // associated with exiting/removed apps
    Surface.openTransaction();

    try {
      updateWindowsAppsAndRotationAnimationsLocked();
      performAnimationsLocked();
      testWallpaperAndBackgroundLocked();

      // THIRD LOOP: Update the surfaces of all windows.

      if (mScreenRotationAnimation != null) {
        mScreenRotationAnimation.updateSurfaces();
      }

      final int N = mWinAnimators.size();
      for (int i = 0; i < N; i++) {
        mWinAnimators.get(i).prepareSurfaceLocked(true);
      }

      if (mDimParams != null) {
        mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
      }
      if (mDimAnimator != null && mDimAnimator.mDimShown) {
        mAnimating |=
            mDimAnimator.updateSurface(isDimming(), mCurrentTime, !mService.okToDisplay());
      }

      if (mService.mBlackFrame != null) {
        if (mScreenRotationAnimation != null) {
          mService.mBlackFrame.setMatrix(
              mScreenRotationAnimation.getEnterTransformation().getMatrix());
        } else {
          mService.mBlackFrame.clearMatrix();
        }
      }

      if (mService.mWatermark != null) {
        mService.mWatermark.drawIfNeeded();
      }
    } catch (RuntimeException e) {
      Log.wtf(TAG, "Unhandled exception in Window Manager", e);
    } finally {
      Surface.closeTransaction();
    }

    mService.bulkSetParameters(mBulkUpdateParams, mPendingLayoutChanges);

    if (mAnimating) {
      mService.scheduleAnimationLocked();
    } else if (wasAnimating) {
      mService.requestTraversalLocked();
    }
    if (WindowManagerService.DEBUG_WINDOW_TRACE) {
      Slog.i(
          TAG,
          "!!! animate: exit mAnimating="
              + mAnimating
              + " mBulkUpdateParams="
              + Integer.toHexString(mBulkUpdateParams)
              + " mPendingLayoutChanges="
              + Integer.toHexString(mPendingLayoutChanges));
    }
  }