From 4aad491d8887c0d9daccaf7d11ddc422e6d5b495 Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Thu, 10 Dec 2020 16:25:29 -0800 Subject: [PATCH] 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 --- .../systemui/statusbar/phone/StatusBar.java | 78 +++++++++++++++++-- .../statusbar/phone/StatusBarTest.java | 19 ----- 2 files changed, 71 insertions(+), 26 deletions(-) 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 8f2382486abd1..41cba10596a11 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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 @@ public class StatusBar extends SystemUI implements DemoMode, // 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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 @@ public class StatusBar extends SystemUI implements DemoMode, @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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 8e84f1a4e843d..51ce8e59e9995 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.assertFalse; 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.doAnswer; 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.StatusBarManager; 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.FalsingCollectorFake; 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.bubbles.Bubbles; 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 @@ public class StatusBarTest extends SysuiTestCase { verify(mDozeServiceHost).setDozeSuppressed(false); } - @Ignore // TODO (b/175240607) - Figure out if the device will actually dial 911. - @Test - public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() { - ArgumentCaptor 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 {