Merge "Autoenabling gesture mode only is the device is unmanaged" into qt-r1-dev

This commit is contained in:
TreeHugger Robot
2019-07-12 15:47:36 +00:00
committed by Android (Google) Code Review
2 changed files with 131 additions and 1 deletions

View File

@@ -49,6 +49,15 @@ public class QuickStepContract {
public static final String NAV_BAR_MODE_GESTURAL_OVERLAY =
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
// Action sent by a system app to switch to gesture nav
public static final String ACTION_ENABLE_GESTURE_NAV =
"com.android.systemui.ENABLE_GESTURE_NAV";
// Action for the intent to receive the result
public static final String ACTION_ENABLE_GESTURE_NAV_RESULT =
"com.android.systemui.action.ENABLE_GESTURE_NAV_RESULT";
// Extra containing the pending intent to receive the result
public static final String EXTRA_RESULT_INTENT = "com.android.systemui.EXTRA_RESULT_INTENT";
// Overview is disabled, either because the device is in lock task mode, or because the device
// policy has disabled the feature
public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;

View File

@@ -16,17 +16,26 @@
package com.android.systemui.statusbar.phone;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV;
import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV_RESULT;
import static com.android.systemui.shared.system.QuickStepContract.EXTRA_RESULT_INTENT;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -40,6 +49,7 @@ import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.text.TextUtils;
@@ -157,6 +167,8 @@ public class NavigationModeController implements Dumpable {
}
};
private BroadcastReceiver mEnableGestureNavReceiver;
@Inject
public NavigationModeController(Context context,
DeviceProvisionedController deviceProvisionedController,
@@ -177,6 +189,7 @@ public class NavigationModeController implements Dumpable {
IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
null);
// We are only interested in launcher changes, so keeping track of the current default.
mLastDefaultLauncher = getDefaultLauncherPackageName(mContext);
@@ -187,6 +200,82 @@ public class NavigationModeController implements Dumpable {
deferGesturalNavOverlayIfNecessary();
}
private void removeEnableGestureNavListener() {
if (mEnableGestureNavReceiver != null) {
if (DEBUG) {
Log.d(TAG, "mEnableGestureNavReceiver unregistered");
}
mContext.unregisterReceiver(mEnableGestureNavReceiver);
mEnableGestureNavReceiver = null;
}
}
private boolean setGestureModeOverlayForMainLauncher() {
removeEnableGestureNavListener();
if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) {
// Already in gesture mode
return true;
}
final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext);
if (supported == null || supported) {
Log.d(TAG, "Switching system navigation to full-gesture mode:"
+ " defaultLauncher="
+ getDefaultLauncherPackageName(mCurrentUserContext)
+ " contextUser="
+ mCurrentUserContext.getUserId());
setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
return true;
} else {
Log.e(TAG, "Gesture nav is not supported for defaultLauncher="
+ getDefaultLauncherPackageName(mCurrentUserContext));
return false;
}
}
private boolean enableGestureNav(Intent intent) {
if (!(intent.getParcelableExtra(EXTRA_RESULT_INTENT) instanceof PendingIntent)) {
Log.e(TAG, "No callback pending intent was attached");
return false;
}
PendingIntent callback = intent.getParcelableExtra(EXTRA_RESULT_INTENT);
Intent callbackIntent = callback.getIntent();
if (callbackIntent == null
|| !ACTION_ENABLE_GESTURE_NAV_RESULT.equals(callbackIntent.getAction())) {
Log.e(TAG, "Invalid callback intent");
return false;
}
String callerPackage = callback.getCreatorPackage();
UserHandle callerUser = callback.getCreatorUserHandle();
DevicePolicyManager dpm = mCurrentUserContext.getSystemService(DevicePolicyManager.class);
ComponentName ownerComponent = dpm.getDeviceOwnerComponentOnCallingUser();
if (ownerComponent != null) {
// Verify that the caller is the owner component
if (!ownerComponent.getPackageName().equals(callerPackage)
|| !mCurrentUserContext.getUser().equals(callerUser)) {
Log.e(TAG, "Callback must be from the device owner");
return false;
}
} else {
UserHandle callerParent = mCurrentUserContext.getSystemService(UserManager.class)
.getProfileParent(callerUser);
if (callerParent == null || !callerParent.equals(mCurrentUserContext.getUser())) {
Log.e(TAG, "Callback must be from a managed user");
return false;
}
ComponentName profileOwner = dpm.getProfileOwnerAsUser(callerUser);
if (profileOwner == null || !profileOwner.getPackageName().equals(callerPackage)) {
Log.e(TAG, "Callback must be from the profile owner");
return false;
}
}
return setGestureModeOverlayForMainLauncher();
}
public void updateCurrentInteractionMode(boolean notify) {
mCurrentUserContext = getCurrentUserContext();
int mode = getCurrentInteractionMode(mCurrentUserContext);
@@ -245,6 +334,10 @@ public class NavigationModeController implements Dumpable {
}
}
private boolean supportsDeviceAdmin() {
return mContext.getPackageManager().hasSystemFeature(FEATURE_DEVICE_ADMIN);
}
private void deferGesturalNavOverlayIfNecessary() {
final int userId = mDeviceProvisionedController.getCurrentUser();
mRestoreGesturalNavBarMode.put(userId, false);
@@ -255,6 +348,7 @@ public class NavigationModeController implements Dumpable {
Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is "
+ "setup");
}
removeEnableGestureNavListener();
return;
}
@@ -270,6 +364,7 @@ public class NavigationModeController implements Dumpable {
Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, "
+ "default=" + defaultOverlays);
}
removeEnableGestureNavListener();
return;
}
@@ -277,6 +372,24 @@ public class NavigationModeController implements Dumpable {
// provisioned
setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
mRestoreGesturalNavBarMode.put(userId, true);
if (supportsDeviceAdmin() && mEnableGestureNavReceiver == null) {
mEnableGestureNavReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Log.d(TAG, "ACTION_ENABLE_GESTURE_NAV");
}
setResultCode(enableGestureNav(intent) ? RESULT_OK : RESULT_CANCELED);
}
};
// Register for all users so that we can get managed users as well
mContext.registerReceiverAsUser(mEnableGestureNavReceiver, UserHandle.ALL,
new IntentFilter(ACTION_ENABLE_GESTURE_NAV), null, null);
if (DEBUG) {
Log.d(TAG, "mEnableGestureNavReceiver registered");
}
}
if (DEBUG) {
Log.d(TAG, "deferGesturalNavOverlayIfNecessary: setting to 3 button mode");
}
@@ -290,7 +403,15 @@ public class NavigationModeController implements Dumpable {
final int userId = mDeviceProvisionedController.getCurrentUser();
if (mRestoreGesturalNavBarMode.get(userId)) {
// Restore the gestural state if necessary
setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
if (!supportsDeviceAdmin()
|| mCurrentUserContext.getSystemService(DevicePolicyManager.class)
.getUserProvisioningState() == STATE_USER_UNMANAGED) {
setGestureModeOverlayForMainLauncher();
} else {
if (DEBUG) {
Log.d(TAG, "Not restoring to gesture nav for managed user");
}
}
mRestoreGesturalNavBarMode.put(userId, false);
}
}