• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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