Merge "Autoenabling gesture mode only is the device is unmanaged" into qt-r1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7d5da92740
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user