diff options
author | 2018-04-05 09:20:00 -0700 | |
---|---|---|
committer | 2018-04-05 09:20:00 -0700 | |
commit | 76cc3df9b832e026cb4891dda95ec33c012cacf9 (patch) | |
tree | 25da8af4cd946b307e9421fd9e1f0fb5694278e0 | |
parent | 7e918239b8a3d4ae5315ab674277cb85829296d6 (diff) | |
parent | 312a176a0be0f4807b19e1583decca535e2ee6b7 (diff) |
Merge "Require screen to be unlocked for smart replies" into pi-dev
am: 312a176a0b
Change-Id: I11d4eb66d036edb263717d21a3d4dde4047bb54b
6 files changed, 144 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 039e7b5a6613..0ba26e94ce1e 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -44,6 +44,7 @@ import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBouncer; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockscreenWallpaper; @@ -142,5 +143,6 @@ public class SystemUIFactory { providers.put(NotificationViewHierarchyManager.class, () -> new NotificationViewHierarchyManager(context)); providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context)); + providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java new file mode 100644 index 000000000000..759a0d173cdd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 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.statusbar.phone; + +import android.annotation.Nullable; + +import com.android.keyguard.KeyguardHostView.OnDismissAction; + + +/** Executes actions that require the screen to be unlocked. */ +public interface KeyguardDismissHandler { + /** Executes an action that requres the screen to be unlocked. */ + void dismissKeyguardThenExecute( + OnDismissAction action, @Nullable Runnable cancelAction, boolean afterKeyguardGone); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java new file mode 100644 index 000000000000..c38b0b63190d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 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.statusbar.phone; + +import android.util.Log; + +import com.android.keyguard.KeyguardHostView.OnDismissAction; + +/** + * Executes actions that require the screen to be unlocked. Delegates the actual handling to an + * implementation passed via {@link #setDismissHandler}. + */ +public class KeyguardDismissUtil implements KeyguardDismissHandler { + private static final String TAG = "KeyguardDismissUtil"; + + private volatile KeyguardDismissHandler mDismissHandler; + + /** Sets the actual {@link DismissHandler} implementation. */ + public void setDismissHandler(KeyguardDismissHandler dismissHandler) { + mDismissHandler = dismissHandler; + } + + /** + * Executes an action that requres the screen to be unlocked. + * + * <p>Must be called after {@link #setDismissHandler}. + */ + @Override + public void dismissKeyguardThenExecute( + OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) { + KeyguardDismissHandler dismissHandler = mDismissHandler; + if (dismissHandler == null) { + Log.wtf(TAG, "KeyguardDismissHandler not set."); + action.onDismiss(); + return; + } + dismissHandler.dismissKeyguardThenExecute(action, cancelAction, afterKeyguardGone); + } +} 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 340b462d2540..7987bfd9bfb8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -213,6 +213,7 @@ import com.android.systemui.statusbar.notification.AboveShelfObserver; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.BrightnessMirrorController; @@ -1300,6 +1301,8 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController); + Dependency.get(KeyguardDismissUtil.class).setDismissHandler( + this::dismissKeyguardThenExecute); Trace.endSection(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 790135fc03ca..74b39268fc2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -20,8 +20,10 @@ import android.view.ViewGroup; import android.widget.Button; import com.android.internal.annotations.VisibleForTesting; +import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import java.text.BreakIterator; import java.util.Comparator; @@ -42,6 +44,7 @@ public class SmartReplyView extends ViewGroup { private static final int SQUEEZE_FAILED = -1; private final SmartReplyConstants mConstants; + private final KeyguardDismissUtil mKeyguardDismissUtil; /** Spacing to be applied between views. */ private final int mSpacing; @@ -62,6 +65,7 @@ public class SmartReplyView extends ViewGroup { public SmartReplyView(Context context, AttributeSet attrs) { super(context, attrs); mConstants = Dependency.get(SmartReplyConstants.class); + mKeyguardDismissUtil = Dependency.get(KeyguardDismissUtil.class); int spacing = 0; int singleLineButtonPaddingHorizontal = 0; @@ -126,12 +130,13 @@ public class SmartReplyView extends ViewGroup { } @VisibleForTesting - static Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice, + Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice, RemoteInput remoteInput, PendingIntent pendingIntent) { Button b = (Button) LayoutInflater.from(context).inflate( R.layout.smart_reply_button, root, false); b.setText(choice); - b.setOnClickListener(view -> { + + OnDismissAction action = () -> { Bundle results = new Bundle(); results.putString(remoteInput.getResultKey(), choice.toString()); Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -142,6 +147,12 @@ public class SmartReplyView extends ViewGroup { } catch (PendingIntent.CanceledException e) { Log.w(TAG, "Unable to send smart reply", e); } + return false; // do not defer + }; + + b.setOnClickListener(view -> { + mKeyguardDismissUtil.dismissKeyguardThenExecute( + action, null /* cancelAction */, false /* afterKeyguardGone */); }); return b; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java index a9b2c96d3ae1..56882c654b33 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java @@ -18,6 +18,7 @@ import static android.view.View.MeasureSpec; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -34,8 +35,12 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; +import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; + +import java.util.concurrent.atomic.AtomicReference; import org.junit.After; import org.junit.Before; @@ -65,6 +70,8 @@ public class SmartReplyViewTest extends SysuiTestCase { public void setUp() { mReceiver = new BlockingQueueIntentReceiver(); mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION)); + mDependency.get(KeyguardDismissUtil.class).setDismissHandler( + (action, cancelAction, afterKeyguardGone) -> action.onDismiss()); mView = SmartReplyView.inflate(mContext, null); @@ -95,6 +102,42 @@ public class SmartReplyViewTest extends SysuiTestCase { } @Test + public void testSendSmartReply_keyguardCancelled() throws InterruptedException { + mDependency.get(KeyguardDismissUtil.class).setDismissHandler( + (action, cancelAction, afterKeyguardGone) -> { + if (cancelAction != null) { + cancelAction.run(); + } + }); + setRepliesFromRemoteInput(TEST_CHOICES); + + mView.getChildAt(2).performClick(); + + assertNull(mReceiver.waitForIntent()); + } + + @Test + public void testSendSmartReply_waitsForKeyguard() throws InterruptedException { + AtomicReference<OnDismissAction> actionRef = new AtomicReference<>(); + mDependency.get(KeyguardDismissUtil.class).setDismissHandler( + (action, cancelAction, afterKeyguardGone) -> actionRef.set(action)); + setRepliesFromRemoteInput(TEST_CHOICES); + + mView.getChildAt(2).performClick(); + + // No intent until the screen is unlocked. + assertNull(mReceiver.waitForIntent()); + + actionRef.get().onDismiss(); + + // Now the intent should arrive. + Intent resultIntent = mReceiver.waitForIntent(); + assertEquals(TEST_CHOICES[2], + RemoteInput.getResultsFromIntent(resultIntent).get(TEST_RESULT_KEY)); + assertEquals(RemoteInput.SOURCE_CHOICE, RemoteInput.getResultsSource(resultIntent)); + } + + @Test public void testMeasure_empty() { mView.measure(WIDTH_SPEC, HEIGHT_SPEC); assertEquals(500, mView.getMeasuredWidthAndState()); @@ -301,7 +344,7 @@ public class SmartReplyViewTest extends SysuiTestCase { Button previous = null; for (CharSequence choice : choices) { - Button current = SmartReplyView.inflateReplyButton(mContext, mView, choice, null, null); + Button current = mView.inflateReplyButton(mContext, mView, choice, null, null); current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal, current.getPaddingBottom()); if (previous != null) { |