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

Commit b4948d4d authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "Fix UsbDeviceSettingsManager locking."

parents 04e1a962 7a976a43
Loading
Loading
Loading
Loading
+169 −132
Original line number Diff line number Diff line
@@ -64,18 +64,20 @@ class UsbDeviceSettingsManager {
    private final Context mContext;

    // maps UID to user approved USB devices
    final SparseArray<ArrayList<DeviceFilter>> mDevicePermissionMap =
    private final SparseArray<ArrayList<DeviceFilter>> mDevicePermissionMap =
            new SparseArray<ArrayList<DeviceFilter>>();
    // maps UID to user approved USB accessories
    final SparseArray<ArrayList<AccessoryFilter>> mAccessoryPermissionMap =
    private final SparseArray<ArrayList<AccessoryFilter>> mAccessoryPermissionMap =
            new SparseArray<ArrayList<AccessoryFilter>>();
    // Maps DeviceFilter to user preferred application package
    final HashMap<DeviceFilter, String> mDevicePreferenceMap =
    private final HashMap<DeviceFilter, String> mDevicePreferenceMap =
            new HashMap<DeviceFilter, String>();
    // Maps DeviceFilter to user preferred application package
    final HashMap<AccessoryFilter, String> mAccessoryPreferenceMap =
    private final HashMap<AccessoryFilter, String> mAccessoryPreferenceMap =
            new HashMap<AccessoryFilter, String>();

    private final Object mLock = new Object();

    // This class is used to describe a USB device.
    // When used in HashMaps all values must be specified,
    // but wildcards can be used for any of the fields in
@@ -343,16 +345,20 @@ class UsbDeviceSettingsManager {

    private class MyPackageMonitor extends PackageMonitor {
        public void onPackageRemoved(String packageName, int uid) {
            synchronized (mLock) {
                // clear all activity preferences for the package
            if (clearPackageDefaults(packageName)) {
                writeSettings();
                if (clearPackageDefaultsLocked(packageName)) {
                    writeSettingsLocked();
                }
            }
        }

        public void onUidRemoved(int uid) {
            synchronized (mLock) {
                // clear all permissions for the UID
            if (clearUidDefaults(uid)) {
                writeSettings();
                if (clearUidDefaultsLocked(uid)) {
                    writeSettingsLocked();
                }
            }
        }
    }
@@ -360,7 +366,9 @@ class UsbDeviceSettingsManager {

    public UsbDeviceSettingsManager(Context context) {
        mContext = context;
        readSettings();
        synchronized (mLock) {
            readSettingsLocked();
        }
        mPackageMonitor.register(context, true);
    }

@@ -423,7 +431,7 @@ class UsbDeviceSettingsManager {
        XmlUtils.nextElement(parser);
    }

    private void readSettings() {
    private void readSettingsLocked() {
        FileInputStream stream = null;
        try {
            stream = new FileInputStream(sSettingsFile);
@@ -458,7 +466,7 @@ class UsbDeviceSettingsManager {
        }
    }

    private void writeSettings() {
    private void writeSettingsLocked() {
        FileOutputStream fos = null;
        try {
            FileOutputStream fstr = new FileOutputStream(sSettingsFile);
@@ -524,7 +532,7 @@ class UsbDeviceSettingsManager {

    // Checks to see if a package matches a device or accessory.
    // Only one of device and accessory should be non-null.
    private boolean packageMatches(ResolveInfo info, String metaDataName,
    private boolean packageMatchesLocked(ResolveInfo info, String metaDataName,
            UsbDevice device, UsbAccessory accessory) {
        ActivityInfo ai = info.activityInfo;
        PackageManager pm = mContext.getPackageManager();
@@ -562,7 +570,7 @@ class UsbDeviceSettingsManager {
        return false;
    }

    private final ArrayList<ResolveInfo> getDeviceMatches(UsbDevice device, Intent intent) {
    private final ArrayList<ResolveInfo> getDeviceMatchesLocked(UsbDevice device, Intent intent) {
        ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
        PackageManager pm = mContext.getPackageManager();
        List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent,
@@ -570,14 +578,15 @@ class UsbDeviceSettingsManager {
        int count = resolveInfos.size();
        for (int i = 0; i < count; i++) {
            ResolveInfo resolveInfo = resolveInfos.get(i);
            if (packageMatches(resolveInfo, intent.getAction(), device, null)) {
            if (packageMatchesLocked(resolveInfo, intent.getAction(), device, null)) {
                matches.add(resolveInfo);
            }
        }
        return matches;
    }

    private final ArrayList<ResolveInfo> getAccessoryMatches(UsbAccessory accessory, Intent intent) {
    private final ArrayList<ResolveInfo> getAccessoryMatchesLocked(
            UsbAccessory accessory, Intent intent) {
        ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
        PackageManager pm = mContext.getPackageManager();
        List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent,
@@ -585,7 +594,7 @@ class UsbDeviceSettingsManager {
        int count = resolveInfos.size();
        for (int i = 0; i < count; i++) {
            ResolveInfo resolveInfo = resolveInfos.get(i);
            if (packageMatches(resolveInfo, intent.getAction(), null, accessory)) {
            if (packageMatchesLocked(resolveInfo, intent.getAction(), null, accessory)) {
                matches.add(resolveInfo);
            }
        }
@@ -597,10 +606,15 @@ class UsbDeviceSettingsManager {
        deviceIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
        deviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ArrayList<ResolveInfo> matches = getDeviceMatches(device, deviceIntent);
        ArrayList<ResolveInfo> matches;
        String defaultPackage;
        synchronized (mLock) {
            matches = getDeviceMatchesLocked(device, deviceIntent);
            // Launch our default activity directly, if we have one.
            // Otherwise we will start the UsbResolverActivity to allow the user to choose.
        String defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
            defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
        }

        if (defaultPackage != null) {
            int count = matches.size();
            for (int i = 0; i < count; i++) {
@@ -623,8 +637,7 @@ class UsbDeviceSettingsManager {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        intent.putExtra(Intent.EXTRA_INTENT, deviceIntent);
        intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS,
                matches);
        intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches);
        try {
            mContext.startActivity(intent);
        } catch (ActivityNotFoundException e) {
@@ -644,10 +657,15 @@ class UsbDeviceSettingsManager {
        accessoryIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
        accessoryIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ArrayList<ResolveInfo> matches = getAccessoryMatches(accessory, accessoryIntent);
        ArrayList<ResolveInfo> matches;
        String defaultPackage;
        synchronized (mLock) {
            matches = getAccessoryMatchesLocked(accessory, accessoryIntent);
            // Launch our default activity directly, if we have one.
            // Otherwise we will start the UsbResolverActivity to allow the user to choose.
        String defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory));
            defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory));
        }

        if (defaultPackage != null) {
            int count = matches.size();
            for (int i = 0; i < count; i++) {
@@ -670,8 +688,7 @@ class UsbDeviceSettingsManager {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        intent.putExtra(Intent.EXTRA_INTENT, accessoryIntent);
        intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS,
                matches);
        intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches);
        try {
            mContext.startActivity(intent);
        } catch (ActivityNotFoundException e) {
@@ -688,6 +705,7 @@ class UsbDeviceSettingsManager {

    public void checkPermission(UsbDevice device) {
        if (device == null) return;
        synchronized (mLock) {
            ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(Binder.getCallingUid());
            if (filterList != null) {
                int count = filterList.size();
@@ -699,11 +717,13 @@ class UsbDeviceSettingsManager {
                    }
                }
            }
        }
        throw new SecurityException("User has not given permission to device " + device);
    }

    public void checkPermission(UsbAccessory accessory) {
        if (accessory == null) return;
        synchronized (mLock) {
            ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(Binder.getCallingUid());
            if (filterList != null) {
                int count = filterList.size();
@@ -715,32 +735,38 @@ class UsbDeviceSettingsManager {
                    }
                }
            }
        }
        throw new SecurityException("User has not given permission to accessory " + accessory);
    }

    public void setDevicePackage(UsbDevice device, String packageName) {
        DeviceFilter filter = new DeviceFilter(device);
        synchronized (mLock) {
            if (packageName == null) {
                mDevicePreferenceMap.remove(filter);
            } else {
                mDevicePreferenceMap.put(filter, packageName);
            }
           // FIXME - only if changed
        writeSettings();
            writeSettingsLocked();
        }
    }

    public void setAccessoryPackage(UsbAccessory accessory, String packageName) {
        AccessoryFilter filter = new AccessoryFilter(accessory);
        synchronized (mLock) {
            if (packageName == null) {
                mAccessoryPreferenceMap.remove(filter);
            } else {
                mAccessoryPreferenceMap.put(filter, packageName);
            }
            // FIXME - only if changed
        writeSettings();
            writeSettingsLocked();
        }
    }

    public void grantDevicePermission(UsbDevice device, int uid) {
        synchronized (mLock) {
            ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(uid);
            if (filterList == null) {
                filterList = new ArrayList<DeviceFilter>();
@@ -752,10 +778,12 @@ class UsbDeviceSettingsManager {
                }
            }
            filterList.add(new DeviceFilter(device));
        writeSettings();
            writeSettingsLocked();
        }
    }

    public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
        synchronized (mLock) {
            ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(uid);
            if (filterList == null) {
                filterList = new ArrayList<AccessoryFilter>();
@@ -767,26 +795,31 @@ class UsbDeviceSettingsManager {
                }
            }
            filterList.add(new AccessoryFilter(accessory));
        writeSettings();
            writeSettingsLocked();
        }
    }

    public boolean hasDefaults(String packageName, int uid) {
        synchronized (mLock) {
            if (mDevicePermissionMap.get(uid) != null) return true;
            if (mAccessoryPermissionMap.get(uid) != null) return true;
            if (mDevicePreferenceMap.values().contains(packageName)) return true;
            if (mAccessoryPreferenceMap.values().contains(packageName)) return true;
            return false;
        }
    }

    public void clearDefaults(String packageName, int uid) {
        boolean packageCleared = clearPackageDefaults(packageName);
        boolean uidCleared = clearUidDefaults(uid);
        synchronized (mLock) {
            boolean packageCleared = clearPackageDefaultsLocked(packageName);
            boolean uidCleared = clearUidDefaultsLocked(uid);
            if (packageCleared || uidCleared) {
            writeSettings();
                writeSettingsLocked();
            }
        }
    }

    private boolean clearUidDefaults(int uid) {
    private boolean clearUidDefaultsLocked(int uid) {
        boolean cleared = false;
        int index = mDevicePermissionMap.indexOfKey(uid);
        if (index >= 0) {
@@ -801,8 +834,9 @@ class UsbDeviceSettingsManager {
        return cleared;
    }

    private boolean clearPackageDefaults(String packageName) {
    private boolean clearPackageDefaultsLocked(String packageName) {
        boolean cleared = false;
        synchronized (mLock) {
            if (mDevicePreferenceMap.containsValue(packageName)) {
                // make a copy of the key set to avoid ConcurrentModificationException
                Object[] keys = mDevicePreferenceMap.keySet().toArray();
@@ -827,8 +861,10 @@ class UsbDeviceSettingsManager {
            }
            return cleared;
        }
    }

    public void dump(FileDescriptor fd, PrintWriter pw) {
        synchronized (mLock) {
            pw.println("  Device permissions:");
            int count = mDevicePermissionMap.size();
            for (int i = 0; i < count; i++) {
@@ -859,3 +895,4 @@ class UsbDeviceSettingsManager {
            }
        }
    }
}
+12 −24
Original line number Diff line number Diff line
@@ -454,46 +454,34 @@ public class UsbService extends IUsbManager.Stub {
    }

    public void setDevicePackage(UsbDevice device, String packageName) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.setDevicePackage(device, packageName);
    }
    }

    public void setAccessoryPackage(UsbAccessory accessory, String packageName) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.setAccessoryPackage(accessory, packageName);
    }
    }

    public void grantDevicePermission(UsbDevice device, int uid) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.grantDevicePermission(device, uid);
    }
    }

    public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.grantAccessoryPermission(accessory, uid);
    }
    }

    public boolean hasDefaults(String packageName, int uid) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        return mDeviceManager.hasDefaults(packageName, uid);
    }
    }

    public void clearDefaults(String packageName, int uid) {
        synchronized (mLock) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.clearDefaults(packageName, uid);
    }
    }

    /*
     * This handler is for deferred handling of events related to device mode and accessories.