public boolean stepAnimation(long now) {
    if (mEnterAnimation == null && mExitAnimation == null) {
      return false;
    }

    if (!mStarted) {
      if (mEnterAnimation != null) {
        mEnterAnimation.setStartTime(now);
      }
      if (mExitAnimation != null) {
        mExitAnimation.setStartTime(now);
      }
      mStarted = true;
    }

    mExitTransformation.clear();
    boolean moreExit = false;
    if (mExitAnimation != null) {
      moreExit = mExitAnimation.getTransformation(now, mExitTransformation);
      if (DEBUG) Slog.v(TAG, "Stepped exit: " + mExitTransformation);
      if (!moreExit) {
        if (DEBUG) Slog.v(TAG, "Exit animation done!");
        mExitAnimation.cancel();
        mExitAnimation = null;
        mExitTransformation.clear();
        if (mSurface != null) {
          mSurface.hide();
        }
      }
    }

    mEnterTransformation.clear();
    boolean moreEnter = false;
    if (mEnterAnimation != null) {
      moreEnter = mEnterAnimation.getTransformation(now, mEnterTransformation);
      if (!moreEnter) {
        mEnterAnimation.cancel();
        mEnterAnimation = null;
        mEnterTransformation.clear();
        if (mBlackFrame != null) {
          mBlackFrame.hide();
        }
      } else {
        if (mBlackFrame != null) {
          mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
        }
      }
    }

    mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
    setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());

    return moreEnter || moreExit;
  }
 public void kill() {
   if (mSurface != null) {
     if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.SHOW_SURFACE_ALLOC)
       Slog.i(WindowManagerService.TAG, "  FREEZE " + mSurface + ": DESTROY");
     mSurface.destroy();
     mSurface = null;
   }
   if (mBlackFrame != null) {
     mBlackFrame.kill();
   }
   if (mExitAnimation != null) {
     mExitAnimation.cancel();
     mExitAnimation = null;
   }
   if (mEnterAnimation != null) {
     mEnterAnimation.cancel();
     mEnterAnimation = null;
   }
 }
  void updateSurfacesInTransaction() {
    if (!mStarted) {
      return;
    }

    if (mSurface != null) {
      if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
        if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
        mSurface.hide();
      }
    }

    if (mCustomBlackFrame != null) {
      if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
        if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
        mCustomBlackFrame.hide();
      } else {
        mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
      }
    }

    if (mExitingBlackFrame != null) {
      if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
        if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
        mExitingBlackFrame.hide();
      } else {
        mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
        mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
      }
    }

    if (mEnteringBlackFrame != null) {
      if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
        if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
        mEnteringBlackFrame.hide();
      } else {
        mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
      }
    }

    setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
  }
 public void kill() {
   if (DEBUG_STATE) Slog.v(TAG, "Kill!");
   if (mSurface != null) {
     /// M: Add systrace for orientation chagnge performance analysis
     Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "ScreenRotationAnimation:End");
     Slog.i(WindowManagerService.TAG, "  FREEZE " + mSurface + ": DESTROY");
     Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     mSurface.destroy();
     mSurface = null;
   }
   if (mCustomBlackFrame != null) {
     mCustomBlackFrame.kill();
     mCustomBlackFrame = null;
   }
   if (mExitingBlackFrame != null) {
     mExitingBlackFrame.kill();
     mExitingBlackFrame = null;
   }
   if (mEnteringBlackFrame != null) {
     mEnteringBlackFrame.kill();
     mEnteringBlackFrame = null;
   }
   if (TWO_PHASE_ANIMATION) {
     if (mStartExitAnimation != null) {
       mStartExitAnimation.cancel();
       mStartExitAnimation = null;
     }
     if (mStartEnterAnimation != null) {
       mStartEnterAnimation.cancel();
       mStartEnterAnimation = null;
     }
     if (mFinishExitAnimation != null) {
       mFinishExitAnimation.cancel();
       mFinishExitAnimation = null;
     }
     if (mFinishEnterAnimation != null) {
       mFinishEnterAnimation.cancel();
       mFinishEnterAnimation = null;
     }
   }
   if (USE_CUSTOM_BLACK_FRAME) {
     if (mStartFrameAnimation != null) {
       mStartFrameAnimation.cancel();
       mStartFrameAnimation = null;
     }
     if (mRotateFrameAnimation != null) {
       mRotateFrameAnimation.cancel();
       mRotateFrameAnimation = null;
     }
     if (mFinishFrameAnimation != null) {
       mFinishFrameAnimation.cancel();
       mFinishFrameAnimation = null;
     }
   }
   if (mRotateExitAnimation != null) {
     mRotateExitAnimation.cancel();
     mRotateExitAnimation = null;
   }
   if (mRotateEnterAnimation != null) {
     mRotateEnterAnimation.cancel();
     mRotateEnterAnimation = null;
   }
 }
  /** 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;
  }
 public void printTo(String prefix, PrintWriter pw) {
   pw.print(prefix);
   pw.print("mSurface=");
   pw.print(mSurface);
   pw.print(" mWidth=");
   pw.print(mWidth);
   pw.print(" mHeight=");
   pw.println(mHeight);
   if (USE_CUSTOM_BLACK_FRAME) {
     pw.print(prefix);
     pw.print("mCustomBlackFrame=");
     pw.println(mCustomBlackFrame);
     if (mCustomBlackFrame != null) {
       mCustomBlackFrame.printTo(prefix + "  ", pw);
     }
   }
   pw.print(prefix);
   pw.print("mExitingBlackFrame=");
   pw.println(mExitingBlackFrame);
   if (mExitingBlackFrame != null) {
     mExitingBlackFrame.printTo(prefix + "  ", pw);
   }
   pw.print(prefix);
   pw.print("mEnteringBlackFrame=");
   pw.println(mEnteringBlackFrame);
   if (mEnteringBlackFrame != null) {
     mEnteringBlackFrame.printTo(prefix + "  ", pw);
   }
   pw.print(prefix);
   pw.print("mCurRotation=");
   pw.print(mCurRotation);
   pw.print(" mOriginalRotation=");
   pw.println(mOriginalRotation);
   pw.print(prefix);
   pw.print("mOriginalWidth=");
   pw.print(mOriginalWidth);
   pw.print(" mOriginalHeight=");
   pw.println(mOriginalHeight);
   pw.print(prefix);
   pw.print("mStarted=");
   pw.print(mStarted);
   pw.print(" mAnimRunning=");
   pw.print(mAnimRunning);
   pw.print(" mFinishAnimReady=");
   pw.print(mFinishAnimReady);
   pw.print(" mFinishAnimStartTime=");
   pw.println(mFinishAnimStartTime);
   pw.print(prefix);
   pw.print("mStartExitAnimation=");
   pw.print(mStartExitAnimation);
   pw.print(" ");
   mStartExitTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mStartEnterAnimation=");
   pw.print(mStartEnterAnimation);
   pw.print(" ");
   mStartEnterTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mStartFrameAnimation=");
   pw.print(mStartFrameAnimation);
   pw.print(" ");
   mStartFrameTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mFinishExitAnimation=");
   pw.print(mFinishExitAnimation);
   pw.print(" ");
   mFinishExitTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mFinishEnterAnimation=");
   pw.print(mFinishEnterAnimation);
   pw.print(" ");
   mFinishEnterTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mFinishFrameAnimation=");
   pw.print(mFinishFrameAnimation);
   pw.print(" ");
   mFinishFrameTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mRotateExitAnimation=");
   pw.print(mRotateExitAnimation);
   pw.print(" ");
   mRotateExitTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mRotateEnterAnimation=");
   pw.print(mRotateEnterAnimation);
   pw.print(" ");
   mRotateEnterTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mRotateFrameAnimation=");
   pw.print(mRotateFrameAnimation);
   pw.print(" ");
   mRotateFrameTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mExitTransformation=");
   mExitTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mEnterTransformation=");
   mEnterTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mFrameTransformation=");
   mEnterTransformation.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mFrameInitialMatrix=");
   mFrameInitialMatrix.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mSnapshotInitialMatrix=");
   mSnapshotInitialMatrix.printShortString(pw);
   pw.print(" mSnapshotFinalMatrix=");
   mSnapshotFinalMatrix.printShortString(pw);
   pw.println();
   pw.print(prefix);
   pw.print("mExitFrameFinalMatrix=");
   mExitFrameFinalMatrix.printShortString(pw);
   pw.println();
 }