/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.usb;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.AccessoryFilter;
import android.hardware.usb.DeviceFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Environment;
import android.os.Process;
import android.os.UserHandle;
import android.service.usb.UsbAccessoryPermissionProto;
import android.service.usb.UsbAccessoryPersistentPermissionProto;
import android.service.usb.UsbDevicePermissionProto;
import android.service.usb.UsbDevicePersistentPermissionProto;
import android.service.usb.UsbUidPermissionProto;
import android.service.usb.UsbUserPermissionsManagerProto;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.dump.DualDumpOutputStream;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * UsbUserPermissionManager manages usb device or accessory access permissions.
 *
 * @hide
 */
class UsbUserPermissionManager {
    private static final String TAG = UsbUserPermissionManager.class.getSimpleName();
    private static final boolean DEBUG = false;

    @GuardedBy("mLock")
    /** Mapping of USB device name to list of UIDs with permissions for the device
     * Each entry lasts until device is disconnected*/
    private final ArrayMap<String, SparseBooleanArray> mDevicePermissionMap =
            new ArrayMap<>();
    @GuardedBy("mLock")
    /** Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory
     * Each entry lasts until accessory is disconnected*/
    private final ArrayMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap =
            new ArrayMap<>();

    @GuardedBy("mLock")
    /** Maps USB device to list of UIDs with persistent permissions for the device*/
    private final ArrayMap<DeviceFilter, SparseBooleanArray>
            mDevicePersistentPermissionMap = new ArrayMap<>();
    @GuardedBy("mLock")
    /** Maps Usb Accessory to list of UIDs with persistent permissions for the accessory*/
    private final ArrayMap<AccessoryFilter, SparseBooleanArray>
            mAccessoryPersistentPermissionMap = new ArrayMap<>();

    private final Context mContext;
    private final UserHandle mUser;
    private final UsbUserSettingsManager mUsbUserSettingsManager;
    private final boolean mDisablePermissionDialogs;

    private final @NonNull AtomicFile mPermissionsFile;

    private final Object mLock = new Object();

    /**
     * If a async task to persist the mDevicePersistentPreferenceMap and
     * mAccessoryPersistentPreferenceMap is currently scheduled.
     */
    @GuardedBy("mLock")
    private boolean mIsCopyPermissionsScheduled;

    UsbUserPermissionManager(@NonNull Context context,
            @NonNull UsbUserSettingsManager usbUserSettingsManager) {
        mContext = context;
        mUser = context.getUser();
        mUsbUserSettingsManager = usbUserSettingsManager;
        mDisablePermissionDialogs = context.getResources().getBoolean(
                com.android.internal.R.bool.config_disableUsbPermissionDialogs);

        mPermissionsFile = new AtomicFile(new File(
                Environment.getUserSystemDirectory(mUser.getIdentifier()),
                "usb_permissions.xml"), "usb-permissions");

        synchronized (mLock) {
            readPermissionsLocked();
        }
    }

    /**
     * Removes access permissions of all packages for the USB accessory.
     *
     * @param accessory to remove permissions for
     */
    void removeAccessoryPermissions(@NonNull UsbAccessory accessory) {
        synchronized (mLock) {
            mAccessoryPermissionMap.remove(accessory);
        }
    }

    /**
     * Removes access permissions of all packages for the USB device.
     *
     * @param device to remove permissions for
     */
    void removeDevicePermissions(@NonNull UsbDevice device) {
        synchronized (mLock) {
            mDevicePermissionMap.remove(device.getDeviceName());
        }
    }

    /**
     * Grants permission for USB device without showing system dialog for package with uid.
     *
     * @param device to grant permission for
     * @param uid to grant permission for
     */
    void grantDevicePermission(@NonNull UsbDevice device, int uid) {
        synchronized (mLock) {
            String deviceName = device.getDeviceName();
            SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
            if (uidList == null) {
                uidList = new SparseBooleanArray(1);
                mDevicePermissionMap.put(deviceName, uidList);
            }
            uidList.put(uid, true);
        }
    }

    /**
     * Grants permission for USB accessory without showing system dialog for package with uid.
     *
     * @param accessory to grant permission for
     * @param uid to grant permission for
     */
    void grantAccessoryPermission(@NonNull UsbAccessory accessory, int uid) {
        synchronized (mLock) {
            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
            if (uidList == null) {
                uidList = new SparseBooleanArray(1);
                mAccessoryPermissionMap.put(accessory, uidList);
            }
            uidList.put(uid, true);
        }
    }

