国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android6.0開發中屏幕旋轉原理與流程分析

2019-12-12 01:38:05
字體:
來源:轉載
供稿:網友

本文實例講述了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, 0, 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, "Deferring rotation, animation in progress.");      return false;    }    if (!mDisplayEnabled) {      // No point choosing a rotation if the display is not enabled.      if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, 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(),Settings.System.ACCELEROMETER_ROTATION, 1);  }  /**   * 關閉重力感應,即設置屏幕不可旋轉   * @param context   */  public static void closeSensor(Context context){    Settings.System.putInt(context.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION, 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程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 封开县| 天水市| 阳原县| 滦南县| 库尔勒市| 嘉定区| 白朗县| 大连市| 荔波县| 清河县| 遂昌县| 宜丰县| 犍为县| 静宁县| 文安县| 佳木斯市| 宁国市| 巨野县| 如皋市| 天津市| 姚安县| 文登市| 余庆县| 司法| 和顺县| 琼中| 奉节县| 花莲县| 赣州市| 平远县| 湘潭市| 博兴县| 临沂市| 通化县| 三河市| 拜城县| 丰顺县| 唐山市| 大冶市| 吴忠市| 淅川县|