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

Commit 75cddae2 authored by Ben Murdoch's avatar Ben Murdoch Committed by Android (Google) Code Review
Browse files

Merge "Make ModifierShortcutManager multiuser aware." into main

parents 6f4ee4a3 68eed418
Loading
Loading
Loading
Loading
+133 −38
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.policy;

import static com.android.server.flags.Flags.modifierShortcutManagerMultiuser;

import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.role.RoleManager;
@@ -82,6 +84,10 @@ public class ModifierShortcutManager {
    private final SparseArray<String> mRoleShortcuts = new SparseArray<String>();
    private final SparseArray<String> mShiftRoleShortcuts = new SparseArray<String>();
    private final Map<String, Intent> mRoleIntents = new HashMap<String, Intent>();
    private final SparseArray<ComponentName> mComponentShortcuts = new SparseArray<>();
    private final SparseArray<ComponentName> mShiftComponentShortcuts = new SparseArray<>();
    private final Map<ComponentName, Intent> mComponentIntents =
            new HashMap<ComponentName, Intent>();

    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();

@@ -115,23 +121,31 @@ public class ModifierShortcutManager {

    private final Context mContext;
    private final Handler mHandler;
    private final RoleManager mRoleManager;
    private final PackageManager mPackageManager;
    private boolean mSearchKeyShortcutPending = false;
    private boolean mConsumeSearchKeyUp = true;
    private UserHandle mCurrentUser;

    ModifierShortcutManager(Context context, Handler handler) {
    ModifierShortcutManager(Context context, Handler handler, UserHandle currentUser) {
        mContext = context;
        mHandler = handler;
        mPackageManager = mContext.getPackageManager();
        mRoleManager = mContext.getSystemService(RoleManager.class);
        mRoleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(),
        RoleManager rm = mContext.getSystemService(RoleManager.class);
        rm.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(),
                (String roleName, UserHandle user) -> {
                    mRoleIntents.remove(roleName);
                }, UserHandle.ALL);
        mCurrentUser = currentUser;
        loadShortcuts();
    }

    void setCurrentUser(UserHandle newUser) {
        mCurrentUser = newUser;

        // Role based shortcuts may resolve to different apps for different users
        // so clear the cache.
        mRoleIntents.clear();
        mComponentIntents.clear();
    }

    /**
     * Gets the shortcut intent for a given keycode+modifier. Make sure you
     * strip whatever modifier is used for invoking shortcuts (for example,
@@ -147,9 +161,11 @@ public class ModifierShortcutManager {
     * to invoke the shortcut.
     * @return The intent that matches the shortcut, or null if not found.
     */
    @Nullable
    private Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
        // If a modifier key other than shift is also pressed, skip it.
        final boolean isShiftOn = KeyEvent.metaStateHasModifiers(metaState, KeyEvent.META_SHIFT_ON);
        final boolean isShiftOn = KeyEvent.metaStateHasModifiers(
                metaState, KeyEvent.META_SHIFT_ON);
        if (!isShiftOn && !KeyEvent.metaStateHasNoModifiers(metaState)) {
            return null;
        }
@@ -161,37 +177,54 @@ public class ModifierShortcutManager {

        // First try the exact keycode (with modifiers).
        int shortcutChar = kcm.get(keyCode, metaState);
        if (shortcutChar != 0) {
            shortcutIntent = shortcutMap.get(shortcutChar);
        if (shortcutChar == 0) {
            return null;
        }
        shortcutIntent = shortcutMap.get(shortcutChar);

        // Next try the primary character on that key.
        if (shortcutIntent == null) {
            // Next try the primary character on that key.
            shortcutChar = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
            if (shortcutChar != 0) {
            if (shortcutChar == 0) {
                return null;
            }
            shortcutIntent = shortcutMap.get(shortcutChar);
        }

        if (shortcutIntent == null) {
                    // Check for role based shortcut
            // Next check for role based shortcut with primary character.
            String role = isShiftOn ? mShiftRoleShortcuts.get(shortcutChar)
                    : mRoleShortcuts.get(shortcutChar);
            if (role != null) {
                shortcutIntent = getRoleLaunchIntent(role);
            }
        }

        if (modifierShortcutManagerMultiuser()) {
            if (shortcutIntent == null) {
                // Next check component based shortcuts with primary character.
                ComponentName component = isShiftOn
                        ? mShiftComponentShortcuts.get(shortcutChar)
                        : mComponentShortcuts.get(shortcutChar);
                if (component != null) {
                    shortcutIntent = resolveComponentNameIntent(component);
                }
            }
        }

        return shortcutIntent;
    }

    private Intent getRoleLaunchIntent(String role) {
        Intent intent = mRoleIntents.get(role);
        if (intent == null) {
            if (mRoleManager.isRoleAvailable(role)) {
                String rolePackage = mRoleManager.getDefaultApplication(role);
            Context context = modifierShortcutManagerMultiuser()
                    ? mContext.createContextAsUser(mCurrentUser, 0) : mContext;
            RoleManager rm = context.getSystemService(RoleManager.class);
            PackageManager pm = context.getPackageManager();
            if (rm.isRoleAvailable(role)) {
                String rolePackage = rm.getDefaultApplication(role);
                if (rolePackage != null) {
                    intent = mPackageManager.getLaunchIntentForPackage(rolePackage);
                    intent = pm.getLaunchIntentForPackage(rolePackage);
                    if (intent != null) {
                        intent.putExtra(EXTRA_ROLE, role);
                        mRoleIntents.put(role, intent);
@@ -249,7 +282,17 @@ public class ModifierShortcutManager {
                                + " className=" + className + " shortcutChar=" + shortcutChar);
                        continue;
                    }
                    if (modifierShortcutManagerMultiuser()) {
                        ComponentName componentName = new ComponentName(packageName, className);
                        if (isShiftShortcut) {
                            mShiftComponentShortcuts.put(shortcutChar, componentName);
                        } else {
                            mComponentShortcuts.put(shortcutChar, componentName);
                        }
                        continue;
                    } else {
                        intent = resolveComponentNameIntent(packageName, className);
                    }
                } else if (categoryName != null) {
                    if (roleName != null) {
                        Log.w(TAG, "Cannot specify role bookmark when category is present for"
@@ -287,20 +330,38 @@ public class ModifierShortcutManager {
        }
    }

    @Nullable
    private Intent resolveComponentNameIntent(ComponentName componentName) {
        Intent intent = mComponentIntents.get(componentName);
        if (intent == null) {
            intent = resolveComponentNameIntent(
                    componentName.getPackageName(), componentName.getClassName());
            if (intent != null) {
                mComponentIntents.put(componentName, intent);
            }
        }
        return intent;
    }

    @Nullable
    private Intent resolveComponentNameIntent(String packageName, String className) {
        int flags = PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                | PackageManager.MATCH_DIRECT_BOOT_AWARE
        Context context = modifierShortcutManagerMultiuser()
                ? mContext.createContextAsUser(mCurrentUser, 0) : mContext;
        PackageManager pm = context.getPackageManager();
        int flags = PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
        if (!modifierShortcutManagerMultiuser()) {
            flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
                    | PackageManager.MATCH_UNINSTALLED_PACKAGES;
        }
        ComponentName componentName = new ComponentName(packageName, className);
        try {
            mPackageManager.getActivityInfo(componentName, flags);
            pm.getActivityInfo(componentName, flags);
        } catch (PackageManager.NameNotFoundException e) {
            String[] packages = mPackageManager.canonicalToCurrentPackageNames(
            String[] packages = pm.canonicalToCurrentPackageNames(
                    new String[] { packageName });
            componentName = new ComponentName(packages[0], className);
            try {
                mPackageManager.getActivityInfo(componentName, flags);
                pm.getActivityInfo(componentName, flags);
            } catch (PackageManager.NameNotFoundException e1) {
                Log.w(TAG, "Unable to add bookmark: " + packageName
                        + "/" + className + " not found.");
@@ -399,7 +460,11 @@ public class ModifierShortcutManager {
            if (intent != null) {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                try {
                    if (modifierShortcutManagerMultiuser()) {
                        mContext.startActivityAsUser(intent, mCurrentUser);
                    } else {
                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
                    }
                } catch (ActivityNotFoundException ex) {
                    Slog.w(TAG, "Dropping application launch key because "
                            + "the activity to which it is registered was not found: "
@@ -417,7 +482,11 @@ public class ModifierShortcutManager {
        if (shortcutIntent != null) {
            shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            try {
                if (modifierShortcutManagerMultiuser()) {
                    mContext.startActivityAsUser(shortcutIntent, mCurrentUser);
                } else {
                    mContext.startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
                }
            } catch (ActivityNotFoundException ex) {
                Slog.w(TAG, "Dropping shortcut key combination because "
                        + "the activity to which it is registered was not found: "
@@ -526,6 +595,30 @@ public class ModifierShortcutManager {
            }
        }

        if (modifierShortcutManagerMultiuser()) {
            for (int i = 0; i < mComponentShortcuts.size(); i++) {
                ComponentName component = mComponentShortcuts.valueAt(i);
                KeyboardShortcutInfo info = shortcutInfoFromIntent(
                        (char) (mComponentShortcuts.keyAt(i)),
                        resolveComponentNameIntent(component),
                        false);
                if (info != null) {
                    shortcuts.add(info);
                }
            }

            for (int i = 0; i < mShiftComponentShortcuts.size(); i++) {
                ComponentName component = mShiftComponentShortcuts.valueAt(i);
                KeyboardShortcutInfo info = shortcutInfoFromIntent(
                        (char) (mShiftComponentShortcuts.keyAt(i)),
                        resolveComponentNameIntent(component),
                        true);
                if (info != null) {
                    shortcuts.add(info);
                }
            }
        }

        return new KeyboardShortcutGroup(
                mContext.getString(R.string.keyboard_shortcut_group_applications),
                shortcuts);
@@ -548,23 +641,26 @@ public class ModifierShortcutManager {

        CharSequence label;
        Icon icon;
        Context context = modifierShortcutManagerMultiuser()
                ? mContext.createContextAsUser(mCurrentUser, 0) : mContext;
        PackageManager pm = context.getPackageManager();
        ActivityInfo resolvedActivity = intent.resolveActivityInfo(
                mPackageManager, PackageManager.MATCH_DEFAULT_ONLY);
                pm, PackageManager.MATCH_DEFAULT_ONLY);
        if (resolvedActivity == null) {
            return null;
        }
        boolean isResolver = com.android.internal.app.ResolverActivity.class.getName().equals(
                resolvedActivity.name);
        if (isResolver) {
            label = getIntentCategoryLabel(mContext,
            label = getIntentCategoryLabel(context,
                    intent.getSelector().getCategories().iterator().next());
            if (label == null) {
                return null;
            }
            icon = Icon.createWithResource(mContext, R.drawable.sym_def_app_icon);
            icon = Icon.createWithResource(context, R.drawable.sym_def_app_icon);

        } else {
            label = resolvedActivity.loadLabel(mPackageManager);
            label = resolvedActivity.loadLabel(pm);
            icon = Icon.createWithResource(
                    resolvedActivity.packageName, resolvedActivity.getIconResource());
        }
@@ -609,5 +705,4 @@ public class ModifierShortcutManager {
        }
        return context.getString(resid);
    };

}
+6 −1
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;

import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable;
import static com.android.server.flags.Flags.modifierShortcutManagerMultiuser;
import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
@@ -2281,7 +2282,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
        mSettingsObserver = new SettingsObserver(mHandler);
        mSettingsObserver.observe();
        mModifierShortcutManager = new ModifierShortcutManager(mContext, mHandler);
        mModifierShortcutManager = new ModifierShortcutManager(
                mContext, mHandler, UserHandle.of(mCurrentUserId));
        mUiMode = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_defaultUiModeType);
        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
@@ -6506,6 +6508,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (statusBar != null) {
            statusBar.setCurrentUser(newUserId);
        }
        if (modifierShortcutManagerMultiuser()) {
            mModifierShortcutManager.setCurrentUser(UserHandle.of(newUserId));
        }
    }

    @Override
+4 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
import android.view.KeyboardShortcutInfo;
@@ -77,6 +78,7 @@ public class ModifierShortcutManagerTests {
        XmlResourceParser testBookmarks = mResources.getXml(
                com.android.frameworks.wmtests.R.xml.bookmarks);

        doReturn(mContext).when(mContext).createContextAsUser(anyObject(), anyInt());
        when(mContext.getResources()).thenReturn(mResources);
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mResources.getXml(R.xml.bookmarks)).thenReturn(testBookmarks);
@@ -98,7 +100,8 @@ public class ModifierShortcutManagerTests {
                .canonicalToCurrentPackageNames(aryEq(new String[] { "com.test2" }));


        mModifierShortcutManager = new ModifierShortcutManager(mContext, mHandler);
        mModifierShortcutManager = new ModifierShortcutManager(
                mContext, mHandler, UserHandle.SYSTEM);
    }

    @Test