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