1.android 横竖屏切换上层从HdmiSettings.java 开始。我们从这里开始分析。

路径:packages\apps\Settings\src\com\android\settings\HdmiSettings.java

mHdmiResolution.setOnPreferenceClickListener(this);public boolean onPreferenceChange(Preference preference, Object obj) {Log.i(TAG, "onPreferenceChange:" + obj);String key = preference.getKey();Log.d(TAG, key);if(preference == mHdmiResolution) {if (KEY_HDMI_RESOLUTION.equals(key)) {if (obj.equals(mOldResolution))return true;int index = mHdmiResolution.findIndexOfValue((String) obj);Log.i(TAG, "onPreferenceChange: index= " + index);mDisplayInfo = getDisplayInfo();if (mDisplayInfo != null) {DrmDisplaySetting.setDisplayModeTemp(mDisplayInfo, index);showConfirmSetModeDialog();}}} else if (preference == mHdmiRotation) {if (KEY_HDMI_ROTATION.equals(key)) {try {int value = Integer.parseInt((String) obj);android.os.SystemProperties.set("persist.sys.orientation", (String) obj);Log.d(TAG,"freezeRotation~~~value:"+(String) obj);if(value == 0)wm.freezeRotation(Surface.ROTATION_0);else if(value == 90)wm.freezeRotation(Surface.ROTATION_90);else if(value == 180)wm.freezeRotation(Surface.ROTATION_180);else if(value == 270)wm.freezeRotation(Surface.ROTATION_270);elsereturn true;//android.os.SystemProperties.set("sys.boot_completed", "1");} catch (Exception e) {Log.e(TAG, "freezeRotation error");}}} else if (preference == mHdmiDualScreen) {android.provider.Settings.System.putInt(getActivity().getContentResolver(),DOUBLE_SCREEN_CONFIG,(Boolean)obj?1:0);SystemProperties.set("persist.orientation.vhinit", "0");SystemProperties.set("persist.orientation.vhshow", "false");mHdmiDualScreenVH.setEnabled((Boolean)obj);mHdmiDualScreenVH.setChecked(false);mHdmiDualScreenList.setEnabled(false);this.finish();} else if (preference == mHdmiDualScreenVH) {if((Boolean)obj) {SystemProperties.set("persist.orientation.vhshow", "true");   mHdmiDualScreenList.setEnabled(true);} else {SystemProperties.set("persist.orientation.vhshow", "false");   mHdmiDualScreenList.setEnabled(false);SystemProperties.set("persist.orientation.vhinit", "0");}SystemProperties.set("persist.orientation.vhinit", "0");} else if (preference == mHdmiDualScreenList) {if("0".equals(obj.toString())) {SystemProperties.set("persist.orientation.vhinit", "0");} else if ("1".equals(obj.toString())) {SystemProperties.set("persist.orientation.vhinit", "1");}}return true;}

2. 主要调用了wm.freezeRotation(Surface.ROTATION_0); 这个函数,通过WMS实现。

wm = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));

3.跨进程访问服务AIDL

路径:frameworks\base\core\java\android\view\IWindowManager.aidl

interface IWindowManager
{ /*** Lock the device orientation to the specified rotation, or to the* current rotation if -1.  Sensor input will be ignored until* thawRotation() is called.* @hide*/void freezeRotation(int rotation);
}

4.AIDL(Android Interface Definition Language)具体实现的方法类

路径:frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

enable  “Auto-rotate screen” 则调用public void freezeRotation(int rotation),disable “Auto-rotate screen” 则调用public void thawRotation() 。

    public void freezeRotation(int rotation) {if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,"freezeRotation()")) {throw new SecurityException("Requires SET_ORIENTATION permission");}if (rotation < -1 || rotation > Surface.ROTATION_270) {throw new IllegalArgumentException("Rotation argument must be -1 or a valid "+ "rotation constant.");}if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation);long origId = Binder.clearCallingIdentity();try {mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,rotation == -1 ? mRotation : rotation);} finally {Binder.restoreCallingIdentity(origId);}updateRotationUnchecked(false, false);}/*** Thaw rotation changes.  (Disable "rotation lock".)* Persists across reboots.*/@Overridepublic void thawRotation() {if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,"thawRotation()")) {throw new SecurityException("Requires SET_ORIENTATION permission");}if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation);long origId = Binder.clearCallingIdentity();try {mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,777); // rot not used} finally {Binder.restoreCallingIdentity(origId);}//关键函数updateRotationUnchecked(false, false);}public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("+ "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");long origId = Binder.clearCallingIdentity();boolean changed;synchronized(mWindowMap) {//更新方向changed = updateRotationUncheckedLocked(false);if (!changed || forceRelayout) {getDefaultDisplayContentLocked().layoutNeeded = true;//屏幕绘制mWindowPlacerLocked.performSurfacePlacement();}}if (changed || alwaysSendConfiguration) {//发送新配置sendNewConfiguration();}Binder.restoreCallingIdentity(origId);}//更新rotation 横转直最核心的codepublic boolean updateRotationUncheckedLocked(boolean inTransaction) {/** 调用函数pauseRotationLocked() mDeferredRotationPauseCount + 1* 调用函数resumeRotationLocked() mDeferredRotationPauseCount - 1               * 调用 updateRotationUncheckedLocked() 将 change rotation*/if (mDeferredRotationPauseCount > 0) {// Rotation updates have been paused temporarily.  Defer the update until// updates have been resumed.if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");return false;}//如果上一次动画未完成,则不进行旋转操作ScreenRotationAnimation screenRotationAnimation =mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {// Rotation updates cannot be performed while the previous rotation change// animation is still in progress.  Skip this update.  We will try updating// again after the animation is finished and the display is unfrozen.if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");return false;}//即使屏幕旋转动画已经完成,仍然有一段时间我们还没有解冻显示。需要中止旋转。if (mDisplayFrozen) {// Even if the screen rotation animation has finished (e.g. isAnimating// returns false), there is still some time where we haven't yet unfrozen// the display. We also need to abort rotation here.if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, still finishing previous rotation");return false;}//如果不启用显示,也无需进行旋转操作if (!mDisplayEnabled) {// No point choosing a rotation if the display is not enabled.if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");return false;}final DisplayContent displayContent = getDefaultDisplayContentLocked();final WindowList windows = displayContent.getWindowList();final int oldRotation = mRotation;//根据传感器综合计算出屏幕方向int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, rotation);//处理判断是否可以无缝旋转if (rotateSeamlessly) {for (int i = windows.size() - 1; i >= 0; i--) {WindowState w = windows.get(i);// We can't rotate (seamlessly or not) while waiting for the last seamless rotation// to complete (that is, waiting for windows to redraw). It's tempting to check// w.mSeamlessRotationCount but that could be incorrect in the case of window-removal.if (w.mSeamlesslyRotated) {return false;}// In what can only be called an unfortunate workaround we require// seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE// flag. Due to limitations in the client API, there is no way for// the client to set this flag in a race free fashion. If we seamlessly rotate// a window which does not have this flag, but then gains it, we will get// an incorrect visual result (rotated viewfinder). This means if we want to// support seamlessly rotating windows which could gain this flag, we can't// rotate windows without it. This limits seamless rotation in N to camera framework// users, windows without children, and native code. This is unfortunate but// having the camera work is our primary goal.if (w.isChildWindow() & w.isVisibleNow() &&!w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) {rotateSeamlessly = false;}}}// TODO: Implement forced rotation changes.//       Set mAltOrientation to indicate that the application is receiving//       an orientation that has different metrics than it expected.//       eg. Portrait instead of Landscape.boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(mLastOrientation, rotation);if (DEBUG_ORIENTATION) {Slog.v(TAG_WM, "Selected orientation "+ mLastOrientation + ", got rotation " + rotation+ " which has " + (altOrientation ? "incompatible" : "compatible")+ " metrics");}if (mRotateOnBoot) {mRotation = Surface.ROTATION_0;rotation = Surface.ROTATION_90;}if (mRotation == rotation && mAltOrientation == altOrientation) {// No change.return false;}if (DEBUG_ORIENTATION) {Slog.v(TAG_WM,"Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")+ " from " + mRotation + (mAltOrientation ? " (alt)" : "")+ ", lastOrientation=" + mLastOrientation);}//获取新的rotation ,传给PhoneWindowManagermRotation = rotation;mAltOrientation = altOrientation;mPolicy.setRotationLw(mRotation);//发送WINDOW_FREEZE_TIMEOUT消息mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);if (mFirstRotate) {mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 5000);mFirstRotate = false;} else {mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);}mWaitingForConfig = true;displayContent.layoutNeeded = true;final int[] anim = new int[2];if (displayContent.isDimming()) {anim[0] = anim[1] = 0;} else {//在PhoneWindowManager中判断进入还是退出转屏动画操作mPolicy.selectRotationAnimationLw(anim);}//如果是Seamlessly则无旋转动画,因Seamlessly目前不支持旋转动画if (!rotateSeamlessly) {startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);// startFreezingDisplayLocked can reset the ScreenRotationAnimation.screenRotationAnimation =mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);} else {// The screen rotation animation uses a screenshot to freeze the screen// while windows resize underneath.// When we are rotating seamlessly, we allow the elements to transition// to their rotated state independently and without a freeze required.screenRotationAnimation = null;// We have to reset this in case a window was removed before it// finished seamless rotation.mSeamlessRotationCount = 0;}boolean isDelay = true;//(("true".equals(SystemProperties.get("ro.config.low_ram", "false")))||("true".equals(SystemProperties.get("ro.mem_optimise.enable", "false")))) && (!"true".equals(SystemProperties.get("sys.cts_gts.status", "false")));if (mRotateOnBoot) {try {IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");if (surfaceFlinger != null) {Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED !!!!!");Parcel data = Parcel.obtain();data.writeInterfaceToken("android.ui.ISurfaceComposer");surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,data, null, 0);data.recycle();}} catch (RemoteException ex) {Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");}}// We need to update our screen size information to match the new rotation. If the rotation// has actually changed then this method will return true and, according to the comment at// the top of the method, the caller is obligated to call computeNewConfigurationLocked().// By updating the Display info here it will be available to// computeScreenConfigurationLocked later.//根据rotation 去更新DisplayInfoupdateDisplayAndOrientationLocked(mCurConfiguration.uiMode);final DisplayInfo displayInfo = displayContent.getDisplayInfo();if (!inTransaction) {if (SHOW_TRANSACTIONS) {Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");}SurfaceControl.openTransaction();}try {// NOTE: We disable the rotation in the emulator because//       it doesn't support hardware OpenGL emulation yet.//进行屏幕过度旋转动画操作if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null&& screenRotationAnimation.hasScreenshot()) {if (screenRotationAnimation.setRotationInTransaction(rotation, mFxSession,MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),displayInfo.logicalWidth, displayInfo.logicalHeight)) {scheduleAnimationLocked();}}if (rotateSeamlessly) {for (int i = windows.size() - 1; i >= 0; i--) {WindowState w = windows.get(i);w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation);}}mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();} finally {if (!inTransaction) {SurfaceControl.closeTransaction();if (SHOW_LIGHT_TRANSACTIONS) {Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");}}}for (int i = windows.size() - 1; i >= 0; i--) {WindowState w = windows.get(i);// Discard surface after orientation change, these can't be reused.if (w.mAppToken != null) {w.mAppToken.destroySavedSurfaces();}if (w.mHasSurface && !rotateSeamlessly) {if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);w.mOrientationChanging = true;mWindowPlacerLocked.mOrientationChangeComplete = false;w.mLastFreezeDuration = 0;}}if (rotateSeamlessly) {mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION);}for (int i=mRotationWatchers.size()-1; i>=0; i--) {try {mRotationWatchers.get(i).watcher.onRotationChanged(rotation);} catch (RemoteException e) {}}// TODO (multidisplay): Magnification is supported only for the default display.// Announce rotation only if we will not animate as we already have the// windows in final state. Otherwise, we make this call at the rotation end.if (screenRotationAnimation == null && mAccessibilityController != null&& displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),rotation);}return true;}

