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

Commit 591eab61 authored by Beverly's avatar Beverly
Browse files

Remove alarm (IPC) after traversal

To avoid an IPC on the main thread from blocking.

Test: observe trace (external/perfetto/tools/record_android_trace gfx
view freq sched wm am binder_driver -a com.android.systemui). There's
no blocking binder call on AlarmManager.remove during the updateDozing
transition.
Test: check DozeLog for time ticks
Test: atest DozeUiTest
Fixes: 236974182

Change-Id: I0d6d9dcbe89f769c9745936a6c91227a8f4c5288
parent 8cfba905
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -26,9 +26,9 @@ import android.os.SystemClock;
import android.text.format.Formatter;
import android.util.Log;

import com.android.systemui.DejankUtils;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
@@ -52,15 +52,21 @@ public class DozeUi implements DozeMachine.Part {
    private final boolean mCanAnimateTransition;
    private final DozeParameters mDozeParameters;
    private final DozeLog mDozeLog;
    private final StatusBarStateController mStatusBarStateController;

    private long mLastTimeTickElapsed = 0;
    // If time tick is scheduled and there's not a pending runnable to cancel:
    private boolean mTimeTickScheduled;
    private final Runnable mCancelTimeTickerRunnable =  new Runnable() {
        @Override
        public void run() {
            mTimeTicker.cancel();
        }
    };

    @Inject
    public DozeUi(Context context, AlarmManager alarmManager,
            WakeLock wakeLock, DozeHost host, @Main Handler handler,
            DozeParameters params,
            StatusBarStateController statusBarStateController,
            DozeLog dozeLog) {
        mContext = context;
        mWakeLock = wakeLock;
@@ -70,7 +76,6 @@ public class DozeUi implements DozeMachine.Part {
        mDozeParameters = params;
        mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
        mDozeLog = dozeLog;
        mStatusBarStateController = statusBarStateController;
    }

    @Override
@@ -157,13 +162,15 @@ public class DozeUi implements DozeMachine.Part {
    }

    private void scheduleTimeTick() {
        if (mTimeTicker.isScheduled()) {
        if (mTimeTickScheduled) {
            return;
        }
        mTimeTickScheduled = true;
        DejankUtils.removeCallbacks(mCancelTimeTickerRunnable);

        long time = System.currentTimeMillis();
        long delta = roundToNextMinute(time) - System.currentTimeMillis();
        boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
        boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_RESCHEDULE_IF_SCHEDULED);
        if (scheduled) {
            mDozeLog.traceTimeTickScheduled(time, time + delta);
        }
@@ -171,11 +178,11 @@ public class DozeUi implements DozeMachine.Part {
    }

    private void unscheduleTimeTick() {
        if (!mTimeTicker.isScheduled()) {
        if (!mTimeTickScheduled) {
            return;
        }
        verifyLastTimeTick();
        mTimeTicker.cancel();
        mTimeTickScheduled = false;
        DejankUtils.postAfterTraversal(mCancelTimeTickerRunnable);
    }

    private void verifyLastTimeTick() {
@@ -205,6 +212,7 @@ public class DozeUi implements DozeMachine.Part {
        // Keep wakelock until a frame has been pushed.
        mHandler.post(mWakeLock.wrap(() -> {}));

        mTimeTickScheduled = false;
        scheduleTimeTick();
    }
}
+7 −10
Original line number Diff line number Diff line
@@ -33,15 +33,14 @@ import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.testing.TestableLooper;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.wakelock.WakeLockFake;

import org.junit.After;
@@ -53,6 +52,7 @@ import org.mockito.MockitoAnnotations;

@RunWith(AndroidJUnit4.class)
@SmallTest
@TestableLooper.RunWithLooper
public class DozeUiTest extends SysuiTestCase {

    @Mock
@@ -62,23 +62,19 @@ public class DozeUiTest extends SysuiTestCase {
    @Mock
    private DozeParameters mDozeParameters;
    @Mock
    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    @Mock
    private DozeHost mHost;
    @Mock
    private DozeLog mDozeLog;
    @Mock
    private TunerService mTunerService;
    private WakeLockFake mWakeLock;
    private Handler mHandler;
    private HandlerThread mHandlerThread;
    private DozeUi mDozeUi;
    @Mock
    private StatusBarStateController mStatusBarStateController;

    @Before
    public void setUp() throws Exception {
        allowTestableLooperAsMainThread();
        MockitoAnnotations.initMocks(this);
        DejankUtils.setImmediate(true);

        mHandlerThread = new HandlerThread("DozeUiTest");
        mHandlerThread.start();
@@ -86,12 +82,13 @@ public class DozeUiTest extends SysuiTestCase {
        mHandler = mHandlerThread.getThreadHandler();

        mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
                mDozeParameters, mStatusBarStateController, mDozeLog);
                mDozeParameters, mDozeLog);
        mDozeUi.setDozeMachine(mMachine);
    }

    @After
    public void tearDown() throws Exception {
        DejankUtils.setImmediate(false);
        mHandlerThread.quit();
        mHandler = null;
        mHandlerThread = null;