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; }
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)); } }