summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony <twickham@google.com>2019-02-22 13:10:59 -0800
committerTony Wickham <twickham@google.com>2019-02-28 14:39:27 -0800
commit573c3e1712b35ff92b0a272a4c4de6f88a8b0cc0 (patch)
treea21d9d74fd5ee5e3a2c148b6410db5e3edaa2225
parent7ceb6f358aae69e69705408e2d35774afdd33a0e (diff)
downloadandroid_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
-rw-r--r--quickstep/AndroidManifest.xml3
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java42
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java84
-rw-r--r--src/com/android/launcher3/LauncherAppState.java5
-rw-r--r--src/com/android/launcher3/Utilities.java13
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) { }
+ }
}