Android6.0开发中屏幕旋转原理与流程分析

Android6.0开发中屏幕旋转原理与流程分析,第1张

概述本文实例讲述了Android6.0开发中屏幕旋转原理与流程。分享给大家供大家参考,具体如下:

本文实例讲述了AndroID6.0开发中屏幕旋转原理与流程。分享给大家供大家参考,具体如下:

从AndroID 系统开发开始,这里写下AndroID 6.0 屏幕旋转系统分析。

第一部分

Kenel

AndroID 系统屏幕旋转得以实现,是靠从底层驱动gsensor 中获取数据,从而判断屏幕方向的。kernel sensor的驱动先就不在这里赘述,简单介绍下,gsensor 驱动注册input 事件 在/dev/input/下,可以通过adb getevent -p 可以查看系统所有的输入事件。
gsensor 提供X/Y/Z 三个方向的加速度数据,一旦注册到系统,harDWare 层打开设备之后,sensor 就开始上报数据。注意这里很关键,sensor 驱动加载完成之后,并不会立即激活,需要harDWare 层打开设备激活设备,设备才开始工作。

第二部分

HarDWare

在harDWare层,通过注册androID 标准modules之后,设备就打开激活,在AndroID 系统就注册了

{ .name = “Gravity sensor”,.vendor = “The AndroID Open Source Project”,.version = 1,.handle = SENSORS_HANDLE_BASE+ID_A,.type = SENSOR_TYPE_ACCELEROMETER,.maxrange = 4.0f*9.81f,.resolution = (4.0f*9.81f)/256.0f,.power = 0.2f,.minDelay = 5000,.reserved = {}},

第三部分

framework

PhoneWindownManager.java中的updateSettings()中读取系统中屏幕的设置方式,一旦开启自动旋转就调用updateOrIEntationListenerLp()开启读取sensor 数据;

// Configure rotation lock.int userRotation = Settings.System.getIntForUser(resolver,Settings.System.USER_ROTATION,Surface.ROTATION_0,UserHandle.USER_CURRENT);if (mUserRotation != userRotation) {    mUserRotation = userRotation;    updateRotation = true;}int userRotationMode = Settings.System.getIntForUser(resolver,Settings.System.ACCELEROMETER_ROTATION,UserHandle.USER_CURRENT) != 0 ?      WindowManagerPolicy.USER_ROTATION_FREE :          WindowManagerPolicy.USER_ROTATION_LOCKED;if (mUserRotationMode != userRotationMode) {    mUserRotationMode = userRotationMode;    updateRotation = true;    updateOrIEntationListenerLp();}

updateOrIEntationListenerLp中调用mOrIEntationListener.enable();调用到WindowOrIEntationListener.java中enable 注册gsensor的监听

