diff options
author | Tony <twickham@google.com> | 2019-02-22 13:10:59 -0800 |
---|---|---|
committer | Tony Wickham <twickham@google.com> | 2019-02-28 14:39:27 -0800 |
commit | 573c3e1712b35ff92b0a272a4c4de6f88a8b0cc0 (patch) | |
tree | a21d9d74fd5ee5e3a2c148b6410db5e3edaa2225 | |
parent | 7ceb6f358aae69e69705408e2d35774afdd33a0e (diff) | |
download | android_packages_apps_Trebuchet-573c3e1712b35ff92b0a272a4c4de6f88a8b0cc0.tar.gz android_packages_apps_Trebuchet-573c3e1712b35ff92b0a272a4c4de6f88a8b0cc0.tar.bz2 android_packages_apps_Trebuchet-573c3e1712b35ff92b0a272a4c4de6f88a8b0cc0.zip |
Make TouchInteractionService direct boot aware
- Add directBootAware="true" to TouchInteractionService manifest component
- Add DeviceLockedInputConsumer which just sends a home intent on touch down
Test:
- Reboot
- Swipe up anywhere to get to bouncer (pin/password/pattern)
- Click "Emergency" to launch dialer while still in direct boot
- Swipe up from the nav bar to exit/bring up bouncer
Test:
- Lock screen
- Double press power to launch camera
- Swipe up from nav bar to exit/bring up bouncer
Bug: 125364936
Change-Id: I7a4cd2dc3a635daf4bb9a643a1e5251ca4e91e33
5 files changed, 134 insertions, 13 deletions
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 542a235ad..62d050016 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -38,7 +38,8 @@ <service android:name="com.android.quickstep.TouchInteractionService" - android:permission="android.permission.STATUS_BAR_SERVICE" > + android:permission="android.permission.STATUS_BAR_SERVICE" + android:directBootAware="true" > <intent-filter> <action android:name="android.intent.action.QUICKSTEP_SERVICE" /> </intent-filter> diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java new file mode 100644 index 000000000..047f34c2d --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 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.quickstep; + +import android.content.Context; +import android.content.Intent; +import android.view.MotionEvent; + +/** + * A dummy input consumer used when the device is still locked, e.g. from secure camera. + */ +public class DeviceLockedInputConsumer implements InputConsumer { + + private final Context mContext; + + public DeviceLockedInputConsumer(Context context) { + mContext = context; + } + + @Override + public void onMotionEvent(MotionEvent ev) { + // For now, just start the home intent so user is prompted to unlock the device. + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mContext.startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index ddf3ad584..cf50fc152 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -23,13 +23,18 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYS import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; +import android.app.KeyguardManager; import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.graphics.Region; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.util.Log; import android.util.Pair; import android.view.Choreographer; @@ -37,6 +42,8 @@ import android.view.InputEvent; import android.view.MotionEvent; import com.android.launcher3.MainThreadExecutor; +import com.android.launcher3.Utilities; +import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.UiThreadHelper; import com.android.systemui.shared.recents.IOverviewProxy; @@ -49,6 +56,8 @@ import com.android.systemui.shared.system.InputConsumerController; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; /** * Service connected by system-UI for handling touch interaction. @@ -75,8 +84,10 @@ public class TouchInteractionService extends Service { public void onInitialize(Bundle bundle) { mISystemUiProxy = ISystemUiProxy.Stub .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY)); - mRecentsModel.setSystemUiProxy(mISystemUiProxy); - mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + runWhenUserUnlocked(() -> { + mRecentsModel.setSystemUiProxy(mISystemUiProxy); + mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + }); disposeEventHandlers(); mInputEventReceiver = InputChannelCompat.fromBundle(bundle, KEY_EXTRA_INPUT_CHANNEL, @@ -128,8 +139,10 @@ public class TouchInteractionService extends Service { public void onBind(ISystemUiProxy iSystemUiProxy) { mISystemUiProxy = iSystemUiProxy; - mRecentsModel.setSystemUiProxy(mISystemUiProxy); - mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + runWhenUserUnlocked(() -> { + mRecentsModel.setSystemUiProxy(mISystemUiProxy); + mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + }); // On Bind is received before onInitialize which will dispose these handlers disposeEventHandlers(); @@ -138,7 +151,6 @@ public class TouchInteractionService extends Service { TouchInteractionService.this::onInputEvent); mDeprecatedDispatcher = pair.first; mInputEventReceiver = pair.second; - } }; @@ -148,6 +160,7 @@ public class TouchInteractionService extends Service { return sConnected; } + private KeyguardManager mKM; private ActivityManagerWrapper mAM; private RecentsModel mRecentsModel; private ISystemUiProxy mISystemUiProxy; @@ -159,6 +172,17 @@ public class TouchInteractionService extends Service { private InputConsumerController mInputConsumer; private SwipeSharedState mSwipeSharedState; + private boolean mIsUserUnlocked; + private List<Runnable> mOnUserUnlockedCallbacks; + private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { + initWhenUserUnlocked(); + } + } + }; + private InputConsumer mConsumer = InputConsumer.NO_OP; private Choreographer mMainChoreographer; @@ -170,10 +194,29 @@ public class TouchInteractionService extends Service { @Override public void onCreate() { super.onCreate(); + + // Initialize anything here that is needed in direct boot mode. + // Everything else should be initialized in initWhenUserUnlocked() below. + mKM = getSystemService(KeyguardManager.class); + mMainChoreographer = Choreographer.getInstance(); + mOnUserUnlockedCallbacks = new ArrayList<>(); + + if (UserManagerCompat.getInstance(this).isUserUnlocked(Process.myUserHandle())) { + initWhenUserUnlocked(); + } else { + mIsUserUnlocked = false; + registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED)); + } + + sConnected = true; + } + + private void initWhenUserUnlocked() { + mIsUserUnlocked = true; + mAM = ActivityManagerWrapper.getInstance(); mRecentsModel = RecentsModel.INSTANCE.get(this); mOverviewComponentObserver = new OverviewComponentObserver(this); - mMainChoreographer = Choreographer.getInstance(); mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver); mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this); @@ -183,18 +226,34 @@ public class TouchInteractionService extends Service { mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); mInputConsumer.registerInputConsumer(); - sConnected = true; + for (Runnable callback : mOnUserUnlockedCallbacks) { + callback.run(); + } + mOnUserUnlockedCallbacks.clear(); // Temporarily disable model preload // new ModelPreload().start(this); + + Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver); + } + + private void runWhenUserUnlocked(Runnable callback) { + if (mIsUserUnlocked) { + callback.run(); + } else { + mOnUserUnlockedCallbacks.add(callback); + } } @Override public void onDestroy() { - mInputConsumer.unregisterInputConsumer(); - mOverviewComponentObserver.onDestroy(); + if (mIsUserUnlocked) { + mInputConsumer.unregisterInputConsumer(); + mOverviewComponentObserver.onDestroy(); + } disposeEventHandlers(); sConnected = false; + Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver); super.onDestroy(); } @@ -234,6 +293,13 @@ public class TouchInteractionService extends Service { } private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) { + // TODO: this makes a binder call every touch down. we should move to a listener pattern. + if (mKM.isDeviceLocked()) { + // This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched + // while device is locked even after exiting direct boot mode (e.g. camera). + return new DeviceLockedInputConsumer(this); + } + RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0); if (!useSharedState) { mSwipeSharedState.clearAllState(); diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 74fa447d1..7bb60714f 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -19,12 +19,14 @@ package com.android.launcher3; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver; +import android.app.KeyguardManager; import android.content.ComponentName; import android.content.ContentProviderClient; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; +import android.os.Process; import android.util.Log; import com.android.launcher3.compat.LauncherAppsCompat; @@ -66,6 +68,9 @@ public class LauncherAppState { } private LauncherAppState(Context context) { + if (!UserManagerCompat.getInstance(context).isUserUnlocked(Process.myUserHandle())) { + throw new RuntimeException("LauncherAppState should not start in direct boot mode"); + } if (getLocalProvider(context) == null) { throw new RuntimeException( "Initializing LauncherAppState in the absence of LauncherProvider"); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index e5ab2d129..832e9c94f 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -16,8 +16,12 @@ package com.android.launcher3; +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP; +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT; + import android.app.ActivityManager; import android.app.WallpaperManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -67,9 +71,6 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT; - /** * Various utilities shared amongst the Launcher's classes. */ @@ -590,4 +591,10 @@ public final class Utilities { outRect.set(viewLocationLeft, viewLocationTop, viewLocationLeft + rect.width(), viewLocationTop + rect.height()); } + + public static void unregisterReceiverSafely(Context context, BroadcastReceiver receiver) { + try { + context.unregisterReceiver(receiver); + } catch (IllegalArgumentException e) { } + } } |