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

Commit 7fc19171 authored by Evan Severson's avatar Evan Severson Committed by Android (Google) Code Review
Browse files

Merge "Usb launch preference denial able to be remembered"

parents d3746933 d9f045eb
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -55,6 +55,18 @@ interface IUsbManager
     */
    void setAccessoryPackage(in UsbAccessory accessory, String packageName, int userId);

    /* Adds packages to the set of "denied and don't ask again" launch preferences for a device */
    void addDevicePackagesToPreferenceDenied(in UsbDevice device, in String[] packageNames, in UserHandle user);

    /* Adds packages to the set of "denied and don't ask again" launch preferences for an accessory */
    void addAccessoryPackagesToPreferenceDenied(in UsbAccessory accessory, in String[] packageNames, in UserHandle user);

    /* Removes packages from the set of "denied and don't ask again" launch preferences for a device */
    void removeDevicePackagesFromPreferenceDenied(in UsbDevice device, in String[] packageNames, in UserHandle user);

    /* Removes packages from the set of "denied and don't ask again" launch preferences for an accessory */
    void removeAccessoryPackagesFromPreferenceDenied(in UsbAccessory device, in String[] packageNames, in UserHandle user);

    /* Sets the persistent permission granted state for USB device
     */
    void setDevicePersistentPermission(in UsbDevice device, int uid, in UserHandle user, boolean shouldBeGranted);