voID updateOrIEntationListenerLp() {    if (!mOrIEntationListener.canDetectOrIEntation()) {      // If sensor is turned off or nonexistent for some reason      return;    }    // Could have been invoked due to screen turning on or off or    // change of the currently visible window's orIEntation.    if (localLOGV) Slog.v(TAG,"mScreenOnEarly=" + mScreenOnEarly        + ",mAwake=" + mAwake + ",mCurrentAppOrIEntation=" + mCurrentAppOrIEntation        + ",mOrIEntationSensorEnabled=" + mOrIEntationSensorEnabled        + ",mKeyguardDrawComplete=" + mKeyguardDrawComplete        + ",mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);    boolean disable = true;    // Note: We postpone the rotating of the screen until the keyguard as well as the    // window manager have reported a draw complete.    if (mScreenOnEarly && mAwake &&        mKeyguardDrawComplete && mWindowManagerDrawComplete) {      if (needSensorRunningLp()) {        disable = false;        //enable Listener if not already enabled        if (!mOrIEntationSensorEnabled) {          mOrIEntationListener.enable();          if(localLOGV) Slog.v(TAG,"Enabling Listeners");          mOrIEntationSensorEnabled = true;        }      }    }    //check if sensors need to be Disabled    if (disable && mOrIEntationSensorEnabled) {      mOrIEntationListener.disable();      if(localLOGV) Slog.v(TAG,"disabling Listeners");      mOrIEntationSensorEnabled = false;    }}/*** Enables the WindowOrIEntationListener so it will monitor the sensor and call* {@link #onProposedRotationChanged(int)} when the device orIEntation changes.*/public voID enable() {    synchronized (mlock) {      if (mSensor == null) {        Slog.w(TAG,"Cannot detect sensors. Not enabled");        return;      }      if (mEnabled == false) {        if (LOG) {          Slog.d(TAG,"WindowOrIEntationListener enabled");        }        mOrIEntationJudge.resetLocked();        mSensorManager.registerListener(mOrIEntationJudge,mSensor,mRate,mHandler);        mEnabled = true;      }    }}

mOrIEntationJudge 类型为OrIEntationJudge ,其中onSensorChanged方法提供了通过gsensor 各个方向的加速度数据计算方向的方法。一旦计算出屏幕方向发送变化则调用onProposedRotationChanged接口通知前面的Listener。而onProposedRotationChanged是一个抽象方法,由子类实现也PhoneWindowmanger 中的MyOrIEntationListener类

@OverrIDepublic voID onProposedRotationChanged(int rotation) {      if (localLOGV) Slog.v(TAG,"onProposedRotationChanged,rotation=" + rotation);      mHandler.post(mUpdateRotationRunnable);}private final Runnable mUpdateRotationRunnable = new Runnable() {      @OverrIDe      public voID run() {        // send interaction hint to improve redraw performance        mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INteraCTION,0);        updateRotation(false);      }};voID updateRotation(boolean alwaysSendConfiguration) {    try {      //set orIEntation on WindowManager      mWindowManager.updateRotation(alwaysSendConfiguration,false);    } catch (remoteexception e) {      // Ignore    }}

调用windowManagerService中的updateRotation方法

@OverrIDepublic voID updateRotation(boolean alwaysSendConfiguration,boolean forceRelayout) {    updateRotationUnchecked(alwaysSendConfiguration,forceRelayout);}public voID updateRotationUnchecked(boolean alwaysSendConfiguration,boolean forceRelayout) {    if(DEBUG_ORIENTATION) Slog.v(TAG,"updateRotationUnchecked("          + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");    long origID = Binder.clearCallingIDentity();    boolean changed;    synchronized(mWindowMap) {      changed = updateRotationUncheckedLocked(false);      if (!changed || forceRelayout) {        getDefaultdisplayContentLocked().layoutNeeded = true;        performlayoutAndplaceSurfacesLocked();      }    }    if (changed || alwaysSendConfiguration) {      sendNewConfiguration();    }    Binder.restoreCallingIDentity(origID);}// Todo(multidisplay): Rotate any display?/*** Updates the current rotation.** Returns true if the rotation has been changed. In this case YOU* MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.*/public boolean updateRotationUncheckedLocked(boolean inTransaction) {    if (mDeferredRotationPauseCount > 0) {      // Rotation updates have been paused temporarily. Defer the update until      // updates have been resumed.      if (DEBUG_ORIENTATION) Slog.v(TAG,"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,animation in progress.");      return false;    }    if (!mdisplayEnabled) {      // No point choosing a rotation if the display is not enabled.      if (DEBUG_ORIENTATION) Slog.v(TAG,display is not enabled.");      return 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.    int rotation = mPolicy.rotationForOrIEntationLw(mForcedAppOrIEntation,mRotation);    boolean altOrIEntation = !mPolicy.rotationHasCompatibleMetricslw(        mForcedAppOrIEntation,rotation);    if (DEBUG_ORIENTATION) {      Slog.v(TAG,"Application requested orIEntation "          + mForcedAppOrIEntation + ",got rotation " + rotation          + " which has " + (altOrIEntation ? "incompatible" : "compatible")          + " metrics");    }    if (mRotateOnBoot) {       mRotation = Surface.ROTATION_0;       rotation = Surface.ROTATION_90;    }    /* display portrait,force androID rotation according to 90 */    if("true".equals(SystemPropertIEs.get("persist.display.portrait","false"))){       rotation = Surface.ROTATION_90;    }    /* display portrait end */    // if("vr".equals(SystemPropertIEs.get("ro.target.product","tablet")))     // rotation = Surface.ROTATION_0;    if (mRotation == rotation && mAltOrIEntation == altOrIEntation) {      // No change.      return false;    }    resetwindowstate();    if (DEBUG_ORIENTATION) {      Slog.v(TAG,"Rotation changed to " + rotation + (altOrIEntation ? " (alt)" : "")        + " from " + mRotation + (mAltOrIEntation ? " (alt)" : "")        + ",forceApp=" + mForcedAppOrIEntation);    }    mRotation = rotation;    mAltOrIEntation = altOrIEntation;    mPolicy.setRotationLw(mRotation);    ThumbModeHelper.getInstance().setRotation(mRotation);    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;    final displayContent displayContent = getDefaultdisplayContentLocked();    displayContent.layoutNeeded = true;    final int[] anim = new int[2];    if (displayContent.isDimming()) {      anim[0] = anim[1] = 0;    } else {      mPolicy.selectRotationAnimationLw(anim);    }    startFreezingdisplayLocked(inTransaction,anim[0],anim[1]);    // startFreezingdisplayLocked can reset the ScreenRotationAnimation.    screenRotationAnimation =        mAnimator.getScreenRotationAnimationLocked(display.DEFAulT_disPLAY);    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.    updatedisplayAndOrIEntationLocked();    final displayInfo displayInfo = displayContent.getdisplayInfo();    if (!inTransaction) {      if (SHOW_TRANSACTIONS) {        Slog.i(TAG,">>> 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();        }      }      mdisplayManagerInternal.performTraversalintransactionFromWindowManager();    } finally {      if (!inTransaction) {        SurfaceControl.closeTransaction();        if (SHOW_liGHT_TRANSACTIONS) {          Slog.i(TAG,"<<< CLOSE TRANSACTION setRotationUnchecked");        }      }    }    final WindowList windows = displayContent.getwindowList();    for (int i = windows.size() - 1; i >= 0; i--) {      windowstate w = windows.get(i);      if (w.mHasSurface) {        if (DEBUG_ORIENTATION) Slog.v(TAG,"Set mOrIEntationChanging of " + w);        w.mOrIEntationChanging = true;        mInnerFIElds.mOrIEntationChangeComplete = false;      }      w.mLastFreezeDuration = 0;    }    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;}

附:AndroID动态禁用或开启屏幕旋转的方法

package com.gwtsz.gts2.util;import androID.content.Context;import androID.provIDer.Settings;import androID.provIDer.Settings.SettingNotFoundException;/** * 重力感应器开关 * 围绕手机屏幕旋转的设置功能编写的方法 * @author Wilson */public class SensorUtil {  /**   * 打开重力感应,即设置屏幕可旋转   * @param context   */  public static voID openSensor(Context context){    Settings.System.putInt(context.getContentResolver(),1);  }  /**   * 关闭重力感应,即设置屏幕不可旋转   * @param context   */  public static voID closeSensor(Context context){    Settings.System.putInt(context.getContentResolver(),0);  }  /**   * 获取屏幕旋转功能开启状态   * @param context   * @return   */  public static int getSensorState(Context context){    int sensorState = 0;    try {      sensorState = Settings.System.getInt(context.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION);      return sensorState;    } catch (SettingNotFoundException e) {      e.printstacktrace();    }    return sensorState;  }  /**   * 判断屏幕旋转功能是否开启   */  public static boolean isOpenSensor(Context context){    boolean isOpen = false;    if(getSensorState(context) == 1){      isOpen = true;    }else if(getSensorState(context) == 0){      isOpen = false;    }    return isOpen;  }}

更多关于AndroID相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android视图View技巧总结》、《Android编程之activity *** 作技巧总结》、《Android文件 *** 作技巧汇总》、《Android资源 *** 作技巧汇总》及《Android控件用法总结》

希望本文所述对大家AndroID程序设计有所帮助。

总结

以上是内存溢出为你收集整理的Android6.0开发中屏幕旋转原理与流程分析全部内容,希望文章能够帮你解决Android6.0开发中屏幕旋转原理与流程分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1143608.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存