Home | History | Annotate | Download | only in usb
      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 
     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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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