Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a51ba9b authored by Riddle Hsu's avatar Riddle Hsu
Browse files

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
parent 9736fb2a
Loading
Loading
Loading
Loading
+23 −40
Original line number Diff line number Diff line
@@ -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 {
+7 −2
Original line number Diff line number Diff line
@@ -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);
        try {
            return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ignored) {
        }
        throw new AssertionError("Failed to wait for ui handler");
    }

    @Test