+311 −4
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ import android.service.usb.UsbProfileGroupSettingsManagerProto;
import android.service.usb.UsbSettingsAccessoryPreferenceProto;
import android.service.usb.UsbSettingsDevicePreferenceProto;
import android.service.usb.UserPackageProto;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
@@ -70,6 +72,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ProtocolException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
@@ -102,10 +105,20 @@ class UsbProfileGroupSettingsManager {
    @GuardedBy("mLock")
    private final HashMap<DeviceFilter, UserPackage> mDevicePreferenceMap = new HashMap<>();

    /** Maps DeviceFilter to set of UserPackages not to ask for launch preference anymore */
    @GuardedBy("mLock")
    private final ArrayMap<DeviceFilter, ArraySet<UserPackage>> mDevicePreferenceDeniedMap =
            new ArrayMap<>();

    /** Maps AccessoryFilter to user preferred application package */
    @GuardedBy("mLock")
    private final HashMap<AccessoryFilter, UserPackage> mAccessoryPreferenceMap = new HashMap<>();

    /** Maps AccessoryFilter to set of UserPackages not to ask for launch preference anymore */
    @GuardedBy("mLock")
    private final ArrayMap<AccessoryFilter, ArraySet<UserPackage>> mAccessoryPreferenceDeniedMap =
            new ArrayMap<>();

    private final Object mLock = new Object();

    /**
@@ -248,11 +261,11 @@ class UsbProfileGroupSettingsManager {
    }

    /**
     * Remove all defaults for a user.
     * Remove all defaults and denied packages for a user.
     *
     * @param userToRemove The user the defaults belong to.
     * @param userToRemove The user
     */
    void removeAllDefaultsForUser(@NonNull UserHandle userToRemove) {
    void removeUser(@NonNull UserHandle userToRemove) {
        synchronized (mLock) {
            boolean needToPersist = false;
            Iterator<Map.Entry<DeviceFilter, UserPackage>> devicePreferenceIt = mDevicePreferenceMap
@@ -277,6 +290,28 @@ class UsbProfileGroupSettingsManager {
                }
            }

            int numEntries = mDevicePreferenceDeniedMap.size();
            for (int i = 0; i < numEntries; i++) {
                ArraySet<UserPackage> userPackages = mDevicePreferenceDeniedMap.valueAt(i);
                for (int j = userPackages.size() - 1; j >= 0; j--) {
                    if (userPackages.valueAt(j).user.equals(userToRemove)) {
                        userPackages.removeAt(j);
                        needToPersist = true;
                    }
                }
            }

            numEntries = mAccessoryPreferenceDeniedMap.size();
            for (int i = 0; i < numEntries; i++) {
                ArraySet<UserPackage> userPackages = mAccessoryPreferenceDeniedMap.valueAt(i);
                for (int j = userPackages.size() - 1; j >= 0; j--) {
                    if (userPackages.valueAt(j).user.equals(userToRemove)) {
                        userPackages.removeAt(j);
                        needToPersist = true;
                    }
                }
            }

            if (needToPersist) {
                scheduleWriteSettingsLocked();
            }
@@ -284,7 +319,7 @@ class UsbProfileGroupSettingsManager {
    }

    private void readPreference(XmlPullParser parser)
            throws XmlPullParserException, IOException {
            throws IOException, XmlPullParserException {
        String packageName = null;

        // If not set, assume it to be the parent profile
@@ -317,6 +352,67 @@ class UsbProfileGroupSettingsManager {
        XmlUtils.nextElement(parser);
    }

    private void readPreferenceDeniedList(@NonNull XmlPullParser parser)
            throws IOException, XmlPullParserException {
        int outerDepth = parser.getDepth();
        if (!XmlUtils.nextElementWithin(parser, outerDepth)) {
            return;
        }

        if ("usb-device".equals(parser.getName())) {
            DeviceFilter filter = DeviceFilter.read(parser);
            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                if ("user-package".equals(parser.getName())) {
                    try {
                        int userId = XmlUtils.readIntAttribute(parser, "user");

                        String packageName = XmlUtils.readStringAttribute(parser, "package");
                        if (packageName == null) {
                            Slog.e(TAG, "Unable to parse package name");
                        }

                        ArraySet<UserPackage> set = mDevicePreferenceDeniedMap.get(filter);
                        if (set == null) {
                            set = new ArraySet<>();
                            mDevicePreferenceDeniedMap.put(filter, set);
                        }
                        set.add(new UserPackage(packageName, UserHandle.of(userId)));
                    } catch (ProtocolException e) {
                        Slog.e(TAG, "Unable to parse user id", e);
                    }
                }
            }
        } else if ("usb-accessory".equals(parser.getName())) {
            AccessoryFilter filter = AccessoryFilter.read(parser);

            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                if ("user-package".equals(parser.getName())) {
                    try {
                        int userId = XmlUtils.readIntAttribute(parser, "user");

                        String packageName = XmlUtils.readStringAttribute(parser, "package");
                        if (packageName == null) {
                            Slog.e(TAG, "Unable to parse package name");
                        }

                        ArraySet<UserPackage> set = mAccessoryPreferenceDeniedMap.get(filter);
                        if (set == null) {
                            set = new ArraySet<>();
                            mAccessoryPreferenceDeniedMap.put(filter, set);
                        }
                        set.add(new UserPackage(packageName, UserHandle.of(userId)));
                    } catch (ProtocolException e) {
                        Slog.e(TAG, "Unable to parse user id", e);
                    }
                }
            }
        }

        while (parser.getDepth() > outerDepth) {
            parser.nextTag(); // ignore unknown tags
        }
    }

    /**
     * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}.
     * Should only be called by owner.
@@ -373,6 +469,8 @@ class UsbProfileGroupSettingsManager {
                String tagName = parser.getName();
                if ("preference".equals(tagName)) {
                    readPreference(parser);
                } else if ("preference-denied-list".equals(tagName)) {
                    readPreferenceDeniedList(parser);
                } else {
                    XmlUtils.nextElement(parser);
                }
@@ -436,6 +534,46 @@ class UsbProfileGroupSettingsManager {
                        serializer.endTag(null, "preference");
                    }

                    int numEntries = mDevicePreferenceDeniedMap.size();
                    for (int i = 0; i < numEntries; i++) {
                        DeviceFilter filter = mDevicePreferenceDeniedMap.keyAt(i);
                        ArraySet<UserPackage> userPackageSet = mDevicePreferenceDeniedMap
                                .valueAt(i);
                        serializer.startTag(null, "preference-denied-list");
                        filter.write(serializer);

                        int numUserPackages = userPackageSet.size();
                        for (int j = 0; j < numUserPackages; j++) {
                            UserPackage userPackage = userPackageSet.valueAt(j);
                            serializer.startTag(null, "user-package");
                            serializer.attribute(null, "user",
                                    String.valueOf(getSerial(userPackage.user)));
                            serializer.attribute(null, "package", userPackage.packageName);
                            serializer.endTag(null, "user-package");
                        }
                        serializer.endTag(null, "preference-denied-list");
                    }

                    numEntries = mAccessoryPreferenceDeniedMap.size();
                    for (int i = 0; i < numEntries; i++) {
                        AccessoryFilter filter = mAccessoryPreferenceDeniedMap.keyAt(i);
                        ArraySet<UserPackage> userPackageSet =
                                mAccessoryPreferenceDeniedMap.valueAt(i);
                        serializer.startTag(null, "preference-denied-list");
                        filter.write(serializer);

                        int numUserPackages = userPackageSet.size();
                        for (int j = 0; j < numUserPackages; j++) {
                            UserPackage userPackage = userPackageSet.valueAt(j);
                            serializer.startTag(null, "user-package");
                            serializer.attribute(null, "user",
                                    String.valueOf(getSerial(userPackage.user)));
                            serializer.attribute(null, "package", userPackage.packageName);
                            serializer.endTag(null, "user-package");
                        }
                        serializer.endTag(null, "preference-denied-list");
                    }

                    serializer.endTag(null, "settings");
                    serializer.endDocument();

@@ -834,6 +972,25 @@ class UsbProfileGroupSettingsManager {
    private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
            @Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
            @Nullable UsbAccessory accessory) {
        // Remove all matches which are on the denied list
        ArraySet deniedPackages = null;
        if (device != null) {
            deniedPackages = mDevicePreferenceDeniedMap.get(new DeviceFilter(device));
        } else if (accessory != null) {
            deniedPackages = mAccessoryPreferenceDeniedMap.get(new AccessoryFilter(accessory));
        }
        if (deniedPackages != null) {
            for (int i = matches.size() - 1; i >= 0; i--) {
                ResolveInfo match = matches.get(i);
                String packageName = match.activityInfo.packageName;
                UserHandle user = UserHandle
                        .getUserHandleForUid(match.activityInfo.applicationInfo.uid);
                if (deniedPackages.contains(new UserPackage(packageName, user))) {
                    matches.remove(i);
                }
            }
        }

        // don't show the resolver activity if there are no choices available
        if (matches.size() == 0) {
            if (accessory != null) {
@@ -1075,6 +1232,156 @@ class UsbProfileGroupSettingsManager {
        }
    }

    /**
     * Add package to the denied for handling a device
     *
     * @param device the device to add to the denied
     * @param packageNames the packages to not become handler
     * @param user the user
     */
    void addDevicePackagesToDenied(@NonNull UsbDevice device, @NonNull String[] packageNames,
            @NonNull UserHandle user) {
        if (packageNames.length == 0) {
            return;
        }
        DeviceFilter filter = new DeviceFilter(device);

        synchronized (mLock) {
            ArraySet<UserPackage> userPackages;
            if (mDevicePreferenceDeniedMap.containsKey(filter)) {
                userPackages = mDevicePreferenceDeniedMap.get(filter);
            } else {
                userPackages = new ArraySet<>();
                mDevicePreferenceDeniedMap.put(filter, userPackages);
            }

            boolean shouldWrite = false;
            for (String packageName : packageNames) {
                UserPackage userPackage = new UserPackage(packageName, user);
                if (!userPackages.contains(userPackage)) {
                    userPackages.add(userPackage);
                    shouldWrite = true;
                }
            }

            if (shouldWrite) {
                scheduleWriteSettingsLocked();
            }
        }
    }

    /**
     * Add package to the denied for handling a accessory
     *
     * @param accessory the accessory to add to the denied
     * @param packageNames the packages to not become handler
     * @param user the user
     */
    void addAccessoryPackagesToDenied(@NonNull UsbAccessory accessory,
            @NonNull String[] packageNames, @NonNull UserHandle user) {
        if (packageNames.length == 0) {
            return;
        }
        AccessoryFilter filter = new AccessoryFilter(accessory);

        synchronized (mLock) {
            ArraySet<UserPackage> userPackages;
            if (mAccessoryPreferenceDeniedMap.containsKey(filter)) {
                userPackages = mAccessoryPreferenceDeniedMap.get(filter);
            } else {
                userPackages = new ArraySet<>();
                mAccessoryPreferenceDeniedMap.put(filter, userPackages);
            }

            boolean shouldWrite = false;
            for (String packageName : packageNames) {
                UserPackage userPackage = new UserPackage(packageName, user);
                if (!userPackages.contains(userPackage)) {
                    userPackages.add(userPackage);
                    shouldWrite = true;
                }
            }

            if (shouldWrite) {
                scheduleWriteSettingsLocked();
            }
        }
    }

    /**
     * Remove UserPackage from the denied for handling a device
     *
     * @param device the device to remove denied packages from
     * @param packageName the packages to remove
     * @param user the user
     */
    void removeDevicePackagesFromDenied(@NonNull UsbDevice device, @NonNull String[] packageNames,
            @NonNull UserHandle user) {
        DeviceFilter filter = new DeviceFilter(device);

        synchronized (mLock) {
            ArraySet<UserPackage> userPackages = mDevicePreferenceDeniedMap.get(filter);

            if (userPackages != null) {
                boolean shouldWrite = false;
                for (String packageName : packageNames) {
                    UserPackage userPackage = new UserPackage(packageName, user);

                    if (userPackages.contains(userPackage)) {
                        userPackages.remove(userPackage);
                        shouldWrite = true;

                        if (userPackages.size() == 0) {
                            mDevicePreferenceDeniedMap.remove(filter);
                            break;
                        }
                    }
                }

                if (shouldWrite) {
                    scheduleWriteSettingsLocked();
                }
            }
        }
    }

    /**
     * Remove UserPackage from the denied for handling a accessory
     *
     * @param accessory the accessory to remove denied packages from
     * @param packageName the packages to remove
     * @param user the user
     */
    void removeAccessoryPackagesFromDenied(@NonNull UsbAccessory accessory,
            @NonNull String[] packageNames, @NonNull UserHandle user) {
        AccessoryFilter filter = new AccessoryFilter(accessory);

        synchronized (mLock) {
            ArraySet<UserPackage> userPackages = mAccessoryPreferenceDeniedMap.get(filter);

            if (userPackages != null) {
                boolean shouldWrite = false;
                for (String packageName : packageNames) {
                    UserPackage userPackage = new UserPackage(packageName, user);

                    if (userPackages.contains(userPackage)) {
                        userPackages.remove(userPackage);
                        shouldWrite = true;

                        if (userPackages.size() == 0) {
                            mAccessoryPreferenceDeniedMap.remove(filter);
                            break;
                        }
                    }
                }

                if (shouldWrite) {
                    scheduleWriteSettingsLocked();
                }
            }
        }
    }

    /**
     * Set a package as default handler for a accessory.
     *
+72 −0
Original line number Diff line number Diff line
@@ -360,6 +360,78 @@ public class UsbService extends IUsbManager.Stub {
        }
    }

    @Override
    public void addDevicePackagesToPreferenceDenied(UsbDevice device, String[] packageNames,
            UserHandle user) {
        device = Preconditions.checkNotNull(device);
        packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
        user = Preconditions.checkNotNull(user);

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);

        final long token = Binder.clearCallingIdentity();
        try {
            mSettingsManager.getSettingsForProfileGroup(user)
                    .addDevicePackagesToDenied(device, packageNames, user);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void addAccessoryPackagesToPreferenceDenied(UsbAccessory accessory,
            String[] packageNames, UserHandle user) {
        accessory = Preconditions.checkNotNull(accessory);
        packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
        user = Preconditions.checkNotNull(user);

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);

        final long token = Binder.clearCallingIdentity();
        try {
            mSettingsManager.getSettingsForProfileGroup(user)
                    .addAccessoryPackagesToDenied(accessory, packageNames, user);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void removeDevicePackagesFromPreferenceDenied(UsbDevice device, String[] packageNames,
            UserHandle user) {
        device = Preconditions.checkNotNull(device);
        packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
        user = Preconditions.checkNotNull(user);

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);

        final long token = Binder.clearCallingIdentity();
        try {
            mSettingsManager.getSettingsForProfileGroup(user)
                    .removeDevicePackagesFromDenied(device, packageNames, user);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void removeAccessoryPackagesFromPreferenceDenied(UsbAccessory accessory,
            String[] packageNames, UserHandle user) {
        accessory = Preconditions.checkNotNull(accessory);
        packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
        user = Preconditions.checkNotNull(user);

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);

        final long token = Binder.clearCallingIdentity();
        try {
            mSettingsManager.getSettingsForProfileGroup(user)
                    .removeAccessoryPackagesFromDenied(accessory, packageNames, user);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void setDevicePersistentPermission(UsbDevice device, int uid, UserHandle user,
            boolean shouldBeGranted) {
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ class UsbSettingsManager {
                // it from all profile groups.
                int numProfileGroups = mSettingsByProfileGroup.size();
                for (int i = 0; i < numProfileGroups; i++) {
                    mSettingsByProfileGroup.valueAt(i).removeAllDefaultsForUser(userToRemove);
                    mSettingsByProfileGroup.valueAt(i).removeUser(userToRemove);
                }
            }
        }