    /**
     * Returns true if package with uid has permission to access the device.
     *
     * @param device to check permission for
     * @param pid to check permission for
     * @param uid to check permission for
     * @return {@code true} if package with uid has permission
     */
    boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid,
            int uid) {
        if (isCameraDevicePresent(device)) {
            if (!isCameraPermissionGranted(packageName, pid, uid)) {
                return false;
            }
        }
        synchronized (mLock) {
            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
                return true;
            }
            DeviceFilter filter = new DeviceFilter(device);
            SparseBooleanArray permissionsForDevice = mDevicePersistentPermissionMap.get(filter);
            if (permissionsForDevice != null) {
                int idx = permissionsForDevice.indexOfKey(uid);
                if (idx >= 0) {
                    return permissionsForDevice.valueAt(idx);
                }
            }
            SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
            if (uidList == null) {
                return false;
            }
            return uidList.get(uid);
        }
    }

    /**
     * Returns true if caller has permission to access the accessory.
     *
     * @param accessory to check permission for
     * @param uid to check permission for
     * @return {@code true} if caller has permssion
     */
    boolean hasPermission(@NonNull UsbAccessory accessory, int uid) {
        synchronized (mLock) {
            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
                return true;
            }
            AccessoryFilter filter = new AccessoryFilter(accessory);
            SparseBooleanArray permissionsForAccessory =
                    mAccessoryPersistentPermissionMap.get(filter);
            if (permissionsForAccessory != null) {
                int idx = permissionsForAccessory.indexOfKey(uid);
                if (idx >= 0) {
                    return permissionsForAccessory.valueAt(idx);
                }
            }
            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
            if (uidList == null) {
                return false;
            }
            return uidList.get(uid);
        }
    }

    void setDevicePersistentPermission(@NonNull UsbDevice device, int uid, boolean isGranted) {

        boolean isChanged;
        DeviceFilter filter = new DeviceFilter(device);
        synchronized (mLock) {
            SparseBooleanArray permissionsForDevice = mDevicePersistentPermissionMap.get(filter);
            if (permissionsForDevice == null) {
                permissionsForDevice = new SparseBooleanArray();
                mDevicePersistentPermissionMap.put(filter, permissionsForDevice);
            }
            int idx = permissionsForDevice.indexOfKey(uid);
            if (idx >= 0) {
                isChanged = permissionsForDevice.valueAt(idx) != isGranted;
                permissionsForDevice.setValueAt(idx, isGranted);
            } else {
                isChanged = true;
                permissionsForDevice.put(uid, isGranted);
            }

            if (isChanged) {
                scheduleWritePermissionsLocked();
            }
        }
    }

    void setAccessoryPersistentPermission(@NonNull UsbAccessory accessory, int uid,
            boolean isGranted) {

        boolean isChanged;
        AccessoryFilter filter = new AccessoryFilter(accessory);
        synchronized (mLock) {
            SparseBooleanArray permissionsForAccessory =
                    mAccessoryPersistentPermissionMap.get(filter);
            if (permissionsForAccessory == null) {
                permissionsForAccessory = new SparseBooleanArray();
                mAccessoryPersistentPermissionMap.put(filter, permissionsForAccessory);
            }
            int idx = permissionsForAccessory.indexOfKey(uid);
            if (idx >= 0) {
                isChanged = permissionsForAccessory.valueAt(idx) != isGranted;
                permissionsForAccessory.setValueAt(idx, isGranted);
            } else {
                isChanged = true;
                permissionsForAccessory.put(uid, isGranted);
            }

            if (isChanged) {
                scheduleWritePermissionsLocked();
            }
        }
    }

    private void readPermission(@NonNull XmlPullParser parser) throws XmlPullParserException,
            IOException {
        int uid;
        boolean isGranted;

        try {
            uid = XmlUtils.readIntAttribute(parser, "uid");
        } catch (NumberFormatException e) {
            Slog.e(TAG, "error reading usb permission uid", e);
            XmlUtils.skipCurrentTag(parser);
            return;
        }

        // only use "true"/"false" as valid values
        String isGrantedString = parser.getAttributeValue(null, "granted");
        if (isGrantedString == null || !(isGrantedString.equals(Boolean.TRUE.toString())
                || isGrantedString.equals(Boolean.FALSE.toString()))) {
            Slog.e(TAG, "error reading usb permission granted state");
            XmlUtils.skipCurrentTag(parser);
            return;
        }
        isGranted = isGrantedString.equals(Boolean.TRUE.toString());
        XmlUtils.nextElement(parser);
        if ("usb-device".equals(parser.getName())) {
            DeviceFilter filter = DeviceFilter.read(parser);
            int idx = mDevicePersistentPermissionMap.indexOfKey(filter);
            if (idx >= 0) {
                SparseBooleanArray permissionsForDevice =
                        mDevicePersistentPermissionMap.valueAt(idx);
                permissionsForDevice.put(uid, isGranted);
            } else {
                SparseBooleanArray permissionsForDevice = new SparseBooleanArray();
                mDevicePersistentPermissionMap.put(filter, permissionsForDevice);
                permissionsForDevice.put(uid, isGranted);
            }
        } else if ("usb-accessory".equals(parser.getName())) {
            AccessoryFilter filter = AccessoryFilter.read(parser);
            int idx = mAccessoryPersistentPermissionMap.indexOfKey(filter);
            if (idx >= 0) {
                SparseBooleanArray permissionsForAccessory =
                        mAccessoryPersistentPermissionMap.valueAt(idx);
                permissionsForAccessory.put(uid, isGranted);
            } else {
                SparseBooleanArray permissionsForAccessory = new SparseBooleanArray();
                mAccessoryPersistentPermissionMap.put(filter, permissionsForAccessory);
                permissionsForAccessory.put(uid, isGranted);
            }
        }
    }

    @GuardedBy("mLock")
    private void readPermissionsLocked() {
        mDevicePersistentPermissionMap.clear();
        mAccessoryPersistentPermissionMap.clear();

        try (FileInputStream in = mPermissionsFile.openRead()) {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, StandardCharsets.UTF_8.name());

            XmlUtils.nextElement(parser);
            while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
                String tagName = parser.getName();
                if ("permission".equals(tagName)) {
                    readPermission(parser);
                } else {
                    XmlUtils.nextElement(parser);
                }
            }
        } catch (FileNotFoundException e) {
            if (DEBUG) Slog.d(TAG, "usb permissions file not found");
        } catch (Exception e) {
            Slog.e(TAG, "error reading usb permissions file, deleting to start fresh", e);
            mPermissionsFile.delete();
        }
    }

    @GuardedBy("mLock")
    private void scheduleWritePermissionsLocked() {
        if (mIsCopyPermissionsScheduled) {
            return;
        }
        mIsCopyPermissionsScheduled = true;

        AsyncTask.execute(() -> {
            int numDevices;
            DeviceFilter[] devices;
            int[][] uidsForDevices;
            boolean[][] grantedValuesForDevices;

            int numAccessories;
            AccessoryFilter[] accessories;
            int[][] uidsForAccessories;
            boolean[][] grantedValuesForAccessories;

            synchronized (mLock) {
                // Copy the permission state so we can write outside of lock
                numDevices = mDevicePersistentPermissionMap.size();
                devices = new DeviceFilter[numDevices];
                uidsForDevices = new int[numDevices][];
                grantedValuesForDevices = new boolean[numDevices][];
                for (int deviceIdx = 0; deviceIdx < numDevices; deviceIdx++) {
                    devices[deviceIdx] =
                            new DeviceFilter(mDevicePersistentPermissionMap.keyAt(deviceIdx));
                    SparseBooleanArray permissions =
                            mDevicePersistentPermissionMap.valueAt(deviceIdx);
                    int numPermissions = permissions.size();
                    uidsForDevices[deviceIdx] = new int[numPermissions];
                    grantedValuesForDevices[deviceIdx] = new boolean[numPermissions];
                    for (int permissionIdx = 0; permissionIdx < numPermissions; permissionIdx++) {
                        uidsForDevices[deviceIdx][permissionIdx] = permissions.keyAt(permissionIdx);
                        grantedValuesForDevices[deviceIdx][permissionIdx] =
                                permissions.valueAt(permissionIdx);
                    }
                }

                numAccessories = mAccessoryPersistentPermissionMap.size();
                accessories = new AccessoryFilter[numAccessories];
                uidsForAccessories = new int[numAccessories][];
                grantedValuesForAccessories = new boolean[numAccessories][];
                for (int accessoryIdx = 0; accessoryIdx < numAccessories; accessoryIdx++) {
                    accessories[accessoryIdx] = new AccessoryFilter(
                                    mAccessoryPersistentPermissionMap.keyAt(accessoryIdx));
                    SparseBooleanArray permissions =
                            mAccessoryPersistentPermissionMap.valueAt(accessoryIdx);
                    int numPermissions = permissions.size();
                    uidsForAccessories[accessoryIdx] = new int[numPermissions];
                    grantedValuesForAccessories[accessoryIdx] = new boolean[numPermissions];
                    for (int permissionIdx = 0; permissionIdx < numPermissions; permissionIdx++) {
                        uidsForAccessories[accessoryIdx][permissionIdx] =
                                permissions.keyAt(permissionIdx);
                        grantedValuesForAccessories[accessoryIdx][permissionIdx] =
                                permissions.valueAt(permissionIdx);
                    }
                }
                mIsCopyPermissionsScheduled = false;
            }

            synchronized (mPermissionsFile) {
                FileOutputStream out = null;
                try {
                    out = mPermissionsFile.startWrite();
                    FastXmlSerializer serializer = new FastXmlSerializer();
                    serializer.setOutput(out, StandardCharsets.UTF_8.name());
                    serializer.startDocument(null, true);
                    serializer.startTag(null, "permissions");

                    for (int i = 0; i < numDevices; i++) {
                        int numPermissions = uidsForDevices[i].length;
                        for (int j = 0; j < numPermissions; j++) {
                            serializer.startTag(null, "permission");
                            serializer.attribute(null, "uid",
                                    Integer.toString(uidsForDevices[i][j]));
                            serializer.attribute(null, "granted",
                                    Boolean.toString(grantedValuesForDevices[i][j]));
                            devices[i].write(serializer);
                            serializer.endTag(null, "permission");
                        }
                    }

                    for (int i = 0; i < numAccessories; i++) {
                        int numPermissions = uidsForAccessories[i].length;
                        for (int j = 0; j < numPermissions; j++) {
                            serializer.startTag(null, "permission");
                            serializer.attribute(null, "uid",
                                    Integer.toString(uidsForAccessories[i][j]));
                            serializer.attribute(null, "granted",
                                    Boolean.toString(grantedValuesForDevices[i][j]));
                            accessories[i].write(serializer);
                            serializer.endTag(null, "permission");
                        }
                    }

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

                    mPermissionsFile.finishWrite(out);
                } catch (IOException e) {
                    Slog.e(TAG, "Failed to write permissions", e);
                    if (out != null) {
                        mPermissionsFile.failWrite(out);
                    }
                }
            }
        });
    }

    /**
     * Creates UI dialog to request permission for the given package to access the device
     * or accessory.
     *
     * @param device       The USB device attached
     * @param accessory    The USB accessory attached
     * @param canBeDefault Whether the calling pacakge can set as default handler
     *                     of the USB device or accessory
     * @param packageName  The package name of the calling package
     * @param uid          The uid of the calling package
     * @param userContext  The context to start the UI dialog
     * @param pi           PendingIntent for returning result
     */
    void requestPermissionDialog(@Nullable UsbDevice device,
            @Nullable UsbAccessory accessory,
            boolean canBeDefault,
            @NonNull String packageName,
            int uid,
            @NonNull Context userContext,
            @NonNull PendingIntent pi) {
        long identity = Binder.clearCallingIdentity();
        Intent intent = new Intent();
        if (device != null) {
            intent.putExtra(UsbManager.EXTRA_DEVICE, device);
        } else {
            intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
        }
        intent.putExtra(Intent.EXTRA_INTENT, pi);
        intent.putExtra(Intent.EXTRA_UID, uid);
        intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault);
        intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName);
        intent.setComponent(ComponentName.unflattenFromString(userContext.getResources().getString(
                com.android.internal.R.string.config_usbPermissionActivity)));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
            userContext.startActivityAsUser(intent, mUser);
        } catch (ActivityNotFoundException e) {
            Slog.e(TAG, "unable to start UsbPermissionActivity");
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
        long token = dump.start(idName, id);
        synchronized (mLock) {
            dump.write("user_id", UsbUserPermissionsManagerProto.USER_ID, mUser.getIdentifier());
            int numMappings = mDevicePermissionMap.size();
            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
                String deviceName = mDevicePermissionMap.keyAt(mappingsIdx);
                long devicePermissionToken = dump.start("device_permissions",
                        UsbUserPermissionsManagerProto.DEVICE_PERMISSIONS);

                dump.write("device_name", UsbDevicePermissionProto.DEVICE_NAME, deviceName);

                SparseBooleanArray uidList = mDevicePermissionMap.valueAt(mappingsIdx);
                int numUids = uidList.size();
                for (int uidsIdx = 0; uidsIdx < numUids; uidsIdx++) {
                    dump.write("uids", UsbDevicePermissionProto.UIDS, uidList.keyAt(uidsIdx));
                }

                dump.end(devicePermissionToken);
            }

            numMappings = mAccessoryPermissionMap.size();
            for (int mappingsIdx = 0; mappingsIdx < numMappings; ++mappingsIdx) {
                UsbAccessory accessory = mAccessoryPermissionMap.keyAt(mappingsIdx);
                long accessoryPermissionToken = dump.start("accessory_permissions",
                        UsbUserPermissionsManagerProto.ACCESSORY_PERMISSIONS);

                dump.write("accessory_description",
                        UsbAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
                        accessory.getDescription());

                SparseBooleanArray uidList = mAccessoryPermissionMap.valueAt(mappingsIdx);
                int numUids = uidList.size();
                for (int uidsIdx = 0; uidsIdx < numUids; uidsIdx++) {
                    dump.write("uids", UsbAccessoryPermissionProto.UIDS, uidList.keyAt(uidsIdx));
                }

                dump.end(accessoryPermissionToken);
            }

            numMappings = mDevicePersistentPermissionMap.size();
            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
                DeviceFilter filter = mDevicePersistentPermissionMap.keyAt(mappingsIdx);
                long devicePermissionToken = dump.start("device_persistent_permissions",
                        UsbUserPermissionsManagerProto.DEVICE_PERSISTENT_PERMISSIONS);
                filter.dump(dump, "device",
                        UsbDevicePersistentPermissionProto.DEVICE_FILTER);
                SparseBooleanArray permissions =
                        mDevicePersistentPermissionMap.valueAt(mappingsIdx);
                int numPermissions = permissions.size();
                for (int permissionsIdx = 0; permissionsIdx < numPermissions; permissionsIdx++) {
                    long uidPermissionToken = dump.start("uid_permission",
                            UsbDevicePersistentPermissionProto.PERMISSION_VALUES);
                    dump.write("uid", UsbUidPermissionProto.UID, permissions.keyAt(permissionsIdx));
                    dump.write("is_granted",
                            UsbUidPermissionProto.IS_GRANTED, permissions.valueAt(permissionsIdx));
                    dump.end(uidPermissionToken);
                }
                dump.end(devicePermissionToken);
            }

            numMappings = mAccessoryPersistentPermissionMap.size();
            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
                AccessoryFilter filter = mAccessoryPersistentPermissionMap.keyAt(mappingsIdx);
                long accessoryPermissionToken = dump.start("accessory_persistent_permissions",
                        UsbUserPermissionsManagerProto.ACCESSORY_PERSISTENT_PERMISSIONS);
                filter.dump(dump, "accessory",
                        UsbAccessoryPersistentPermissionProto.ACCESSORY_FILTER);
                SparseBooleanArray permissions =
                        mAccessoryPersistentPermissionMap.valueAt(mappingsIdx);
                int numPermissions = permissions.size();
                for (int permissionsIdx = 0; permissionsIdx < numPermissions; permissionsIdx++) {
                    long uidPermissionToken = dump.start("uid_permission",
                            UsbAccessoryPersistentPermissionProto.PERMISSION_VALUES);
                    dump.write("uid", UsbUidPermissionProto.UID, permissions.keyAt(permissionsIdx));
                    dump.write("is_granted",
                            UsbUidPermissionProto.IS_GRANTED, permissions.valueAt(permissionsIdx));
                    dump.end(uidPermissionToken);
                }
                dump.end(accessoryPermissionToken);
            }
        }
        dump.end(token);
    }

    /**
     * Check for camera permission of the calling process.
     *
     * @param packageName Package name of the caller.
     * @param pid         Linux pid of the calling process.
     * @param uid         Linux uid of the calling process.
     * @return True in case camera permission is available, False otherwise.
     */
    private boolean isCameraPermissionGranted(String packageName, int pid, int uid) {
        int targetSdkVersion = android.os.Build.VERSION_CODES.P;
        try {
            ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
            // compare uid with packageName to foil apps pretending to be someone else
            if (aInfo.uid != uid) {
                Slog.i(TAG, "Package " + packageName + " does not match caller's uid " + uid);
                return false;
            }
            targetSdkVersion = aInfo.targetSdkVersion;
        } catch (PackageManager.NameNotFoundException e) {
            Slog.i(TAG, "Package not found, likely due to invalid package name!");
            return false;
        }

        if (targetSdkVersion >= android.os.Build.VERSION_CODES.P) {
            int allowed = mContext.checkPermission(android.Manifest.permission.CAMERA, pid, uid);
            if (android.content.pm.PackageManager.PERMISSION_DENIED == allowed) {
                Slog.i(TAG, "Camera permission required for USB video class devices");
                return false;
            }
        }

        return true;
    }

    public void checkPermission(UsbDevice device, String packageName, int pid, int uid) {
        if (!hasPermission(device, packageName, pid, uid)) {
            throw new SecurityException("User has not given " + uid + "/" + packageName
                    + " permission to access device " + device.getDeviceName());
        }
    }

    public void checkPermission(UsbAccessory accessory, int uid) {
        if (!hasPermission(accessory, uid)) {
            throw new SecurityException("User has not given " + uid + " permission to accessory "
                    + accessory);
        }
    }

    private void requestPermissionDialog(@Nullable UsbDevice device,
            @Nullable UsbAccessory accessory,
            boolean canBeDefault,
            String packageName,
            PendingIntent pi,
            int uid) {
        // compare uid with packageName to foil apps pretending to be someone else
        try {
            ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
            if (aInfo.uid != uid) {
                throw new IllegalArgumentException("package " + packageName
                        + " does not match caller's uid " + uid);
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new IllegalArgumentException("package " + packageName + " not found");
        }

        requestPermissionDialog(device, accessory, canBeDefault, packageName, uid, mContext, pi);
    }

    public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int pid,
            int uid) {
        Intent intent = new Intent();

        // respond immediately if permission has already been granted
        if (hasPermission(device, packageName, pid, uid)) {
            intent.putExtra(UsbManager.EXTRA_DEVICE, device);
            intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
            try {
                pi.send(mContext, 0, intent);
            } catch (PendingIntent.CanceledException e) {
                if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
            }
            return;
        }
        if (isCameraDevicePresent(device)) {
            if (!isCameraPermissionGranted(packageName, pid, uid)) {
                intent.putExtra(UsbManager.EXTRA_DEVICE, device);
                intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
                try {
                    pi.send(mContext, 0, intent);
                } catch (PendingIntent.CanceledException e) {
                    if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
                }
                return;
            }
        }

        requestPermissionDialog(device, null,
                mUsbUserSettingsManager.canBeDefault(device, packageName), packageName, pi, uid);
    }

    public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi,
            int uid) {
        // respond immediately if permission has already been granted
        if (hasPermission(accessory, uid)) {
            Intent intent = new Intent();
            intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
            intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
            try {
                pi.send(mContext, 0, intent);
            } catch (PendingIntent.CanceledException e) {
                if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
            }
            return;
        }

        requestPermissionDialog(null, accessory,
                mUsbUserSettingsManager.canBeDefault(accessory, packageName), packageName, pi, uid);
    }

    /**
     * Check whether a particular device or any of its interfaces
     * is of class VIDEO.
     *
     * @param device The device that needs to get scanned
     * @return True in case a VIDEO device or interface is present,
     * False otherwise.
     */
    private boolean isCameraDevicePresent(UsbDevice device) {
        if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) {
            return true;
        }

        for (int i = 0; i < device.getInterfaceCount(); i++) {
            UsbInterface iface = device.getInterface(i);
            if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_VIDEO) {
                return true;
            }
        }

        return false;
    }
}
