Polish sos gesture behind the lockscreen
Unlike camera, we only want one intent for the emergency action (rather
than a secure / insecure breakdown). The api startActivity didn't work
behind the keyguard (WAI, I believe) so this CL changes that approach
to start the activity more traditionally.
The existing test is unfortunately removed. In its implementation CL,
[ag/12721582] dupin@ and I discussed the best way to test the action
given we would either check the activity was started with the context
[mContext.startActivity] or from the ActivityStarter
[StatusBar#startActivity]. Unfortunately ActivityStarter doesn't work
for our use case given the Keyguard gets raised (what we're trying to
fix in this CL), so we're left with verifying the injected Context gets
called. In theory we could add a wrapper method and verify it gets
called, but that seems next-to-useless.
Bug: 172278542
Fixes: 171084088
Fixes: 175240607
Test: atest StatusBarTest
Change-Id: Idd855be8d8c9fd35691c32bf88b3b9e2cdbc7b50
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8f23824..41cba10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -574,6 +574,8 @@
private NotificationEntry mDraggedDownEntry;
private boolean mLaunchCameraWhenFinishedWaking;
private boolean mLaunchCameraOnFinishedGoingToSleep;
+ private boolean mLaunchEmergencyActionWhenFinishedWaking;
+ private boolean mLaunchEmergencyActionOnFinishedGoingToSleep;
private int mLastCameraLaunchSource;
protected PowerManager.WakeLock mGestureWakeLock;
private Vibrator mVibrator;
@@ -3844,6 +3846,14 @@
// is correct.
mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource));
}
+
+ if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
+ mLaunchEmergencyActionOnFinishedGoingToSleep = false;
+
+ // This gets executed before we will show Keyguard, so post it in order that the
+ // state is correct.
+ mHandler.post(() -> onEmergencyActionLaunchGestureDetected());
+ }
updateIsKeyguard();
}
@@ -3890,6 +3900,13 @@
false /* animate */, mLastCameraLaunchSource);
mLaunchCameraWhenFinishedWaking = false;
}
+ if (mLaunchEmergencyActionWhenFinishedWaking) {
+ mLaunchEmergencyActionWhenFinishedWaking = false;
+ Intent emergencyIntent = getEmergencyActionIntent();
+ if (emergencyIntent != null) {
+ mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
+ }
+ }
updateScrimController();
}
};
@@ -4027,20 +4044,65 @@
@Override
public void onEmergencyActionLaunchGestureDetected() {
- // TODO (b/169793384) Polish the panic gesture to be just like its older brother, camera.
+ Intent emergencyIntent = getEmergencyActionIntent();
+
+ if (emergencyIntent == null) {
+ Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+ return;
+ }
+
+ if (isGoingToSleep()) {
+ mLaunchEmergencyActionOnFinishedGoingToSleep = true;
+ return;
+ }
+
+ if (!mDeviceInteractive) {
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+ PowerManager.WAKE_REASON_GESTURE,
+ "com.android.systemui:EMERGENCY_GESTURE");
+ }
+ // TODO(b/169087248) Possibly add haptics here for emergency action. Currently disabled for
+ // app-side haptic experimentation.
+
+ if (!mStatusBarKeyguardViewManager.isShowing()) {
+ startActivityDismissingKeyguard(emergencyIntent,
+ false /* onlyProvisioned */, true /* dismissShade */,
+ true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0);
+ return;
+ }
+
+ if (!mDeviceInteractive) {
+ // Avoid flickering of the scrim when we instant launch the camera and the bouncer
+ // comes on.
+ mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
+ }
+
+ if (isWakingUpOrAwake()) {
+ if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ mStatusBarKeyguardViewManager.reset(true /* hide */);
+ }
+ mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
+ return;
+ }
+ // We need to defer the emergency action launch until the screen comes on, since otherwise
+ // we will dismiss us too early since we are waiting on an activity to be drawn and
+ // incorrectly get notified because of the screen on event (which resumes and pauses
+ // some activities)
+ mLaunchEmergencyActionWhenFinishedWaking = true;
+ }
+
+ private @Nullable Intent getEmergencyActionIntent() {
Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
PackageManager pm = mContext.getPackageManager();
ResolveInfo resolveInfo = pm.resolveActivity(emergencyIntent, /*flags=*/0);
if (resolveInfo == null) {
- // TODO(b/171084088) Upgrade log to wtf when we have default app in main branch.
- Log.d(TAG, "Couldn't find an app to process the emergency intent.");
- return;
+ Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+ return null;
}
-
emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
resolveInfo.activityInfo.name));
emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(emergencyIntent, /*dismissShade=*/true);
+ return emergencyIntent;
}
boolean isCameraAllowedByAdmin() {
@@ -4100,8 +4162,10 @@
ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
- } else if (isInLaunchTransition() || mLaunchCameraWhenFinishedWaking
+ } else if (isInLaunchTransition()
+ || mLaunchCameraWhenFinishedWaking
|| launchingAffordanceWithPreview) {
+ // TODO(b/170133395) Investigate whether Emergency Gesture flag should be included here.
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 8e84f1a..51ce8e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -24,7 +24,6 @@
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.fail;
-import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -35,7 +34,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -45,7 +43,6 @@
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
-import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.fingerprint.FingerprintManager;
@@ -87,7 +84,6 @@
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.emergency.EmergencyGesture;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -151,10 +147,8 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -887,19 +881,6 @@
verify(mDozeServiceHost).setDozeSuppressed(false);
}
- @Ignore // TODO (b/175240607) - Figure out if the device will actually dial 911.
- @Test
- public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() {
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- StatusBar statusBarSpy = spy(mStatusBar);
-
- statusBarSpy.onEmergencyActionLaunchGestureDetected();
-
- verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true));
- Intent sentIntent = intentCaptor.getValue();
- assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
- }
-
public static class TestableNotificationInterruptStateProviderImpl extends
NotificationInterruptStateProviderImpl {