• Home
  • 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.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