1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.usb;
18 
19 import android.annotation.NonNull;
20 import android.annotation.UserIdInt;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.UserInfo;
24 import android.hardware.usb.UsbAccessory;
25 import android.hardware.usb.UsbDevice;
26 import android.hardware.usb.UsbManager;
27 import android.os.UserHandle;
28 import android.os.UserManager;
29 import android.service.usb.UsbSettingsManagerProto;
30 import android.util.Slog;
31 import android.util.SparseArray;
32 
33 import com.android.internal.annotations.GuardedBy;
34 import com.android.internal.util.dump.DualDumpOutputStream;
35 
36 import java.util.List;
37 
38 class UsbPermissionManager {
39     private static final String LOG_TAG = UsbPermissionManager.class.getSimpleName();
40     private static final boolean DEBUG = false;
41 
42     /** Context to be used by this module */
43     private final @NonNull Context mContext;
44 
45     /** Map from user id to {@link UsbUserPermissionManager} for the user */
46     @GuardedBy("mPermissionsByUser")
47     private final SparseArray<UsbUserPermissionManager> mPermissionsByUser = new SparseArray<>();
48 
49     final UsbService mUsbService;
50 
UsbPermissionManager(@onNull Context context, @NonNull UsbService usbService)51     UsbPermissionManager(@NonNull Context context,
52             @NonNull UsbService usbService) {
53         mContext = context;
54         mUsbService = usbService;
55     }
56 
getPermissionsForUser(@serIdInt int userId)57     @NonNull UsbUserPermissionManager getPermissionsForUser(@UserIdInt int userId) {
58         synchronized (mPermissionsByUser) {
59             UsbUserPermissionManager permissions = mPermissionsByUser.get(userId);
60             if (permissions == null) {
61                 permissions = new UsbUserPermissionManager(mContext.createContextAsUser(
62                         UserHandle.of(userId), 0), mUsbService.getSettingsForUser(userId));
63                 mPermissionsByUser.put(userId, permissions);
64             }
65             return permissions;
66         }
67     }
68 
getPermissionsForUser(@onNull UserHandle user)69     @NonNull UsbUserPermissionManager getPermissionsForUser(@NonNull UserHandle user) {
70         return getPermissionsForUser(user.getIdentifier());
71     }
72 
remove(@onNull UserHandle userToRemove)73     void remove(@NonNull UserHandle userToRemove) {
74         synchronized (mPermissionsByUser) {
75             mPermissionsByUser.remove(userToRemove.getIdentifier());
76         }
77     }
78 
79     /**
80      * Remove temporary access permission and broadcast that a device was removed.
81      *
82      * @param device The device that is removed
83      */
usbDeviceRemoved(@onNull UsbDevice device)84     void usbDeviceRemoved(@NonNull UsbDevice device) {
85         synchronized (mPermissionsByUser) {
86             for (int i = 0; i < mPermissionsByUser.size(); i++) {
87                 // clear temporary permissions for the device
88                 mPermissionsByUser.valueAt(i).removeDevicePermissions(device);
89             }
90         }
91 
92         Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
93         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
94         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
95 
96         if (DEBUG) {
97             Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent);
98         }
99         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
100     }
101 
102     /**
103      * Remove temporary access permission and broadcast that a accessory was removed.
104      *
105      * @param accessory The accessory that is removed
106      */
usbAccessoryRemoved(@onNull UsbAccessory accessory)107     void usbAccessoryRemoved(@NonNull UsbAccessory accessory) {
108         synchronized (mPermissionsByUser) {
109             for (int i = 0; i < mPermissionsByUser.size(); i++) {
110                 // clear temporary permissions for the accessory
111                 mPermissionsByUser.valueAt(i).removeAccessoryPermissions(accessory);
112             }
113         }
114 
115         Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
116         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
117         intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
118         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
119     }
120 
dump(@onNull DualDumpOutputStream dump, String idName, long id)121     void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
122         long token = dump.start(idName, id);
123         UserManager userManager = mContext.getSystemService(UserManager.class);
124         synchronized (mPermissionsByUser) {
125             List<UserInfo> users = userManager.getUsers();
126             int numUsers = users.size();
127             for (int i = 0; i < numUsers; i++) {
128                 getPermissionsForUser(users.get(i).id).dump(dump, "user_permissions",
129                         UsbSettingsManagerProto.USER_SETTINGS);
130             }
131         }
132         dump.end(token);
133     }
134 
135 }
136