RK3288 android7.1.2 开机固定横屏或者竖屏+Sensor自动旋转分析(可以通过adb shell 设定屏幕旋转方向)

本文详细解析了在RK3288平台上,如何通过adb shell设定Android7.1.2系统的屏幕旋转,包括查看加速度计状态、固定横屏或竖屏以及Sensor自动旋转的实现机制。涉及关键步骤如设置system.prop、调整屏幕旋转方向、设置Sensor监听以及SurfaceFlinger的屏幕更新流程。
摘要由CSDN通过智能技术生成

通过adb shell 查看加速度计开启情况

//0:不支持旋转   1:支持旋转
adb shell settings get system accelerometer_rotation

通过adb shell 设定加速度计关闭与开启

//0:不支持旋转   1:支持旋转
adb shell settings put system accelerometer_rotation 0

通过adb shell 查看指定的屏幕旋转方向

//0:0度  1:90度 2:180度 3:270度
adb shell settings get system user_rotation

通过adb shell 更改指定的屏幕旋转方向

//0:0度  1:90度 2:180度 3:270度
adb shell settings put system user_rotation 0

屏幕属性:

路径:frameworks\base\core\java\android\content\pm\ActivityInfo.java

    /** @hide */
    @IntDef({
            SCREEN_ORIENTATION_UNSPECIFIED,//系统自动选择合适方向
            SCREEN_ORIENTATION_LANDSCAPE,//正向横屏,显示的宽比高长(锁死为横屏方向,不再让方向感应起作用)
            SCREEN_ORIENTATION_PORTRAIT,//正向竖屏,显示的高比宽长(锁死为竖屏方向,不再让方向感应起作用)
            SCREEN_ORIENTATION_USER,//用户当前首选的方向
            SCREEN_ORIENTATION_BEHIND,//Activity堆栈中的下面一个Activity的方向一致
            SCREEN_ORIENTATION_SENSOR,//开启方向传感器计算方向,忽略用户强制设定
            SCREEN_ORIENTATION_NOSENSOR,//关闭方向传感器
            SCREEN_ORIENTATION_SENSOR_LANDSCAPE,//开启方向传感器计算方向,只切换正反横向,忽略用户强制设定
            SCREEN_ORIENTATION_SENSOR_PORTRAIT,//开启方向传感器计算方向,只切换正反竖向,忽略用户强制设定
            SCREEN_ORIENTATION_REVERSE_LANDSCAPE,//反向横屏
            SCREEN_ORIENTATION_REVERSE_PORTRAIT,//反向竖屏
            SCREEN_ORIENTATION_FULL_SENSOR,//支持在四个方向旋转,即使设备在某个方向上不适用旋转
            SCREEN_ORIENTATION_USER_LANDSCAPE,
            SCREEN_ORIENTATION_USER_PORTRAIT,
            SCREEN_ORIENTATION_FULL_USER,
            SCREEN_ORIENTATION_LOCKED
    })

   @Retention(RetentionPolicy.SOURCE)
    public @interface ScreenOrientation {}

    /**
     * Constant corresponding to <code>unspecified</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1;
    /**
     * Constant corresponding to <code>landscape</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_LANDSCAPE = 0;
    /**
     * Constant corresponding to <code>portrait</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_PORTRAIT = 1;
    /**
     * Constant corresponding to <code>user</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_USER = 2;
    /**
     * Constant corresponding to <code>behind</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_BEHIND = 3;
    /**
     * Constant corresponding to <code>sensor</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_SENSOR = 4;

    /**
     * Constant corresponding to <code>nosensor</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_NOSENSOR = 5;

    /**
     * Constant corresponding to <code>sensorLandscape</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6;

    /**
     * Constant corresponding to <code>sensorPortrait</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7;

    /**
     * Constant corresponding to <code>reverseLandscape</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;

    /**
     * Constant corresponding to <code>reversePortrait</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

    /**
     * Constant corresponding to <code>fullSensor</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10;

    /**
     * Constant corresponding to <code>userLandscape</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_USER_LANDSCAPE = 11;

    /**
     * Constant corresponding to <code>userPortrait</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_USER_PORTRAIT = 12;

    /**
     * Constant corresponding to <code>fullUser</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_FULL_USER = 13;

    /**
     * Constant corresponding to <code>locked</code> in
     * the {@link android.R.attr#screenOrientation} attribute.
     */
    public static final int SCREEN_ORIENTATION_LOCKED = 14;

    /**
     * The preferred screen orientation this activity would like to run in.
     * From the {@link android.R.attr#screenOrientation} attribute, one of
     * {@link #SCREEN_ORIENTATION_UNSPECIFIED},
     * {@link #SCREEN_ORIENTATION_LANDSCAPE},
     * {@link #SCREEN_ORIENTATION_PORTRAIT},
     * {@link #SCREEN_ORIENTATION_USER},
     * {@link #SCREEN_ORIENTATION_BEHIND},
     * {@link #SCREEN_ORIENTATION_SENSOR},
     * {@link #SCREEN_ORIENTATION_NOSENSOR},
     * {@link #SCREEN_ORIENTATION_SENSOR_LANDSCAPE},
     * {@link #SCREEN_ORIENTATION_SENSOR_PORTRAIT},
     * {@link #SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
     * {@link #SCREEN_ORIENTATION_REVERSE_PORTRAIT},
     * {@link #SCREEN_ORIENTATION_FULL_SENSOR},
     * {@link #SCREEN_ORIENTATION_USER_LANDSCAPE},
     * {@link #SCREEN_ORIENTATION_USER_PORTRAIT},
     * {@link #SCREEN_ORIENTATION_FULL_USER},
     * {@link #SCREEN_ORIENTATION_LOCKED},
     */
    @ScreenOrientation
    public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;

