Toggle orientation sensor outside of WM lock
Otherwise when turning on/off, the toggling of orientation sensor may spend time in IPC to HIDL::ISensors, which may block other callers to window manager service. Now the enable/disable are moved to the same thread (android.ui) that receives sensor events. Also remove UpdateRunnable because onProposedRotationChanged is already called on the handler thread. The original code just posts one more time. Bug: 225183104 Test: atest DisplayRotationTests Change-Id: I3d3b774fae1f5981533b79ebdbf6f651c803d511
This commit is contained in:
@@ -56,7 +56,6 @@ import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.IDisplayWindowRotationCallback;
|
||||
@@ -1024,13 +1023,7 @@ public class DisplayRotation {
|
||||
disable = false;
|
||||
// Enable listener if not already enabled.
|
||||
if (!mOrientationListener.mEnabled) {
|
||||
// Don't clear the current sensor orientation if the keyguard is going away in
|
||||
// dismiss mode. This allows window manager to use the last sensor reading to
|
||||
// determine the orientation vs. falling back to the last known orientation if
|
||||
// the sensor reading was cleared which can cause it to relaunch the app that
|
||||
// will show in the wrong orientation first before correcting leading to app
|
||||
// launch delays.
|
||||
mOrientationListener.enable(true /* clearCurrentRotation */);
|
||||
mOrientationListener.enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1560,35 +1553,13 @@ public class DisplayRotation {
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
private class OrientationListener extends WindowOrientationListener {
|
||||
final SparseArray<Runnable> mRunnableCache = new SparseArray<>(5);
|
||||
boolean mEnabled;
|
||||
private class OrientationListener extends WindowOrientationListener implements Runnable {
|
||||
transient boolean mEnabled;
|
||||
|
||||
OrientationListener(Context context, Handler handler) {
|
||||
super(context, handler);
|
||||
}
|
||||
|
||||
private class UpdateRunnable implements Runnable {
|
||||
final int mRotation;
|
||||
|
||||
UpdateRunnable(int rotation) {
|
||||
mRotation = rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Send interaction power boost to improve redraw performance.
|
||||
mService.mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
|
||||
if (isRotationChoicePossible(mCurrentAppOrientation)) {
|
||||
final boolean isValid = isValidRotationChoice(mRotation);
|
||||
sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
|
||||
} else {
|
||||
mService.updateRotation(false /* alwaysSendConfiguration */,
|
||||
false /* forceRelayout */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKeyguardLocked() {
|
||||
return mService.isKeyguardLocked();
|
||||
@@ -1605,27 +1576,39 @@ public class DisplayRotation {
|
||||
@Override
|
||||
public void onProposedRotationChanged(int rotation) {
|
||||
ProtoLog.v(WM_DEBUG_ORIENTATION, "onProposedRotationChanged, rotation=%d", rotation);
|
||||
Runnable r = mRunnableCache.get(rotation, null);
|
||||
if (r == null) {
|
||||
r = new UpdateRunnable(rotation);
|
||||
mRunnableCache.put(rotation, r);
|
||||
// Send interaction power boost to improve redraw performance.
|
||||
mService.mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
|
||||
if (isRotationChoicePossible(mCurrentAppOrientation)) {
|
||||
final boolean isValid = isValidRotationChoice(rotation);
|
||||
sendProposedRotationChangeToStatusBarInternal(rotation, isValid);
|
||||
} else {
|
||||
mService.updateRotation(false /* alwaysSendConfiguration */,
|
||||
false /* forceRelayout */);
|
||||
}
|
||||
getHandler().post(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable(boolean clearCurrentRotation) {
|
||||
super.enable(clearCurrentRotation);
|
||||
public void enable() {
|
||||
mEnabled = true;
|
||||
getHandler().post(this);
|
||||
ProtoLog.v(WM_DEBUG_ORIENTATION, "Enabling listeners");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
mEnabled = false;
|
||||
getHandler().post(this);
|
||||
ProtoLog.v(WM_DEBUG_ORIENTATION, "Disabling listeners");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mEnabled) {
|
||||
super.enable();
|
||||
} else {
|
||||
super.disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsObserver extends ContentObserver {
|
||||
|
||||
@@ -318,6 +318,7 @@ public class DisplayRotationTests {
|
||||
private void verifyOrientationListenerRegistration(int numOfInvocation) {
|
||||
final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(
|
||||
SensorEventListener.class);
|
||||
waitForUiHandler();
|
||||
verify(mMockSensorManager, times(numOfInvocation)).registerListener(
|
||||
listenerCaptor.capture(),
|
||||
same(mFakeSensor),
|
||||
@@ -478,10 +479,14 @@ public class DisplayRotationTests {
|
||||
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
|
||||
}
|
||||
|
||||
private boolean waitForUiHandler() throws Exception {
|
||||
private boolean waitForUiHandler() {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
UiThread.getHandler().post(latch::countDown);
|
||||
return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
try {
|
||||
return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
throw new AssertionError("Failed to wait for ui handler");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user