Merge "Make TouchInteractionService direct boot aware" into ub-launcher3-master

This commit is contained in:
Tony Wickham 2019-02-28 23:48:03 +00:00 committed by Android (Google) Code Review
commit 3efd32adea
5 changed files with 134 additions and 13 deletions

View File

@ -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>

View File

@ -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));
}
}
}

View File

@ -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();

View File

@ -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");

View File

@ -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) { }
}
}