diff options
9 files changed, 161 insertions, 31 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 5e367046bd2b..65729372363a 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -34,6 +34,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.wakelock.DelayedWakeLock; @@ -56,6 +57,7 @@ public class DozeFactory { private final ProximitySensor mProximitySensor; private final DelayedWakeLock.Builder mDelayedWakeLockBuilder; private final Handler mHandler; + private final DelayableExecutor mDelayableExecutor; private final BiometricUnlockController mBiometricUnlockController; private final BroadcastDispatcher mBroadcastDispatcher; private final DozeHost mDozeHost; @@ -68,6 +70,7 @@ public class DozeFactory { DockManager dockManager, @Nullable IWallpaperManager wallpaperManager, ProximitySensor proximitySensor, DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler, + DelayableExecutor delayableExecutor, BiometricUnlockController biometricUnlockController, BroadcastDispatcher broadcastDispatcher, DozeHost dozeHost) { mFalsingManager = falsingManager; @@ -83,6 +86,7 @@ public class DozeFactory { mProximitySensor = proximitySensor; mDelayedWakeLockBuilder = delayedWakeLockBuilder; mHandler = handler; + mDelayableExecutor = delayableExecutor; mBiometricUnlockController = biometricUnlockController; mBroadcastDispatcher = broadcastDispatcher; mDozeHost = dozeHost; @@ -107,8 +111,8 @@ public class DozeFactory { new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()), new DozeFalsingManagerAdapter(mFalsingManager), createDozeTriggers(dozeService, mAsyncSensorManager, mDozeHost, - mAlarmManager, config, mDozeParameters, mHandler, wakeLock, machine, - mDockManager, mDozeLog), + mAlarmManager, config, mDozeParameters, mDelayableExecutor, wakeLock, + machine, mDockManager, mDozeLog), createDozeUi(dozeService, mDozeHost, wakeLock, machine, mHandler, mAlarmManager, mDozeParameters, mDozeLog), new DozeScreenState(wrappedService, mHandler, mDozeHost, mDozeParameters, @@ -135,11 +139,11 @@ public class DozeFactory { private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager, DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config, - DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine, - DockManager dockManager, DozeLog dozeLog) { + DozeParameters params, DelayableExecutor delayableExecutor, WakeLock wakeLock, + DozeMachine machine, DockManager dockManager, DozeLog dozeLog) { boolean allowPulseTriggers = true; return new DozeTriggers(context, machine, host, alarmManager, config, params, - sensorManager, handler, wakeLock, allowPulseTriggers, dockManager, + sensorManager, delayableExecutor, wakeLock, allowPulseTriggers, dockManager, mProximitySensor, dozeLog, mBroadcastDispatcher); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index e1081cd5ef82..78f8f673cab9 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -101,7 +101,8 @@ public class DozeSensors { public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager, DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock, - Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog) { + Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog, + ProximitySensor proximitySensor) { mContext = context; mAlarmManager = alarmManager; mSensorManager = sensorManager; @@ -111,6 +112,7 @@ public class DozeSensors { mProxCallback = proxCallback; mResolver = mContext.getContentResolver(); mCallback = callback; + mProximitySensor = proximitySensor; boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT); mSensors = new TriggerSensor[] { @@ -173,7 +175,6 @@ public class DozeSensors { dozeLog), }; - mProximitySensor = new ProximitySensor(context.getResources(), sensorManager); setProxListening(false); // Don't immediately start listening when we register. mProximitySensor.register( proximityEvent -> { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 3510e07d2cea..6a5501445a4d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -26,7 +26,6 @@ import android.content.IntentFilter; import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.metrics.LogMaker; -import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.Formatter; @@ -43,6 +42,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.Assert; +import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.wakelock.WakeLock; @@ -152,9 +152,9 @@ public class DozeTriggers implements DozeMachine.Part { public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost, AlarmManager alarmManager, AmbientDisplayConfiguration config, - DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler, - WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager, - ProximitySensor proximitySensor, + DozeParameters dozeParameters, AsyncSensorManager sensorManager, + DelayableExecutor delayableExecutor, WakeLock wakeLock, boolean allowPulseTriggers, + DockManager dockManager, ProximitySensor proximitySensor, DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) { mContext = context; mMachine = machine; @@ -165,10 +165,10 @@ public class DozeTriggers implements DozeMachine.Part { mWakeLock = wakeLock; mAllowPulseTriggers = allowPulseTriggers; mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters, - config, wakeLock, this::onSensor, this::onProximityFar, dozeLog); + config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor); mUiModeManager = mContext.getSystemService(UiModeManager.class); mDockManager = dockManager; - mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler); + mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, delayableExecutor); mDozeLog = dozeLog; mBroadcastDispatcher = broadcastDispatcher; } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index 378dde284747..708b5a7a45f7 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -21,16 +21,17 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; -import android.os.Handler; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import javax.inject.Inject; @@ -49,8 +50,9 @@ public class ProximitySensor { private String mTag = null; @VisibleForTesting ProximityEvent mLastEvent; private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL; - private boolean mPaused; + @VisibleForTesting protected boolean mPaused; private boolean mRegistered; + private final AtomicBoolean mAlerting = new AtomicBoolean(); private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override @@ -217,8 +219,12 @@ public class ProximitySensor { /** Update all listeners with the last value this class received from the sensor. */ public void alertListeners() { + if (mAlerting.getAndSet(true)) { + return; + } mListeners.forEach(proximitySensorListener -> proximitySensorListener.onSensorEvent(mLastEvent)); + mAlerting.set(false); } private void onSensorEvent(SensorEvent event) { @@ -239,14 +245,14 @@ public class ProximitySensor { public static class ProximityCheck implements Runnable { private final ProximitySensor mSensor; - private final Handler mHandler; + private final DelayableExecutor mDelayableExecutor; private List<Consumer<Boolean>> mCallbacks = new ArrayList<>(); @Inject - public ProximityCheck(ProximitySensor sensor, Handler handler) { + public ProximityCheck(ProximitySensor sensor, DelayableExecutor delayableExecutor) { mSensor = sensor; mSensor.setTag("prox_check"); - mHandler = handler; + mDelayableExecutor = delayableExecutor; mSensor.pause(); ProximitySensorListener listener = proximityEvent -> { mCallbacks.forEach( @@ -280,7 +286,7 @@ public class ProximitySensor { mCallbacks.add(callback); if (!mSensor.isRegistered()) { mSensor.resume(); - mHandler.postDelayed(this, timeoutMs); + mDelayableExecutor.executeDelayed(this, timeoutMs); } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 317500cf5b02..a5675360a57e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -18,6 +18,7 @@ package com.android.systemui.doze; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN; +import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; @@ -46,6 +47,7 @@ import com.android.systemui.doze.DozeSensors.TriggerSensor; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.sensors.AsyncSensorManager; +import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.wakelock.WakeLock; import org.junit.Before; @@ -82,7 +84,7 @@ public class DozeSensorsTest extends SysuiTestCase { @Mock private DozeLog mDozeLog; @Mock - private Sensor mProximitySensor; + private ProximitySensor mProximitySensor; private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener; private TestableLooper mTestableLooper; private DozeSensors mDozeSensors; @@ -93,7 +95,6 @@ public class DozeSensorsTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L); when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true); - when(mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)).thenReturn(mProximitySensor); doAnswer(invocation -> { ((Runnable) invocation.getArgument(0)).run(); return null; @@ -103,10 +104,9 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testRegisterProx() { - // We should not register with the sensor manager initially. - verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt()); + assertFalse(mProximitySensor.isRegistered()); mDozeSensors.setProxListening(true); - verify(mSensorManager).registerListener(any(), any(Sensor.class), anyInt()); + verify(mProximitySensor).resume(); } @Test @@ -169,7 +169,8 @@ public class DozeSensorsTest extends SysuiTestCase { TestableDozeSensors() { super(getContext(), mAlarmManager, mSensorManager, mDozeParameters, - mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog); + mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog, + mProximitySensor); for (TriggerSensor sensor : mSensors) { if (sensor instanceof PluginSensor && ((PluginSensor) sensor).mPluginSensor.getType() diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index debc9d6430e0..73aaeffd6044 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -31,7 +31,6 @@ import android.app.AlarmManager; import android.hardware.Sensor; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Handler; -import android.os.Looper; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; @@ -42,10 +41,12 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.FakeProximitySensor; import com.android.systemui.util.sensors.FakeSensorManager; import com.android.systemui.util.sensors.ProximitySensor; +import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.wakelock.WakeLock; import com.android.systemui.util.wakelock.WakeLockFake; @@ -75,6 +76,7 @@ public class DozeTriggersTest extends SysuiTestCase { private FakeSensorManager mSensors; private Sensor mTapSensor; private FakeProximitySensor mProximitySensor; + private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); @Before public void setUp() throws Exception { @@ -89,7 +91,7 @@ public class DozeTriggersTest extends SysuiTestCase { mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager); mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters, - asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true, + asyncSensorManager, mFakeExecutor, wakeLock, true, mDockManager, mProximitySensor, mock(DozeLog.class), mBroadcastDispatcher); waitForSensorManager(); } @@ -111,9 +113,8 @@ public class DozeTriggersTest extends SysuiTestCase { verify(mMachine, never()).requestState(any()); verify(mMachine, never()).requestPulse(anyInt()); - captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */); - waitForSensorManager(); mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(false, 2)); + captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */); mProximitySensor.alertListeners(); verify(mMachine).requestPulse(anyInt()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java index 31d884c38f58..bd697fe394b5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java @@ -20,6 +20,7 @@ import android.content.res.Resources; public class FakeProximitySensor extends ProximitySensor { private boolean mAvailable; + private boolean mRegistered; public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) { super(resources, sensorManager); @@ -35,17 +36,22 @@ public class FakeProximitySensor extends ProximitySensor { } @Override + public boolean isRegistered() { + return mRegistered; + } + + @Override public boolean getSensorAvailable() { return mAvailable; } @Override protected void registerInternal() { - // no-op + mRegistered = !mPaused; } @Override protected void unregisterInternal() { - // no-op + mRegistered = false; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java new file mode 100644 index 000000000000..7221095a1eaf --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.sensors; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.os.Handler; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.function.Consumer; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class ProximityCheckTest extends SysuiTestCase { + + private FakeProximitySensor mFakeProximitySensor; + private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); + + private TestableCallback mTestableCallback = new TestableCallback(); + + private ProximitySensor.ProximityCheck mProximityCheck; + + @Before + public void setUp() throws Exception { + AsyncSensorManager asyncSensorManager = + new AsyncSensorManager(new FakeSensorManager(mContext), null, new Handler()); + mFakeProximitySensor = new FakeProximitySensor(mContext.getResources(), asyncSensorManager); + + mProximityCheck = new ProximitySensor.ProximityCheck(mFakeProximitySensor, mFakeExecutor); + } + + @Test + public void testCheck() { + mProximityCheck.check(100, mTestableCallback); + + assertNull(mTestableCallback.mLastResult); + + mFakeProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(true, 0)); + mFakeProximitySensor.alertListeners(); + + assertTrue(mTestableCallback.mLastResult); + } + + @Test + public void testTimeout() { + mProximityCheck.check(100, mTestableCallback); + + assertTrue(mFakeProximitySensor.isRegistered()); + + mFakeExecutor.advanceClockToNext(); + mFakeExecutor.runAllReady(); + + assertFalse(mFakeProximitySensor.isRegistered()); + } + + private static class TestableCallback implements Consumer<Boolean> { + Boolean mLastResult; + @Override + public void accept(Boolean result) { + mLastResult = result; + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java index 526fba726e9d..914790b53a82 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java @@ -219,6 +219,26 @@ public class ProximitySensorTest extends SysuiTestCase { waitForSensorManager(); } + @Test + public void testPreventRecursiveAlert() { + TestableListener listenerA = new TestableListener() { + @Override + public void onSensorEvent(ProximitySensor.ProximityEvent proximityEvent) { + super.onSensorEvent(proximityEvent); + if (mCallCount < 2) { + mProximitySensor.alertListeners(); + } + } + }; + + mProximitySensor.register(listenerA); + + mProximitySensor.alertListeners(); + + assertEquals(1, listenerA.mCallCount); + } + + class TestableListener implements ProximitySensor.ProximitySensorListener { ProximitySensor.ProximityEvent mLastEvent; int mCallCount = 0; |