Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d5da927 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents bd698b99 56d145fe
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
+122 −1
Original line number Diff line number Diff line
@@ -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);
        }
    }