1)无论 public void freezeRotation(int rotation)还是public void thawRotation() 最终都会调用WindowManagerPolicy.cpp 中提供的接口。

路径:frameworks\base\core\java\android\view\WindowManagerPolicy.java

public interface WindowManagerPolicy {public void selectRotationAnimationLw(int anim[]);public int getUserRotationMode();public void setUserRotationMode(@UserRotationMode int mode, @Surface.Rotation int rotation);...
}

WindowManagerPolicy 接口类的具体实现方法在PhoneWindowManager.java中。

路径:frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java

    public int getUserRotationMode() {return Settings.System.getIntForUser(mContext.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?WindowManagerPolicy.USER_ROTATION_FREE :WindowManagerPolicy.USER_ROTATION_LOCKED;}

2)动画旋转过程

通过截图,制作旋转动画效果,重新绘制横屏转竖屏或者竖屏转横屏的界面,在ScreenRotationAnimation.java 中完成。

路径:frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

screenRotationAnimation.setRotationInTransaction(rotation, mFxSession,MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),displayInfo.logicalWidth, displayInfo.logicalHeight)

在ScreenRotationAnimation.java调用

路径:frameworks\base\services\core\java\com\android\server\wm\ScreenRotationAnimation.java

 //动画旋转的整个过程// Must be called while in a transaction.private void setRotationInTransaction(int rotation) {mCurRotation = rotation;if (DEBUG_STATE) Slog.v(TAG, "navy **** ROTATION: " + rotation);// Compute the transformation matrix that must be applied// to the snapshot to make it stay in the same original position// with the current screen rotation.int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f);}// Must be called while in a transaction.public boolean setRotationInTransaction(int rotation, SurfaceSession session,long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {setRotationInTransaction(rotation);if (TWO_PHASE_ANIMATION) {return startAnimation(session, maxAnimationDuration, animationScale,finalWidth, finalHeight, false, 0, 0);}// Don't start animation yet.return false;}//主要用来计算动画旋转的变换矩阵public static void createRotationMatrix(int rotation, int width, int height,Matrix outMatrix) {switch (rotation) {case Surface.ROTATION_0:outMatrix.reset();break;case Surface.ROTATION_90:outMatrix.setRotate(90, 0, 0);outMatrix.postTranslate(height, 0);break;case Surface.ROTATION_180:outMatrix.setRotate(180, 0, 0);outMatrix.postTranslate(width, height);break;case Surface.ROTATION_270:outMatrix.setRotate(270, 0, 0);outMatrix.postTranslate(0, width);break;}}

