Loading core/res/res/values/config.xml +37 −0 Original line number Diff line number Diff line Loading @@ -572,6 +572,43 @@ true here reverses that logic. --> <bool name="config_reverseDefaultRotation">false</bool> <!-- Sets the minimum and maximum tilt tolerance for each possible rotation. This array consists of 4 pairs of values which specify the minimum and maximum tilt angle at which the device will transition into each rotation. The tilt angle represents the direction in which the plane of the screen is facing; it is also known as the angle of elevation. -90 degree tilt means that the screen is facing straight down (the device is being held overhead upside-down) 0 degree tilt means that the screen is facing outwards (the device is being held vertically) 90 degree tilt means that the screen is facing straight up (the device is resting on a flat table) The default tolerances are set conservatively such that the device is more likely to remain in its natural orientation than rotate into a counterclockwise, clockwise, or reversed posture (with an especially strong bias against the latter) to prevent accidental rotation while carrying the device in hand. These thresholds may need to be tuned when the device is intended to be mounted into a dock with a particularly shallow profile wherein rotation would ordinarily have been suppressed. It is helpful to consider the desired behavior both when the device is being held at a positive tilt (typical case) vs. a negative tilt (reading overhead in bed) since they are quite different. In the overhead case, we typically want the device to more strongly prefer to retain its current configuration (in absence of a clear indication that a rotation is desired) since the user's head and neck may be held at an unusual angle. --> <integer-array name="config_autoRotationTiltTolerance"> <!-- rotation: 0 (natural) --> <item>-25</item> <item>70</item> <!-- rotation: 90 (rotate CCW) --> <item>-25</item> <item>65</item> <!-- rotation: 180 (reverse) --> <item>-25</item> <item>60</item> <!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item> </integer-array> <!-- Lid switch behavior --> <!-- The number of degrees to rotate the display when the keyboard is open. Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1451,6 +1451,7 @@ <java-symbol type="anim" name="voice_activity_open_exit" /> <java-symbol type="anim" name="voice_activity_open_enter" /> <java-symbol type="array" name="config_autoRotationTiltTolerance" /> <java-symbol type="array" name="config_keyboardTapVibePattern" /> <java-symbol type="array" name="config_longPressVibePattern" /> <java-symbol type="array" name="config_safeModeDisabledVibePattern" /> Loading services/core/java/com/android/server/policy/WindowOrientationListener.java +63 −31 Original line number Diff line number Diff line Loading @@ -24,10 +24,10 @@ import android.hardware.SensorManager; import android.os.Handler; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import java.io.PrintWriter; import java.util.Arrays; /** * A special helper class used by the WindowManager Loading @@ -40,8 +40,6 @@ import java.io.PrintWriter; * * You can also visualize the behavior of the WindowOrientationListener. * Refer to frameworks/base/tools/orientationplot/README.txt for details. * * @hide */ public abstract class WindowOrientationListener { private static final String TAG = "WindowOrientationListener"; Loading Loading @@ -90,7 +88,7 @@ public abstract class WindowOrientationListener { ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER); if (mSensor != null) { // Create listener only if sensors do exist mSensorEventListener = new SensorEventListenerImpl(); mSensorEventListener = new SensorEventListenerImpl(context); } } Loading @@ -101,12 +99,12 @@ public abstract class WindowOrientationListener { public void enable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); Slog.w(TAG, "Cannot detect sensors. Not enabled"); return; } if (mEnabled == false) { if (LOG) { Log.d(TAG, "WindowOrientationListener enabled"); Slog.d(TAG, "WindowOrientationListener enabled"); } mSensorEventListener.resetLocked(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler); Loading @@ -121,12 +119,12 @@ public abstract class WindowOrientationListener { public void disable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); Slog.w(TAG, "Cannot detect sensors. Invalid disable"); return; } if (mEnabled == true) { if (LOG) { Log.d(TAG, "WindowOrientationListener disabled"); Slog.d(TAG, "WindowOrientationListener disabled"); } mSensorManager.unregisterListener(mSensorEventListener); mEnabled = false; Loading Loading @@ -296,7 +294,7 @@ public abstract class WindowOrientationListener { // If the tilt angle remains greater than the specified angle for a minimum of // the specified time, then the device is deemed to be lying flat // (just chillin' on a table). private static final float FLAT_ANGLE = 75; private static final float FLAT_ANGLE = 80; private static final long FLAT_TIME_NANOS = 1000 * NANOS_PER_MS; // If the tilt angle has increased by at least delta degrees within the specified amount Loading Loading @@ -361,8 +359,24 @@ public abstract class WindowOrientationListener { SensorManager.STANDARD_GRAVITY + ACCELERATION_TOLERANCE; // Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e. // when screen is facing the sky or ground), we completely ignore orientation data. private static final int MAX_TILT = 75; // when screen is facing the sky or ground), we completely ignore orientation data // because it's too unstable. private static final int MAX_TILT = 80; // The tilt angle below which we conclude that the user is holding the device // overhead reading in bed and lock into that state. private static final int TILT_OVERHEAD_ENTER = -40; // The tilt angle above which we conclude that the user would like a rotation // change to occur and unlock from the overhead state. private static final int TILT_OVERHEAD_EXIT = -15; // The gap angle in degrees between adjacent orientation angles for hysteresis. // This creates a "dead zone" between the current orientation and a proposed // adjacent orientation. No orientation proposal is made when the orientation // angle is within the gap between the current orientation and the adjacent // orientation. private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45; // The tilt angle range in degrees for each orientation. // Beyond these tilt angles, we don't even consider transitioning into the Loading @@ -375,28 +389,13 @@ public abstract class WindowOrientationListener { // facing up (resting on a table). // The ideal tilt angle is 0 (when the device is vertical) so the limits establish // how close to vertical the device must be in order to change orientation. private final int[][] TILT_TOLERANCE = new int[][] { /* ROTATION_0 */ { -25, 70 }, private final int[][] mTiltToleranceConfig = new int[][] { /* ROTATION_0 */ { -25, 70 }, // note: these are overridden by config.xml /* ROTATION_90 */ { -25, 65 }, /* ROTATION_180 */ { -25, 60 }, /* ROTATION_270 */ { -25, 65 } }; // The tilt angle below which we conclude that the user is holding the device // overhead reading in bed and lock into that state. private final int TILT_OVERHEAD_ENTER = -40; // The tilt angle above which we conclude that the user would like a rotation // change to occur and unlock from the overhead state. private final int TILT_OVERHEAD_EXIT = -15; // The gap angle in degrees between adjacent orientation angles for hysteresis. // This creates a "dead zone" between the current orientation and a proposed // adjacent orientation. No orientation proposal is made when the orientation // angle is within the gap between the current orientation and the adjacent // orientation. private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45; // Timestamp and value of the last accelerometer sample. private long mLastFilteredTimestampNanos; private float mLastFilteredX, mLastFilteredY, mLastFilteredZ; Loading Loading @@ -430,11 +429,32 @@ public abstract class WindowOrientationListener { private boolean mOverhead; // History of observed tilt angles. private static final int TILT_HISTORY_SIZE = 40; private static final int TILT_HISTORY_SIZE = 200; private float[] mTiltHistory = new float[TILT_HISTORY_SIZE]; private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE]; private int mTiltHistoryIndex; public SensorEventListenerImpl(Context context) { // Load tilt tolerance configuration. int[] tiltTolerance = context.getResources().getIntArray( com.android.internal.R.array.config_autoRotationTiltTolerance); if (tiltTolerance.length == 8) { for (int i = 0; i < 4; i++) { int min = tiltTolerance[i * 2]; int max = tiltTolerance[i * 2 + 1]; if (min >= -90 && min <= max && max <= 90) { mTiltToleranceConfig[i][0] = min; mTiltToleranceConfig[i][1] = max; } else { Slog.wtf(TAG, "config_autoRotationTiltTolerance contains invalid range: " + "min=" + min + ", max=" + max); } } } else { Slog.wtf(TAG, "config_autoRotationTiltTolerance should have exactly 8 elements"); } } public int getProposedRotationLocked() { return mProposedRotation; } Loading @@ -451,6 +471,18 @@ public abstract class WindowOrientationListener { pw.println(prefix + "mAccelerating=" + mAccelerating); pw.println(prefix + "mOverhead=" + mOverhead); pw.println(prefix + "mTouched=" + mTouched); pw.print(prefix + "mTiltToleranceConfig=["); for (int i = 0; i < 4; i++) { if (i != 0) { pw.print(", "); } pw.print("["); pw.print(mTiltToleranceConfig[i][0]); pw.print(", "); pw.print(mTiltToleranceConfig[i][1]); pw.print("]"); } pw.println("]"); } @Override Loading Loading @@ -658,8 +690,8 @@ public abstract class WindowOrientationListener { * Returns true if the tilt angle is acceptable for a given predicted rotation. */ private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) { return tiltAngle >= TILT_TOLERANCE[rotation][0] && tiltAngle <= TILT_TOLERANCE[rotation][1]; return tiltAngle >= mTiltToleranceConfig[rotation][0] && tiltAngle <= mTiltToleranceConfig[rotation][1]; } /** Loading tools/orientationplot/README.txt +2 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ PREREQUISITES 2. numpy 3. matplotlib eg. sudo apt-get install python-numpy python-matplotlib USAGE ----- Loading tools/orientationplot/orientationplot.py +1 −1 Original line number Diff line number Diff line Loading @@ -440,7 +440,7 @@ class Plotter: # Notice print "Window Orientation Listener plotting tool" print "-----------------------------------------\n" print "Please turn on the Window Orientation Listener logging in Development Settings." print "Please turn on the Window Orientation Listener logging. See README.txt." # Start adb. print "Starting adb logcat.\n" Loading Loading
core/res/res/values/config.xml +37 −0 Original line number Diff line number Diff line Loading @@ -572,6 +572,43 @@ true here reverses that logic. --> <bool name="config_reverseDefaultRotation">false</bool> <!-- Sets the minimum and maximum tilt tolerance for each possible rotation. This array consists of 4 pairs of values which specify the minimum and maximum tilt angle at which the device will transition into each rotation. The tilt angle represents the direction in which the plane of the screen is facing; it is also known as the angle of elevation. -90 degree tilt means that the screen is facing straight down (the device is being held overhead upside-down) 0 degree tilt means that the screen is facing outwards (the device is being held vertically) 90 degree tilt means that the screen is facing straight up (the device is resting on a flat table) The default tolerances are set conservatively such that the device is more likely to remain in its natural orientation than rotate into a counterclockwise, clockwise, or reversed posture (with an especially strong bias against the latter) to prevent accidental rotation while carrying the device in hand. These thresholds may need to be tuned when the device is intended to be mounted into a dock with a particularly shallow profile wherein rotation would ordinarily have been suppressed. It is helpful to consider the desired behavior both when the device is being held at a positive tilt (typical case) vs. a negative tilt (reading overhead in bed) since they are quite different. In the overhead case, we typically want the device to more strongly prefer to retain its current configuration (in absence of a clear indication that a rotation is desired) since the user's head and neck may be held at an unusual angle. --> <integer-array name="config_autoRotationTiltTolerance"> <!-- rotation: 0 (natural) --> <item>-25</item> <item>70</item> <!-- rotation: 90 (rotate CCW) --> <item>-25</item> <item>65</item> <!-- rotation: 180 (reverse) --> <item>-25</item> <item>60</item> <!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item> </integer-array> <!-- Lid switch behavior --> <!-- The number of degrees to rotate the display when the keyboard is open. Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1451,6 +1451,7 @@ <java-symbol type="anim" name="voice_activity_open_exit" /> <java-symbol type="anim" name="voice_activity_open_enter" /> <java-symbol type="array" name="config_autoRotationTiltTolerance" /> <java-symbol type="array" name="config_keyboardTapVibePattern" /> <java-symbol type="array" name="config_longPressVibePattern" /> <java-symbol type="array" name="config_safeModeDisabledVibePattern" /> Loading
services/core/java/com/android/server/policy/WindowOrientationListener.java +63 −31 Original line number Diff line number Diff line Loading @@ -24,10 +24,10 @@ import android.hardware.SensorManager; import android.os.Handler; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import java.io.PrintWriter; import java.util.Arrays; /** * A special helper class used by the WindowManager Loading @@ -40,8 +40,6 @@ import java.io.PrintWriter; * * You can also visualize the behavior of the WindowOrientationListener. * Refer to frameworks/base/tools/orientationplot/README.txt for details. * * @hide */ public abstract class WindowOrientationListener { private static final String TAG = "WindowOrientationListener"; Loading Loading @@ -90,7 +88,7 @@ public abstract class WindowOrientationListener { ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER); if (mSensor != null) { // Create listener only if sensors do exist mSensorEventListener = new SensorEventListenerImpl(); mSensorEventListener = new SensorEventListenerImpl(context); } } Loading @@ -101,12 +99,12 @@ public abstract class WindowOrientationListener { public void enable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); Slog.w(TAG, "Cannot detect sensors. Not enabled"); return; } if (mEnabled == false) { if (LOG) { Log.d(TAG, "WindowOrientationListener enabled"); Slog.d(TAG, "WindowOrientationListener enabled"); } mSensorEventListener.resetLocked(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler); Loading @@ -121,12 +119,12 @@ public abstract class WindowOrientationListener { public void disable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); Slog.w(TAG, "Cannot detect sensors. Invalid disable"); return; } if (mEnabled == true) { if (LOG) { Log.d(TAG, "WindowOrientationListener disabled"); Slog.d(TAG, "WindowOrientationListener disabled"); } mSensorManager.unregisterListener(mSensorEventListener); mEnabled = false; Loading Loading @@ -296,7 +294,7 @@ public abstract class WindowOrientationListener { // If the tilt angle remains greater than the specified angle for a minimum of // the specified time, then the device is deemed to be lying flat // (just chillin' on a table). private static final float FLAT_ANGLE = 75; private static final float FLAT_ANGLE = 80; private static final long FLAT_TIME_NANOS = 1000 * NANOS_PER_MS; // If the tilt angle has increased by at least delta degrees within the specified amount Loading Loading @@ -361,8 +359,24 @@ public abstract class WindowOrientationListener { SensorManager.STANDARD_GRAVITY + ACCELERATION_TOLERANCE; // Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e. // when screen is facing the sky or ground), we completely ignore orientation data. private static final int MAX_TILT = 75; // when screen is facing the sky or ground), we completely ignore orientation data // because it's too unstable. private static final int MAX_TILT = 80; // The tilt angle below which we conclude that the user is holding the device // overhead reading in bed and lock into that state. private static final int TILT_OVERHEAD_ENTER = -40; // The tilt angle above which we conclude that the user would like a rotation // change to occur and unlock from the overhead state. private static final int TILT_OVERHEAD_EXIT = -15; // The gap angle in degrees between adjacent orientation angles for hysteresis. // This creates a "dead zone" between the current orientation and a proposed // adjacent orientation. No orientation proposal is made when the orientation // angle is within the gap between the current orientation and the adjacent // orientation. private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45; // The tilt angle range in degrees for each orientation. // Beyond these tilt angles, we don't even consider transitioning into the Loading @@ -375,28 +389,13 @@ public abstract class WindowOrientationListener { // facing up (resting on a table). // The ideal tilt angle is 0 (when the device is vertical) so the limits establish // how close to vertical the device must be in order to change orientation. private final int[][] TILT_TOLERANCE = new int[][] { /* ROTATION_0 */ { -25, 70 }, private final int[][] mTiltToleranceConfig = new int[][] { /* ROTATION_0 */ { -25, 70 }, // note: these are overridden by config.xml /* ROTATION_90 */ { -25, 65 }, /* ROTATION_180 */ { -25, 60 }, /* ROTATION_270 */ { -25, 65 } }; // The tilt angle below which we conclude that the user is holding the device // overhead reading in bed and lock into that state. private final int TILT_OVERHEAD_ENTER = -40; // The tilt angle above which we conclude that the user would like a rotation // change to occur and unlock from the overhead state. private final int TILT_OVERHEAD_EXIT = -15; // The gap angle in degrees between adjacent orientation angles for hysteresis. // This creates a "dead zone" between the current orientation and a proposed // adjacent orientation. No orientation proposal is made when the orientation // angle is within the gap between the current orientation and the adjacent // orientation. private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45; // Timestamp and value of the last accelerometer sample. private long mLastFilteredTimestampNanos; private float mLastFilteredX, mLastFilteredY, mLastFilteredZ; Loading Loading @@ -430,11 +429,32 @@ public abstract class WindowOrientationListener { private boolean mOverhead; // History of observed tilt angles. private static final int TILT_HISTORY_SIZE = 40; private static final int TILT_HISTORY_SIZE = 200; private float[] mTiltHistory = new float[TILT_HISTORY_SIZE]; private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE]; private int mTiltHistoryIndex; public SensorEventListenerImpl(Context context) { // Load tilt tolerance configuration. int[] tiltTolerance = context.getResources().getIntArray( com.android.internal.R.array.config_autoRotationTiltTolerance); if (tiltTolerance.length == 8) { for (int i = 0; i < 4; i++) { int min = tiltTolerance[i * 2]; int max = tiltTolerance[i * 2 + 1]; if (min >= -90 && min <= max && max <= 90) { mTiltToleranceConfig[i][0] = min; mTiltToleranceConfig[i][1] = max; } else { Slog.wtf(TAG, "config_autoRotationTiltTolerance contains invalid range: " + "min=" + min + ", max=" + max); } } } else { Slog.wtf(TAG, "config_autoRotationTiltTolerance should have exactly 8 elements"); } } public int getProposedRotationLocked() { return mProposedRotation; } Loading @@ -451,6 +471,18 @@ public abstract class WindowOrientationListener { pw.println(prefix + "mAccelerating=" + mAccelerating); pw.println(prefix + "mOverhead=" + mOverhead); pw.println(prefix + "mTouched=" + mTouched); pw.print(prefix + "mTiltToleranceConfig=["); for (int i = 0; i < 4; i++) { if (i != 0) { pw.print(", "); } pw.print("["); pw.print(mTiltToleranceConfig[i][0]); pw.print(", "); pw.print(mTiltToleranceConfig[i][1]); pw.print("]"); } pw.println("]"); } @Override Loading Loading @@ -658,8 +690,8 @@ public abstract class WindowOrientationListener { * Returns true if the tilt angle is acceptable for a given predicted rotation. */ private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) { return tiltAngle >= TILT_TOLERANCE[rotation][0] && tiltAngle <= TILT_TOLERANCE[rotation][1]; return tiltAngle >= mTiltToleranceConfig[rotation][0] && tiltAngle <= mTiltToleranceConfig[rotation][1]; } /** Loading
tools/orientationplot/README.txt +2 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ PREREQUISITES 2. numpy 3. matplotlib eg. sudo apt-get install python-numpy python-matplotlib USAGE ----- Loading
tools/orientationplot/orientationplot.py +1 −1 Original line number Diff line number Diff line Loading @@ -440,7 +440,7 @@ class Plotter: # Notice print "Window Orientation Listener plotting tool" print "-----------------------------------------\n" print "Please turn on the Window Orientation Listener logging in Development Settings." print "Please turn on the Window Orientation Listener logging. See README.txt." # Start adb. print "Starting adb logcat.\n" Loading