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