双屏属性:

ro.same.orientation=false       主屏与副屏方向是否相同
ro.rotation.external=false      副屏是否随主屏旋转
ro.sf.hwrotation=0              主屏初始方向 
ro.orientation.einit=90         副屏初始方向

一. 固定横屏或者竖屏

1.通过system.prop 系统属性进行修改

路径:device\rockchip\rk3288\system.prop

//控制开机动画是否旋转true:旋转  false:不旋转
ro.sf.fakerotation=false
//0:横屏 90:竖屏
ro.sf.hwrotation=90

二. Sensor如何控制屏幕自动旋转

1.Settings -> Display 中有When device is rotated 选项用来控制是否开启自动旋转

路径:packages\apps\Settings\res\values\strings.xml

<string name="display_auto_rotate_title">When device is rotated</string>
<!-- [CHAR LIMIT=70] Rotate when screen is turned option -->
<string name="display_auto_rotate_rotate">Rotate the contents of the screen</string>

2.对应布局在Display_settings.xml 中(其实rk3288 android7.1.2并没有添加自动旋转开关布局)

<com.android.settings.DropDownPreference  
  
android:key="auto_rotate"  
  
android:title="@string/display_auto_rotate_title" />

3.java层调用

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

private static final String KEY_AUTO_ROTATE = "auto_rotate";

if (RotationPolicy.isRotationLockToggleVisible(activity)) {
    DropDownPreference rotatePreference =
            (DropDownPreference) findPreference(KEY_AUTO_ROTATE);
    int rotateLockedResourceId;
    // The following block sets the string used when rotation is locked.
    // If the device locks specifically to portrait or landscape (rather than current
    // rotation), then we use a different string to include this information.
    if (allowAllRotations(activity)) {
        rotateLockedResourceId = R.string.display_auto_rotate_stay_in_current;
    } else {
        if (RotationPolicy.getRotationLockOrientation(activity)
                == Configuration.ORIENTATION_PORTRAIT) {
            rotateLockedResourceId =
                    R.string.display_auto_rotate_stay_in_portrait;
        } else {
            rotateLockedResourceId =
                    R.string.display_auto_rotate_stay_in_landscape;
        }
    }
    rotatePreference.setEntries(new CharSequence[] {
            activity.getString(R.string.display_auto_rotate_rotate),
            activity.getString(rotateLockedResourceId),
    });
    rotatePreference.setEntryValues(new CharSequence[] { "0", "1" });
    rotatePreference.setValueIndex(RotationPolicy.isRotationLocked(activity) ?
            1 : 0);
    rotatePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            final boolean locked = Integer.parseInt((String) newValue) != 0;
            MetricsLogger.action(getActivity(), MetricsEvent.ACTION_ROTATION_LOCK,
                    locked);
            RotationPolicy.setRotationLock(activity, locked);
            return true;
        }
    });
} else {
    removePreference(KEY_AUTO_ROTATE);
}

rotatePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        final boolean locked = Integer.parseInt((String) newValue) != 0;
        MetricsLogger.action(getActivity(), MetricsEvent.ACTION_ROTATION_LOCK,
                locked);
        RotationPolicy.setRotationLock(activity, locked);
        return true;
    }
});

4.继续调用:setRotationLock() ,当enable auto_rotate 则调用wm.freezeRotation(rotation); disable auto_rotate 则调用wm.thawRotation();

