1 /* 2 * Copyright (C) 2016 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.util.Slog; 30 import android.util.SparseArray; 31 import com.android.internal.annotations.GuardedBy; 32 import com.android.internal.util.IndentingPrintWriter; 33 34 /** 35 * Maintains all {@link UsbUserSettingsManager} for all users. 36 */ 37 class UsbSettingsManager { 38 private static final String LOG_TAG = UsbSettingsManager.class.getSimpleName(); 39 private static final boolean DEBUG = false; 40 41 /** Context to be used by this module */ 42 private final @NonNull Context mContext; 43 44 /** Map from user id to {@link UsbUserSettingsManager} for the user */ 45 @GuardedBy("mSettingsByUser") 46 private final SparseArray<UsbUserSettingsManager> mSettingsByUser = new SparseArray<>(); 47 48 /** 49 * Map from the parent profile's user id to {@link UsbProfileGroupSettingsManager} for the 50 * group. 51 */ 52 @GuardedBy("mSettingsByProfileGroup") 53 private final SparseArray<UsbProfileGroupSettingsManager> mSettingsByProfileGroup 54 = new SparseArray<>(); 55 private UserManager mUserManager; 56 UsbSettingsManager(@onNull Context context)57 public UsbSettingsManager(@NonNull Context context) { 58 mContext = context; 59 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 60 } 61 62 /** 63 * Get the {@link UsbUserSettingsManager} for a user. 64 * 65 * @param userId The id of the user 66 * 67 * @return The settings for the user 68 */ getSettingsForUser(@serIdInt int userId)69 @NonNull UsbUserSettingsManager getSettingsForUser(@UserIdInt int userId) { 70 synchronized (mSettingsByUser) { 71 UsbUserSettingsManager settings = mSettingsByUser.get(userId); 72 if (settings == null) { 73 settings = new UsbUserSettingsManager(mContext, new UserHandle(userId)); 74 mSettingsByUser.put(userId, settings); 75 } 76 return settings; 77 } 78 } 79 80 /** 81 * Get the {@link UsbProfileGroupSettingsManager} for a user. 82 * 83 * @param user Any user of the profile group 84 * 85 * @return The settings for the profile group 86 */ getSettingsForProfileGroup(@onNull UserHandle user)87 @NonNull UsbProfileGroupSettingsManager getSettingsForProfileGroup(@NonNull UserHandle user) { 88 UserHandle parentUser; 89 90 UserInfo parentUserInfo = mUserManager.getProfileParent(user.getIdentifier()); 91 if (parentUserInfo != null) { 92 parentUser = parentUserInfo.getUserHandle(); 93 } else { 94 parentUser = user; 95 } 96 97 synchronized (mSettingsByProfileGroup) { 98 UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.get( 99 parentUser.getIdentifier()); 100 if (settings == null) { 101 settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this); 102 mSettingsByProfileGroup.put(parentUser.getIdentifier(), settings); 103 } 104 return settings; 105 } 106 } 107 108 /** 109 * Remove the settings for a user. 110 * 111 * @param userToRemove The user to remove 112 */ remove(@onNull UserHandle userToRemove)113 void remove(@NonNull UserHandle userToRemove) { 114 synchronized (mSettingsByUser) { 115 mSettingsByUser.remove(userToRemove.getIdentifier()); 116 } 117 118 synchronized (mSettingsByProfileGroup) { 119 if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) { 120 // The user to remove is the parent user of the group. The parent is the last user 121 // that gets removed. All state will be removed with the user 122 mSettingsByProfileGroup.remove(userToRemove.getIdentifier()); 123 } else { 124 // We cannot find the parent user of the user that is removed, hence try to remove 125 // it from all profile groups. 126 int numProfileGroups = mSettingsByProfileGroup.size(); 127 for (int i = 0; i < numProfileGroups; i++) { 128 mSettingsByProfileGroup.valueAt(i).removeAllDefaultsForUser(userToRemove); 129 } 130 } 131 } 132 } 133 134 /** 135 * Dump all settings of all users. 136 * 137 * @param pw The writer to dump to 138 */ dump(@onNull IndentingPrintWriter pw)139 void dump(@NonNull IndentingPrintWriter pw) { 140 synchronized (mSettingsByUser) { 141 int numUsers = mSettingsByUser.size(); 142 for (int i = 0; i < numUsers; i++) { 143 final int userId = mSettingsByUser.keyAt(i); 144 final UsbUserSettingsManager settings = mSettingsByUser.valueAt(i); 145 pw.println("Settings for user " + userId + ":"); 146 pw.increaseIndent(); 147 try { 148 settings.dump(pw); 149 } finally { 150 pw.decreaseIndent(); 151 } 152 } 153 } 154 155 synchronized (mSettingsByProfileGroup) { 156 int numProfileGroups = mSettingsByProfileGroup.size(); 157 for (int i = 0; i < numProfileGroups; i++) { 158 final int parentUserId = mSettingsByProfileGroup.keyAt(i); 159 final UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.valueAt(i); 160 pw.println("Settings for profile group " + parentUserId + ":"); 161 pw.increaseIndent(); 162 try { 163 settings.dump(pw); 164 } finally { 165 pw.decreaseIndent(); 166 } 167 } 168 } 169 } 170 171 /** 172 * Remove temporary access permission and broadcast that a device was removed. 173 * 174 * @param device The device that is removed 175 */ usbDeviceRemoved(@onNull UsbDevice device)176 void usbDeviceRemoved(@NonNull UsbDevice device) { 177 synchronized (mSettingsByUser) { 178 for (int i = 0; i < mSettingsByUser.size(); i++) { 179 // clear temporary permissions for the device 180 mSettingsByUser.valueAt(i).removeDevicePermissions(device); 181 } 182 } 183 184 Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); 185 intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 186 intent.putExtra(UsbManager.EXTRA_DEVICE, device); 187 188 if (DEBUG) { 189 Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent); 190 } 191 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 192 } 193 194 /** 195 * Remove temporary access permission and broadcast that a accessory was removed. 196 * 197 * @param accessory The accessory that is removed 198 */ usbAccessoryRemoved(@onNull UsbAccessory accessory)199 void usbAccessoryRemoved(@NonNull UsbAccessory accessory) { 200 synchronized (mSettingsByUser) { 201 for (int i = 0; i < mSettingsByUser.size(); i++) { 202 // clear temporary permissions for the accessory 203 mSettingsByUser.valueAt(i).removeAccessoryPermissions(accessory); 204 } 205 } 206 207 Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED); 208 intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 209 intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); 210 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 211 } 212 } 213