Loading packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java +122 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -157,6 +167,8 @@ public class NavigationModeController implements Dumpable { } }; private BroadcastReceiver mEnableGestureNavReceiver; @Inject public NavigationModeController(Context context, DeviceProvisionedController deviceProvisionedController, Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -255,6 +348,7 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is " + "setup"); } removeEnableGestureNavListener(); return; } Loading @@ -270,6 +364,7 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, " + "default=" + defaultOverlays); } removeEnableGestureNavListener(); return; } Loading @@ -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"); } Loading @@ -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); } } Loading Loading
packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java +122 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -157,6 +167,8 @@ public class NavigationModeController implements Dumpable { } }; private BroadcastReceiver mEnableGestureNavReceiver; @Inject public NavigationModeController(Context context, DeviceProvisionedController deviceProvisionedController, Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -255,6 +348,7 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is " + "setup"); } removeEnableGestureNavListener(); return; } Loading @@ -270,6 +364,7 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, " + "default=" + defaultOverlays); } removeEnableGestureNavListener(); return; } Loading @@ -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"); } Loading @@ -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); } } Loading