路径:frameworks\base\core\java\com\android\internal\view\RotationPolicy.java

/**
     * Enables or disables natural rotation lock from Accessibility settings.
     *
     * If rotation is locked for accessibility, the system UI toggle is hidden to avoid confusion.
     * 自动旋转屏幕,打开为1,关闭为0,默认为0
     * adb shell settings get system hide_rotation_lock_toggle_for_accessibility 0
     */
    public static void setRotationLockForAccessibility(Context context, final boolean enabled) {
        Settings.System.putIntForUser(context.getContentResolver(),
                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0,
                        UserHandle.USER_CURRENT);

        setRotationLock(enabled, NATURAL_ROTATION);
    }

    private static boolean areAllRotationsAllowed(Context context) {
        return context.getResources().getBoolean(R.bool.config_allowAllRotations);
    }

    private static void setRotationLock(final boolean enabled, final int rotation) {
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                    if (enabled) {
                        wm.freezeRotation(rotation);
                    } else {
                        wm.thawRotation();
                    }
                } catch (RemoteException exc) {
                    Log.w(TAG, "Unable to save auto-rotate setting");
                }
            }
        });
    }

5.Sensor开启enable auto_rotate 调用 wm.freezeRotation(rotation);

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

 /**
     * Freeze rotation changes.  (Enable "rotation lock".)
     * Persists across reboots.
     * @param rotation The desired rotation to freeze to, or -1 to use the
     * current rotation.
     */
    @Override
    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_30) {
            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);
    }

6.通过调用PhoneWindowManager.cpp 中的setUserRotationMode()去设置Settings.System相关的数据库值。

1)用户通过界面设定屏幕选装方向USER_ROTATION = rot
Settings.System.putIntForUser(res,Settings.System.USER_ROTATION,rot,UserHandle.USER_CURRENT);
2)是否开启加速度计自动调整方向 ACCELEROMETER_ROTATION  = 0 默认关闭
Settings.System.putIntForUser(res,Settings.System.ACCELEROMETER_ROTATION, 0,UserHandle.USER_CURRENT);

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

// User rotation: to be used when all else fails in assigning an orientation to the device
    @Override
    public void setUserRotationMode(int mode, int rot) {
        ContentResolver res = mContext.getContentResolver();

        // mUserRotationMode and mUserRotation will be assigned by the content observer
        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
            //用户通过界面设定屏幕选装方向USER_ROTATION = rot
            Settings.System.putIntForUser(res,
                    Settings.System.USER_ROTATION,
                    rot,
                    UserHandle.USER_CURRENT);
            //是否开启加速度计自动调整方向 ACCELEROMETER_ROTATION  = 0 默认关闭
            Settings.System.putIntForUser(res,
                    Settings.System.ACCELEROMETER_ROTATION,
                    0,
                    UserHandle.USER_CURRENT);
        } else {
            Settings.System.putIntForUser(res,
                    Settings.System.ACCELEROMETER_ROTATION,
                    1,
                    UserHandle.USER_CURRENT);
        }
    }

启用监听器Observe去监听Settings.System的数值变化,如果有变动就去调用SettingsObserver.onChange()。同时updateSettings() 会读取屏幕设定,一旦打开自动旋转按钮,就开始调用updateOrientationListenerLp();读取sensor 数据。

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

class SettingsObserver extends ContentObserver {
        SettingsObserver(Handler handler) {
            super(handler);
        }

        void observe() {
            // Observe all users' changes
            ContentResolver resolver = mContext.getContentResolver();
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.ACCELEROMETER_ROTATION), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.USER_ROTATION), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.POINTER_LOCATION), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POLICY_CONTROL), false, this,
                    UserHandle.USER_ALL);
            updateSettings();
        }

        // this method is added for shutdown animation.
        public void unRegister() {
            ContentResolver resolver = mContext.getContentResolver();
            resolver.unregisterContentObserver(this);
        }

        @Override public void onChange(boolean selfChange) {
            updateSettings();
            updateRotation(false);
        }
    }


    public void updateSettings() {
        ContentResolver resolver = mContext.getContentResolver();
        boolean updateRotation = false;
        synchronized (mLock) {
            mEndcallBehavior = Settings.System.getIntForUser(resolver,
                    Settings.System.END_BUTTON_BEHAVIOR,
                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);
            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);
            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);

            // Configure wake gesture.
            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
                    UserHandle.USER_CURRENT) != 0;
            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
                updateWakeGestureListenerLp();
            }

            // Configure rotation lock.
            int userRotation = Settings.System.getIntForUser(resolver,
                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
       
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值