am fbcd78e6: Merge "Add support for new window orientation sensor." into mnc-dr-dev
* commit 'fbcd78e6ed5cd0ba3c231aa412ad5b07dd2faa44': Add support for new window orientation sensor.
This commit is contained in:
@@ -619,6 +619,17 @@
|
|||||||
<!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item>
|
<!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- Indicate the name of the window orientation sensor type if present. A
|
||||||
|
window orientation sensor produces values to be used in lieu of the
|
||||||
|
typical, accelerometer based sensor. It must only produce integral
|
||||||
|
values between 0 and 3, inclusive, with each one corresponding to a
|
||||||
|
given rotation:
|
||||||
|
0: 0 degrees of rotation (natural)
|
||||||
|
1: 90 degrees of rotation (rotate CCW)
|
||||||
|
2: 180 degrees of rotation (reverse)
|
||||||
|
3: 270 degrees of rotation (rotate CW) -->
|
||||||
|
<string name="config_orientationSensorType" translatable="false">@null</string>
|
||||||
|
|
||||||
<!-- Lid switch behavior -->
|
<!-- Lid switch behavior -->
|
||||||
|
|
||||||
<!-- The number of degrees to rotate the display when the keyboard is open.
|
<!-- The number of degrees to rotate the display when the keyboard is open.
|
||||||
|
|||||||
@@ -1547,6 +1547,7 @@
|
|||||||
<java-symbol type="string" name="bugreport_title" />
|
<java-symbol type="string" name="bugreport_title" />
|
||||||
<java-symbol type="string" name="bugreport_message" />
|
<java-symbol type="string" name="bugreport_message" />
|
||||||
<java-symbol type="string" name="bugreport_status" />
|
<java-symbol type="string" name="bugreport_status" />
|
||||||
|
<java-symbol type="string" name="config_orientationSensorType" />
|
||||||
<java-symbol type="string" name="faceunlock_multiple_failures" />
|
<java-symbol type="string" name="faceunlock_multiple_failures" />
|
||||||
<java-symbol type="string" name="global_action_power_off" />
|
<java-symbol type="string" name="global_action_power_off" />
|
||||||
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
|
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ import android.hardware.SensorManager;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A special helper class used by the WindowManager
|
* A special helper class used by the WindowManager
|
||||||
@@ -52,8 +54,9 @@ public abstract class WindowOrientationListener {
|
|||||||
private SensorManager mSensorManager;
|
private SensorManager mSensorManager;
|
||||||
private boolean mEnabled;
|
private boolean mEnabled;
|
||||||
private int mRate;
|
private int mRate;
|
||||||
|
private String mSensorType;
|
||||||
private Sensor mSensor;
|
private Sensor mSensor;
|
||||||
private SensorEventListenerImpl mSensorEventListener;
|
private OrientationJudge mOrientationJudge;
|
||||||
private int mCurrentRotation = -1;
|
private int mCurrentRotation = -1;
|
||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@@ -67,7 +70,7 @@ public abstract class WindowOrientationListener {
|
|||||||
public WindowOrientationListener(Context context, Handler handler) {
|
public WindowOrientationListener(Context context, Handler handler) {
|
||||||
this(context, handler, SensorManager.SENSOR_DELAY_UI);
|
this(context, handler, SensorManager.SENSOR_DELAY_UI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new WindowOrientationListener.
|
* Creates a new WindowOrientationListener.
|
||||||
*
|
*
|
||||||
@@ -84,11 +87,31 @@ public abstract class WindowOrientationListener {
|
|||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
|
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
|
||||||
mRate = rate;
|
mRate = rate;
|
||||||
mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
|
|
||||||
? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
|
mSensorType = context.getResources().getString(
|
||||||
if (mSensor != null) {
|
com.android.internal.R.string.config_orientationSensorType);
|
||||||
// Create listener only if sensors do exist
|
if (!TextUtils.isEmpty(mSensorType)) {
|
||||||
mSensorEventListener = new SensorEventListenerImpl(context);
|
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
|
||||||
|
final int N = sensors.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
Sensor sensor = sensors.get(i);
|
||||||
|
if (mSensorType.equals(sensor.getStringType())) {
|
||||||
|
mSensor = sensor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mSensor != null) {
|
||||||
|
mOrientationJudge = new OrientationSensorJudge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOrientationJudge == null) {
|
||||||
|
mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
|
||||||
|
? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
|
||||||
|
if (mSensor != null) {
|
||||||
|
// Create listener only if sensors do exist
|
||||||
|
mOrientationJudge = new AccelSensorJudge(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +129,8 @@ public abstract class WindowOrientationListener {
|
|||||||
if (LOG) {
|
if (LOG) {
|
||||||
Slog.d(TAG, "WindowOrientationListener enabled");
|
Slog.d(TAG, "WindowOrientationListener enabled");
|
||||||
}
|
}
|
||||||
mSensorEventListener.resetLocked();
|
mOrientationJudge.resetLocked();
|
||||||
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler);
|
mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler);
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +149,7 @@ public abstract class WindowOrientationListener {
|
|||||||
if (LOG) {
|
if (LOG) {
|
||||||
Slog.d(TAG, "WindowOrientationListener disabled");
|
Slog.d(TAG, "WindowOrientationListener disabled");
|
||||||
}
|
}
|
||||||
mSensorManager.unregisterListener(mSensorEventListener);
|
mSensorManager.unregisterListener(mOrientationJudge);
|
||||||
mEnabled = false;
|
mEnabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,8 +157,8 @@ public abstract class WindowOrientationListener {
|
|||||||
|
|
||||||
public void onTouchStart() {
|
public void onTouchStart() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mSensorEventListener != null) {
|
if (mOrientationJudge != null) {
|
||||||
mSensorEventListener.onTouchStartLocked();
|
mOrientationJudge.onTouchStartLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,8 +167,8 @@ public abstract class WindowOrientationListener {
|
|||||||
long whenElapsedNanos = SystemClock.elapsedRealtimeNanos();
|
long whenElapsedNanos = SystemClock.elapsedRealtimeNanos();
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mSensorEventListener != null) {
|
if (mOrientationJudge != null) {
|
||||||
mSensorEventListener.onTouchEndLocked(whenElapsedNanos);
|
mOrientationJudge.onTouchEndLocked(whenElapsedNanos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +195,7 @@ public abstract class WindowOrientationListener {
|
|||||||
public int getProposedRotation() {
|
public int getProposedRotation() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mEnabled) {
|
if (mEnabled) {
|
||||||
return mSensorEventListener.getProposedRotationLocked();
|
return mOrientationJudge.getProposedRotationLocked();
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -205,15 +228,77 @@ public abstract class WindowOrientationListener {
|
|||||||
prefix += " ";
|
prefix += " ";
|
||||||
pw.println(prefix + "mEnabled=" + mEnabled);
|
pw.println(prefix + "mEnabled=" + mEnabled);
|
||||||
pw.println(prefix + "mCurrentRotation=" + mCurrentRotation);
|
pw.println(prefix + "mCurrentRotation=" + mCurrentRotation);
|
||||||
|
pw.println(prefix + "mSensorType=" + mSensorType);
|
||||||
pw.println(prefix + "mSensor=" + mSensor);
|
pw.println(prefix + "mSensor=" + mSensor);
|
||||||
pw.println(prefix + "mRate=" + mRate);
|
pw.println(prefix + "mRate=" + mRate);
|
||||||
|
|
||||||
if (mSensorEventListener != null) {
|
if (mOrientationJudge != null) {
|
||||||
mSensorEventListener.dumpLocked(pw, prefix);
|
mOrientationJudge.dumpLocked(pw, prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class OrientationJudge implements SensorEventListener {
|
||||||
|
// Number of nanoseconds per millisecond.
|
||||||
|
protected static final long NANOS_PER_MS = 1000000;
|
||||||
|
|
||||||
|
// Number of milliseconds per nano second.
|
||||||
|
protected static final float MILLIS_PER_NANO = 0.000001f;
|
||||||
|
|
||||||
|
// The minimum amount of time that must have elapsed since the screen was last touched
|
||||||
|
// before the proposed rotation can change.
|
||||||
|
protected static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
|
||||||
|
500 * NANOS_PER_MS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the proposed rotation.
|
||||||
|
*
|
||||||
|
* This method only returns a rotation if the orientation listener is certain
|
||||||
|
* of its proposal. If the rotation is indeterminate, returns -1.
|
||||||
|
*
|
||||||
|
* Should only be called when holding WindowOrientationListener lock.
|
||||||
|
*
|
||||||
|
* @return The proposed rotation, or -1 if unknown.
|
||||||
|
*/
|
||||||
|
public abstract int getProposedRotationLocked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the orientation judge that the screen is being touched.
|
||||||
|
*
|
||||||
|
* Should only be called when holding WindowOrientationListener lock.
|
||||||
|
*/
|
||||||
|
public abstract void onTouchStartLocked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the orientation judge that the screen is no longer being touched.
|
||||||
|
*
|
||||||
|
* Should only be called when holding WindowOrientationListener lock.
|
||||||
|
*
|
||||||
|
* @param whenElapsedNanos Given in the elapsed realtime nanos time base.
|
||||||
|
*/
|
||||||
|
public abstract void onTouchEndLocked(long whenElapsedNanos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the state of the judge.
|
||||||
|
*
|
||||||
|
* Should only be called when holding WindowOrientationListener lock.
|
||||||
|
*/
|
||||||
|
public abstract void resetLocked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps internal state of the orientation judge.
|
||||||
|
*
|
||||||
|
* Should only be called when holding WindowOrientationListener lock.
|
||||||
|
*/
|
||||||
|
public abstract void dumpLocked(PrintWriter pw, String prefix);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void onAccuracyChanged(Sensor sensor, int accuracy);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void onSensorChanged(SensorEvent event);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class filters the raw accelerometer data and tries to detect actual changes in
|
* This class filters the raw accelerometer data and tries to detect actual changes in
|
||||||
* orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
|
* orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
|
||||||
@@ -252,13 +337,10 @@ public abstract class WindowOrientationListener {
|
|||||||
* See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for
|
* See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for
|
||||||
* signal processing background.
|
* signal processing background.
|
||||||
*/
|
*/
|
||||||
final class SensorEventListenerImpl implements SensorEventListener {
|
final class AccelSensorJudge extends OrientationJudge {
|
||||||
// We work with all angles in degrees in this class.
|
// We work with all angles in degrees in this class.
|
||||||
private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
|
private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
|
||||||
|
|
||||||
// Number of nanoseconds per millisecond.
|
|
||||||
private static final long NANOS_PER_MS = 1000000;
|
|
||||||
|
|
||||||
// Indices into SensorEvent.values for the accelerometer sensor.
|
// Indices into SensorEvent.values for the accelerometer sensor.
|
||||||
private static final int ACCELEROMETER_DATA_X = 0;
|
private static final int ACCELEROMETER_DATA_X = 0;
|
||||||
private static final int ACCELEROMETER_DATA_Y = 1;
|
private static final int ACCELEROMETER_DATA_Y = 1;
|
||||||
@@ -286,11 +368,6 @@ public abstract class WindowOrientationListener {
|
|||||||
private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
|
private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
|
||||||
500 * NANOS_PER_MS;
|
500 * NANOS_PER_MS;
|
||||||
|
|
||||||
// The minimum amount of time that must have elapsed since the screen was last touched
|
|
||||||
// before the proposed rotation can change.
|
|
||||||
private static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
|
|
||||||
500 * NANOS_PER_MS;
|
|
||||||
|
|
||||||
// If the tilt angle remains greater than the specified angle for a minimum of
|
// 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
|
// the specified time, then the device is deemed to be lying flat
|
||||||
// (just chillin' on a table).
|
// (just chillin' on a table).
|
||||||
@@ -434,7 +511,7 @@ public abstract class WindowOrientationListener {
|
|||||||
private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
|
private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
|
||||||
private int mTiltHistoryIndex;
|
private int mTiltHistoryIndex;
|
||||||
|
|
||||||
public SensorEventListenerImpl(Context context) {
|
public AccelSensorJudge(Context context) {
|
||||||
// Load tilt tolerance configuration.
|
// Load tilt tolerance configuration.
|
||||||
int[] tiltTolerance = context.getResources().getIntArray(
|
int[] tiltTolerance = context.getResources().getIntArray(
|
||||||
com.android.internal.R.array.config_autoRotationTiltTolerance);
|
com.android.internal.R.array.config_autoRotationTiltTolerance);
|
||||||
@@ -455,11 +532,15 @@ public abstract class WindowOrientationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getProposedRotationLocked() {
|
public int getProposedRotationLocked() {
|
||||||
return mProposedRotation;
|
return mProposedRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dumpLocked(PrintWriter pw, String prefix) {
|
public void dumpLocked(PrintWriter pw, String prefix) {
|
||||||
|
pw.println(prefix + "AccelSensorJudge");
|
||||||
|
prefix += " ";
|
||||||
pw.println(prefix + "mProposedRotation=" + mProposedRotation);
|
pw.println(prefix + "mProposedRotation=" + mProposedRotation);
|
||||||
pw.println(prefix + "mPredictedRotation=" + mPredictedRotation);
|
pw.println(prefix + "mPredictedRotation=" + mPredictedRotation);
|
||||||
pw.println(prefix + "mLastFilteredX=" + mLastFilteredX);
|
pw.println(prefix + "mLastFilteredX=" + mLastFilteredX);
|
||||||
@@ -689,6 +770,33 @@ public abstract class WindowOrientationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTouchStartLocked() {
|
||||||
|
mTouched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTouchEndLocked(long whenElapsedNanos) {
|
||||||
|
mTouched = false;
|
||||||
|
mTouchEndedTimestampNanos = whenElapsedNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLocked() {
|
||||||
|
mLastFilteredTimestampNanos = Long.MIN_VALUE;
|
||||||
|
mProposedRotation = -1;
|
||||||
|
mFlatTimestampNanos = Long.MIN_VALUE;
|
||||||
|
mFlat = false;
|
||||||
|
mSwingTimestampNanos = Long.MIN_VALUE;
|
||||||
|
mSwinging = false;
|
||||||
|
mAccelerationTimestampNanos = Long.MIN_VALUE;
|
||||||
|
mAccelerating = false;
|
||||||
|
mOverhead = false;
|
||||||
|
clearPredictedRotationLocked();
|
||||||
|
clearTiltHistoryLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the tilt angle is acceptable for a given predicted rotation.
|
* Returns true if the tilt angle is acceptable for a given predicted rotation.
|
||||||
*/
|
*/
|
||||||
@@ -787,20 +895,6 @@ public abstract class WindowOrientationListener {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetLocked() {
|
|
||||||
mLastFilteredTimestampNanos = Long.MIN_VALUE;
|
|
||||||
mProposedRotation = -1;
|
|
||||||
mFlatTimestampNanos = Long.MIN_VALUE;
|
|
||||||
mFlat = false;
|
|
||||||
mSwingTimestampNanos = Long.MIN_VALUE;
|
|
||||||
mSwinging = false;
|
|
||||||
mAccelerationTimestampNanos = Long.MIN_VALUE;
|
|
||||||
mAccelerating = false;
|
|
||||||
mOverhead = false;
|
|
||||||
clearPredictedRotationLocked();
|
|
||||||
clearTiltHistoryLocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearPredictedRotationLocked() {
|
private void clearPredictedRotationLocked() {
|
||||||
mPredictedRotation = -1;
|
mPredictedRotation = -1;
|
||||||
mPredictedRotationTimestampNanos = Long.MIN_VALUE;
|
mPredictedRotationTimestampNanos = Long.MIN_VALUE;
|
||||||
@@ -869,14 +963,138 @@ public abstract class WindowOrientationListener {
|
|||||||
private float remainingMS(long now, long until) {
|
private float remainingMS(long now, long until) {
|
||||||
return now >= until ? 0 : (until - now) * 0.000001f;
|
return now >= until ? 0 : (until - now) * 0.000001f;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onTouchStartLocked() {
|
final class OrientationSensorJudge extends OrientationJudge {
|
||||||
mTouched = true;
|
private boolean mTouching;
|
||||||
|
private long mTouchEndedTimestampNanos = Long.MIN_VALUE;
|
||||||
|
private int mProposedRotation = -1;
|
||||||
|
private int mDesiredRotation = -1;
|
||||||
|
private boolean mRotationEvaluationScheduled;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getProposedRotationLocked() {
|
||||||
|
return mProposedRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTouchEndLocked(long whenElapsedNanos) {
|
@Override
|
||||||
mTouched = false;
|
public void onTouchStartLocked() {
|
||||||
|
mTouching = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTouchEndLocked(long whenElapsedNanos) {
|
||||||
|
mTouching = false;
|
||||||
mTouchEndedTimestampNanos = whenElapsedNanos;
|
mTouchEndedTimestampNanos = whenElapsedNanos;
|
||||||
|
if (mDesiredRotation != mProposedRotation) {
|
||||||
|
final long now = SystemClock.elapsedRealtimeNanos();
|
||||||
|
scheduleRotationEvaluationIfNecessaryLocked(now);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSensorChanged(SensorEvent event) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mDesiredRotation = (int) event.values[0];
|
||||||
|
evaluateRotationChangeLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dumpLocked(PrintWriter pw, String prefix) {
|
||||||
|
pw.println(prefix + "OrientationSensorJudge");
|
||||||
|
prefix += " ";
|
||||||
|
pw.println(prefix + "mDesiredRotation=" + mDesiredRotation);
|
||||||
|
pw.println(prefix + "mProposedRotation=" + mProposedRotation);
|
||||||
|
pw.println(prefix + "mTouching=" + mTouching);
|
||||||
|
pw.println(prefix + "mTouchEndedTimestampNanos=" + mTouchEndedTimestampNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLocked() {
|
||||||
|
mProposedRotation = -1;
|
||||||
|
mDesiredRotation = -1;
|
||||||
|
mTouching = false;
|
||||||
|
mTouchEndedTimestampNanos = Long.MIN_VALUE;
|
||||||
|
unscheduleRotationEvaluationLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evaluateRotationChangeLocked() {
|
||||||
|
unscheduleRotationEvaluationLocked();
|
||||||
|
if (mDesiredRotation == mProposedRotation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final long now = SystemClock.elapsedRealtimeNanos();
|
||||||
|
if (isDesiredRotationAcceptableLocked(now)) {
|
||||||
|
mProposedRotation = mDesiredRotation;
|
||||||
|
onProposedRotationChanged(mProposedRotation);
|
||||||
|
} else {
|
||||||
|
scheduleRotationEvaluationIfNecessaryLocked(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDesiredRotationAcceptableLocked(long now) {
|
||||||
|
if (mTouching) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (now < mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleRotationEvaluationIfNecessaryLocked(long now) {
|
||||||
|
if (mRotationEvaluationScheduled || mDesiredRotation == mProposedRotation) {
|
||||||
|
if (LOG) {
|
||||||
|
Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
|
||||||
|
"ignoring, an evaluation is already scheduled or is unnecessary.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mTouching) {
|
||||||
|
if (LOG) {
|
||||||
|
Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
|
||||||
|
"ignoring, user is still touching the screen.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long timeOfNextPossibleRotationNanos =
|
||||||
|
mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS;
|
||||||
|
if (now >= timeOfNextPossibleRotationNanos) {
|
||||||
|
if (LOG) {
|
||||||
|
Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
|
||||||
|
"ignoring, already past the next possible time of rotation.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Use a delay instead of an absolute time since handlers are in uptime millis and we
|
||||||
|
// use elapsed realtime.
|
||||||
|
final long delayMs =
|
||||||
|
(long) Math.ceil((timeOfNextPossibleRotationNanos - now) * MILLIS_PER_NANO);
|
||||||
|
mHandler.postDelayed(mRotationEvaluator, delayMs);
|
||||||
|
mRotationEvaluationScheduled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unscheduleRotationEvaluationLocked() {
|
||||||
|
if (!mRotationEvaluationScheduled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mHandler.removeCallbacks(mRotationEvaluator);
|
||||||
|
mRotationEvaluationScheduled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable mRotationEvaluator = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mRotationEvaluationScheduled = false;
|
||||||
|
evaluateRotationChangeLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user