久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx

Android6.0中屏幕旋轉的原理是什么

這篇文章給大家介紹Android6.0中屏幕旋轉的原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創新互聯建站專業為企業提供黃石網站建設、黃石做網站、黃石網站設計、黃石網站制作等企業網站建設、網頁設計與制作、黃石企業網站模板建站服務,10年黃石做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。

第一部分

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類

@Override
public 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方法

@Override
public 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;
  }
}

關于Android6.0中屏幕旋轉的原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當前名稱:Android6.0中屏幕旋轉的原理是什么
當前地址:http://www.js-pz168.com/article26/pojdcg.html

成都網站建設公司_創新互聯,為您提供品牌網站制作網站策劃域名注冊外貿建站定制開發企業網站制作

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

h5響應式網站建設
久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx
91激情在线视频| 欧美色精品在线视频| 欧美吞精做爰啪啪高潮| www久久精品| 亚洲一区二区三区四区不卡 | 日韩一本精品| av男人天堂一区| 欧美日韩在线高清| 在线播放视频一区| 亚洲人快播电影网| 国产精品一品二品| 欧美精品二区三区四区免费看视频| 欧美日韩卡一卡二| 综合久久综合久久| 国产一区免费电影| 欧美激情论坛| 日韩精品一区二区三区蜜臀| 一二三区精品视频| 成人深夜福利app| 亚洲成色最大综合在线| 精品欧美一区二区久久| 性做久久久久久| 91传媒免费看| 欧美午夜不卡在线观看免费| 国产精品免费视频一区| 精品一区二区在线观看| 免费国产在线精品一区二区三区| 91麻豆精品国产91久久久久久 | 蜜桃一区二区三区在线观看| 懂色av一区二区三区在线播放| 欧美偷拍一区二区| 亚洲蜜桃精久久久久久久| 国产精品996| 先锋在线资源一区二区三区| 久久久www免费人成精品| 久久99久国产精品黄毛片色诱| 久久综合给合久久狠狠色| 日韩视频在线永久播放| 亚洲国产视频在线| 成人在线看片| 91精品蜜臀在线一区尤物| 亚洲国产cao| 国产区二精品视| 日韩欧美一二三四区| 日韩av高清在线观看| 精品视频一区二区| 精品播放一区二区| 国产最新精品精品你懂的| 色之综合天天综合色天天棕色 | 91亚洲国产成人精品一区二三| 在线亚洲欧美专区二区| 亚洲精品国产一区二区精华液 | 日本一区二区三区www| 久久久久国产精品麻豆ai换脸| 国内精品伊人久久久久av影院| 日韩亚洲视频| 中文字幕一区二区在线播放| 成人激情文学综合网| 欧美午夜电影网| 午夜精品爽啪视频| 久久大香伊蕉在人线观看热2| 精品国产一区二区在线观看| 国产最新精品免费| 一本大道久久精品懂色aⅴ| 亚洲精品免费看| 国产手机精品在线| 精品福利在线导航| 国产高清不卡二三区| 在线亚洲人成电影网站色www| 亚洲国产视频在线| 鲁片一区二区三区| 国产欧美一区二区在线观看| 成人av网站在线观看免费| 欧美日韩精品一区二区三区四区 | 国产精品亚洲不卡a| 欧美成人精品1314www| 久久精品国产网站| 色欧美88888久久久久久影院| 亚洲午夜在线观看视频在线| 久久精品日产第一区二区三区精品版| 国产亚洲自拍一区| 99v久久综合狠狠综合久久| 日韩欧美在线不卡| 国产精品99久| 3d动漫精品啪啪| 国产一区在线观看麻豆| 欧美亚洲高清一区| 蜜桃一区二区三区在线观看| 色综合天天视频在线观看| 亚洲第一狼人社区| 亚洲精品一区二区三区樱花 | 国产亚洲欧美色| 91在线高清观看| 久久综合久久综合亚洲| 99天天综合性| 日韩欧美国产三级| 国产成人精品午夜视频免费| 69堂国产成人免费视频| 国产一区二区三区高清播放| 欧美日韩一区久久| 国产综合色视频| 91精品久久久久久蜜臀| 国产成人免费9x9x人网站视频| 欧美一区二区日韩一区二区| 国产不卡在线视频| 日韩欧美高清在线| 不卡av免费在线观看| 久久免费看少妇高潮| 99视频在线| 国产精品毛片久久久久久| 精品无码久久久久久久动漫| 亚洲欧美区自拍先锋| 日韩久久久久久久久久久久久| 亚洲成人你懂的| 色综合天天综合狠狠| 美日韩一区二区三区| 欧美日韩日日摸| 国产福利91精品一区| 日韩欧美高清一区| 91精品国产91久久久久青草| 亚洲国产精品成人综合| 好吊妞www.84com只有这里才有精品| 亚洲视频在线一区二区| 日本在线观看一区二区| 日韩高清一级片| 欧美日韩国产综合一区二区| 国产成人免费网站| 久久久精品天堂| 久久精品国产精品青草色艺| 亚洲在线免费播放| 色狠狠色狠狠综合| 国产精品一区二区三区99| 精品欧美久久久| 国产乱码精品一区二区三区中文 | 欧洲精品码一区二区三区免费看| 午夜免费久久看| 欧美色手机在线观看| 床上的激情91.| 国产午夜亚洲精品不卡| 精品综合在线| 天堂一区二区在线免费观看| 欧美精品乱码久久久久久| av中文字幕不卡| 亚洲色图.com| 色婷婷综合激情| 成人一区二区三区| 中文字幕一区二区三区乱码在线| 先锋影音亚洲资源| 国产麻豆精品一区二区| 久久精品视频一区| 日韩欧美视频第二区| 狠狠色狠狠色综合系列| 久久精品男人的天堂| 日本一区二区视频| 精品无人码麻豆乱码1区2区| 久久亚洲一级片| 欧美一区免费视频| 激情欧美一区二区| 中文字幕不卡三区| 中文字幕日韩精品久久| 成人免费视频视频在线观看免费| 国产精品二三区| 日本久久精品电影| 97aⅴ精品视频一二三区| 一区二区在线观看视频 | 国产欧美日韩视频在线观看| 视频一区国产精品| 国产激情一区二区三区四区| 国产精品麻豆欧美日韩ww| 色网站国产精品| 91在线观看高清| 午夜欧美视频在线观看| 日韩女优av电影在线观看| 欧美久久电影| 国产精品18久久久| 亚洲女人的天堂| 91精品国产综合久久小美女| 好看的日韩精品| 狠狠色丁香婷婷综合久久片| 欧美国产精品中文字幕| 91久久精品国产91性色tv| 91麻豆精品视频| 日韩精品91亚洲二区在线观看| 久久亚洲欧美国产精品乐播| 亚洲乱码一区二区三区| 99久免费精品视频在线观看| 亚洲午夜一区二区| 精品国产乱码久久久久久老虎 | 久久久一区二区三区捆绑**| 日本在线视频一区| 成人福利在线看| 香蕉久久一区二区不卡无毒影院 | 成人动漫在线视频| 蜜臀久久99精品久久久画质超高清 | 亚洲精品在线三区| 宅男av一区二区三区| av一区和二区| 精品综合免费视频观看| 亚洲蜜臀av乱码久久精品蜜桃| 日韩精品在线网站|