在DisplayContent.java比较rotation

路径:frameworks\base\services\core\java\com\android\server\wm\DisplayContent.java

    static int deltaRotation(int oldRotation, int newRotation) {int delta = newRotation - oldRotation;if (delta < 0) delta += 4;return delta;}

3)剖析Matrix 类的实现

路径:frameworks\base\graphics\java\android\graphics\Matrix.java

private static native void native_setRotate(long native_object,float degrees, float px, float py);private static native void native_setRotate(long native_object,float degrees);/*** Set the matrix to rotate by the specified number of degrees, with a pivot* point at (px, py). The pivot point is the coordinate that should remain* unchanged by the specified transformation.*/public void setRotate(float degrees, float px, float py) {native_setRotate(native_instance, degrees, px, py);}/*** Set the matrix to rotate about (0,0) by the specified number of degrees.*/public void setRotate(float degrees) {native_setRotate(native_instance, degrees);}

具体jni 实现方法:

路径:frameworks\base\core\jni\android\graphics\Matrix.cpp

     static void setRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);obj->setRotate(degrees, px, py);}static void setRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);obj->setRotate(degrees);}static const JNINativeMethod methods[] = {{"finalizer", "(J)V", (void*) SkMatrixGlue::finalizer},{"native_create","(J)J", (void*) SkMatrixGlue::create},{"native_isIdentity","!(J)Z", (void*) SkMatrixGlue::isIdentity},{"native_isAffine","!(J)Z", (void*) SkMatrixGlue::isAffine},{"native_rectStaysRect","!(J)Z", (void*) SkMatrixGlue::rectStaysRect},{"native_reset","!(J)V", (void*) SkMatrixGlue::reset},{"native_set","!(JJ)V", (void*) SkMatrixGlue::set},{"native_setTranslate","!(JFF)V", (void*) SkMatrixGlue::setTranslate},{"native_setScale","!(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF},{"native_setScale","!(JFF)V", (void*) SkMatrixGlue::setScale__FF},{"native_setRotate","!(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF},{"native_setRotate","!(JF)V", (void*) SkMatrixGlue::setRotate__F},{"native_setSinCos","!(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF},{"native_setSinCos","!(JFF)V", (void*) SkMatrixGlue::setSinCos__FF},{"native_setSkew","!(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF},{"native_setSkew","!(JFF)V", (void*) SkMatrixGlue::setSkew__FF},{"native_setConcat","!(JJJ)V", (void*) SkMatrixGlue::setConcat},{"native_preTranslate","!(JFF)V", (void*) SkMatrixGlue::preTranslate},{"native_preScale","!(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF},{"native_preScale","!(JFF)V", (void*) SkMatrixGlue::preScale__FF},{"native_preRotate","!(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF},{"native_preRotate","!(JF)V", (void*) SkMatrixGlue::preRotate__F},{"native_preSkew","!(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF},{"native_preSkew","!(JFF)V", (void*) SkMatrixGlue::preSkew__FF},{"native_preConcat","!(JJ)V", (void*) SkMatrixGlue::preConcat},{"native_postTranslate","!(JFF)V", (void*) SkMatrixGlue::postTranslate},{"native_postScale","!(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF},{"native_postScale","!(JFF)V", (void*) SkMatrixGlue::postScale__FF},{"native_postRotate","!(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF},{"native_postRotate","!(JF)V", (void*) SkMatrixGlue::postRotate__F},{"native_postSkew","!(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF},{"native_postSkew","!(JFF)V", (void*) SkMatrixGlue::postSkew__FF},{"native_postConcat","!(JJ)V", (void*) SkMatrixGlue::postConcat},{"native_setRectToRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect},{"native_setPolyToPoly","!(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly},{"native_invert","!(JJ)Z", (void*) SkMatrixGlue::invert},{"native_mapPoints","!(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints},{"native_mapRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z", (void*) SkMatrixGlue::mapRect__RectFRectF},{"native_mapRadius","!(JF)F", (void*) SkMatrixGlue::mapRadius},{"native_getValues","!(J[F)V", (void*) SkMatrixGlue::getValues},{"native_setValues","!(J[F)V", (void*) SkMatrixGlue::setValues},{"native_equals", "!(JJ)Z", (void*) SkMatrixGlue::equals}
};static jfieldID sNativeInstanceField;int register_android_graphics_Matrix(JNIEnv* env) {int result = RegisterMethodsOrDie(env, "android/graphics/Matrix", methods, NELEM(methods));jclass clazz = FindClassOrDie(env, "android/graphics/Matrix");sNativeInstanceField = GetFieldIDOrDie(env, clazz, "native_instance", "J");return result;
}SkMatrix* android_graphics_Matrix_getSkMatrix(JNIEnv* env, jobject matrixObj) {return reinterpret_cast<SkMatrix*>(env->GetLongField(matrixObj, sNativeInstanceField));
}}

函数 static void setRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py);和 函数static void setRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees);中调用SkMatrix.cpp 中的函数。

路径:external\skia\include\core\SkMatrix.h

    /** Set the matrix to rotate by the specified number of degrees, with apivot point at (px, py). The pivot point is the coordinate that shouldremain unchanged by the specified transformation.*/void setRotate(SkScalar degrees, SkScalar px, SkScalar py);/** Set the matrix to rotate about (0,0) by the specified number of degrees.*/void setRotate(SkScalar degrees);

最终的3x3 matrix 来源:

路径:external\skia\src\core\SkMatrix.cpp

void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {fMat[kMScaleX]  = cosV;fMat[kMSkewX]   = -sinV;fMat[kMTransX]  = 0;fMat[kMSkewY]   = sinV;fMat[kMScaleY]  = cosV;fMat[kMTransY]  = 0;fMat[kMPersp0] = fMat[kMPersp1] = 0;fMat[kMPersp2] = 1;this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {SkScalar sinV, cosV;sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);this->setSinCos(sinV, cosV, px, py);
}

rk3288 android7.1 横竖屏切换(动画过度)相关推荐

  1. android横竖屏切换动画,Android应用怎么实现屏幕横竖屏切换功能

    Android应用怎么实现屏幕横竖屏切换功能 发布时间:2020-11-26 15:48:57 来源:亿速云 阅读:121 作者:Leah Android应用怎么实现屏幕横竖屏切换功能?针对这个问题, ...

  2. android横竖屏切换动画,横竖屏切换时候Activity的生命周期

    曾经遇到过一个面试题,让你写出横屏切换竖屏Activity的生命周期.现在给大家分析一下他切换时具体的生命周期是怎么样的: 1.新建一个Activity,并把各个生命周期打印出来 2.运行Activi ...

  3. Android 11---WMS之横竖屏切换流程详解之一

    本文以Activity.setRequestedOrientation为入口梳理下横竖屏切换的详细流程.     代码均是基于最新的11.0版本. 第一篇主要讲了横竖屏切换时的准备操作: 更新方向,执 ...

  4. flutter 实现切屏横竖屏切换

    实现切屏横竖屏切换 参考 参考 class MediaPage extends StatefulWidget {@overrideState<StatefulWidget> createS ...

  5. widget中自动横竖屏切换时的问题

    首页 Android开发者社区 Android百科 极客学院 开启辅助访问 打卡签到 我要上头条 如何赚e币 注册验证问题 版主申请 切换到宽版 帐号 自动登录  找回密码 密码 登录  加入eoe ...

  6. iOS终极横竖屏切换解决方案

    大家的项目都是只支持竖屏的吧?大多数朋友(这其中当然也包括博主),都没有做过横屏开发,这次项目刚好有这个需求,因此把横竖屏相关的心得写成一遍文章供诸位参考. 01.综述 大多数公司的项目都只支持竖屏, ...

  7. [贝聊科技] iOS 终极横竖屏切换解决方案

    大家的项目都是只支持竖屏的吧?大多数朋友(这其中当然也包括博主),都没有做过横屏开发,这次项目刚好有这个需求,因此把横竖屏相关的心得写成一遍文章供诸位参考. 01.综述 大多数公司的项目都只支持竖屏, ...

  8. android 图片横竖判断_Android横竖屏切换及其对应布局加载问题详解

    本文为大家分享了Android横竖屏切换及其对应布局加载问题,供大家参考,具体内容如下 第一,横竖屏切换连带横竖屏布局问题: 如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同 ...

  9. android横竖屏切换生命周期

    前段时间在做项目的时候发现一个很奇怪的现象,在应用中按下锁屏键后再解锁,发现应用自动结束了.一开始以为是占用内存太多系统结束了应用,后来感觉这个很影响用户体验,决定自己查一下这个问题的根源. 仔细阅读 ...

最新文章

  1. Windows之建立C++开发环境
  2. LeetCode Reverse Linked List II
  3. 【Java 网络编程】Socket TCP UDP 联系
  4. BigData:根据最新2018人工智能行业创新企业Top100名单,绘制AI地区热点图,一目了然,看清哪个是AI最热门城市,以及VC最AI的热门领域
  5. android 查找字符在字符串的位置
  6. [转] Bookmarklet(书签工具)编写指南
  7. python的错误处理——try语句
  8. 二倍图三倍图什么意思_为什么说我们需要软件架构图?
  9. ipad是买WiFi版的好,还是买4G版的好?
  10. 阿里将开源进行到底!
  11. centos7.6 LNMP新版本
  12. 计算机系统应用技术课程,基于protégé的课程内容本体的构建-计算机系统应用.pdf...
  13. Hibernate 关于配置Mapping不成功 Unknow Entity
  14. 【C#】eventlog类的使用
  15. JAVA学习-类与对象(韩顺平java-高级篇)
  16. 如何绘制四线3格拼音
  17. 波士顿大学 计算机专业,波士顿大学计算机工程类专业排名还是该小心的看
  18. mysql数据库表中重命名语句_mysql数据库重命名
  19. 李欣桐 计算机竞赛,【赛出精彩】我校举行数学计算能力竞赛活动
  20. Day 5 E. Arranging The Sheep

热门文章

  1. 《皮肤的秘密》 读书笔记
  2. 如何使用激活工具Microsoft Toolkit
  3. ps如何(怎么)调整色阶的原理和方法
  4. 使用微信开发者工具的调试器
  5. cmd命令获取当前日期及时间
  6. 2进制转16进制完整代码
  7. HTML5期末大作业:体育足球网站设计——足球(6页) HTML+CSS+JavaScript 大学生体育运动网页设计模板代码 校园足球网页作业成品 学校足球网页制作模板 学生简单体育运动网站设计成
  8. 夏培肃完成了第一台电子计算机运算器,【判断题】夏培肃完成了第一台电子计算机运算器和控制器的设计工作,同时编写了我国第一本电子计算机原理讲义。...
  9. grid layout网格布局详解
  10. 云计算产品学习(1)