1 /* 2 * Copyright (C) 2010 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 an 14 * limitations under the License. 15 */ 16 17 package com.android.server.usb; 18 19 import android.app.PendingIntent; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.pm.PackageManager; 25 import android.hardware.usb.IUsbManager; 26 import android.hardware.usb.UsbAccessory; 27 import android.hardware.usb.UsbDevice; 28 import android.os.Bundle; 29 import android.os.ParcelFileDescriptor; 30 import android.os.UserHandle; 31 import android.util.SparseArray; 32 33 import com.android.internal.annotations.GuardedBy; 34 import com.android.internal.util.IndentingPrintWriter; 35 36 import java.io.File; 37 import java.io.FileDescriptor; 38 import java.io.PrintWriter; 39 40 /** 41 * UsbService manages all USB related state, including both host and device support. 42 * Host related events and calls are delegated to UsbHostManager, and device related 43 * support is delegated to UsbDeviceManager. 44 */ 45 public class UsbService extends IUsbManager.Stub { 46 private static final String TAG = "UsbService"; 47 48 private final Context mContext; 49 50 private UsbDeviceManager mDeviceManager; 51 private UsbHostManager mHostManager; 52 53 private final Object mLock = new Object(); 54 55 /** Map from {@link UserHandle} to {@link UsbSettingsManager} */ 56 @GuardedBy("mLock") 57 private final SparseArray<UsbSettingsManager> 58 mSettingsByUser = new SparseArray<UsbSettingsManager>(); 59 60 private UsbSettingsManager getSettingsForUser(int userId) { 61 synchronized (mLock) { 62 UsbSettingsManager settings = mSettingsByUser.get(userId); 63 if (settings == null) { 64 settings = new UsbSettingsManager(mContext, new UserHandle(userId)); 65 mSettingsByUser.put(userId, settings); 66 } 67 return settings; 68 } 69 } 70 71 public UsbService(Context context) { 72 mContext = context; 73 74 final PackageManager pm = mContext.getPackageManager(); 75 if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 76 mHostManager = new UsbHostManager(context); 77 } 78 if (new File("/sys/class/android_usb").exists()) { 79 mDeviceManager = new UsbDeviceManager(context); 80 } 81 82 setCurrentUser(UserHandle.USER_OWNER); 83 84 final IntentFilter userFilter = new IntentFilter(); 85 userFilter.addAction(Intent.ACTION_USER_SWITCHED); 86 userFilter.addAction(Intent.ACTION_USER_STOPPED); 87 mContext.registerReceiver(mUserReceiver, userFilter, null, null); 88 } 89 90 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { 91 @Override 92 public void onReceive(Context context, Intent intent) { 93 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 94 final String action = intent.getAction(); 95 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 96 setCurrentUser(userId); 97 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 98 synchronized (mLock) { 99 mSettingsByUser.remove(userId); 100 } 101 } 102 } 103 }; 104 105 private void setCurrentUser(int userId) { 106 final UsbSettingsManager userSettings = getSettingsForUser(userId); 107 if (mHostManager != null) { 108 mHostManager.setCurrentSettings(userSettings); 109 } 110 if (mDeviceManager != null) { 111 mDeviceManager.setCurrentSettings(userSettings); 112 } 113 } 114 115 public void systemReady() { 116 if (mDeviceManager != null) { 117 mDeviceManager.systemReady(); 118 } 119 if (mHostManager != null) { 120 mHostManager.systemReady(); 121 } 122 } 123 124 /* Returns a list of all currently attached USB devices (host mdoe) */ 125 @Override 126 public void getDeviceList(Bundle devices) { 127 if (mHostManager != null) { 128 mHostManager.getDeviceList(devices); 129 } 130 } 131 132 /* Opens the specified USB device (host mode) */ 133 @Override 134 public ParcelFileDescriptor openDevice(String deviceName) { 135 if (mHostManager != null) { 136 return mHostManager.openDevice(deviceName); 137 } else { 138 return null; 139 } 140 } 141 142 /* returns the currently attached USB accessory (device mode) */ 143 @Override 144 public UsbAccessory getCurrentAccessory() { 145 if (mDeviceManager != null) { 146 return mDeviceManager.getCurrentAccessory(); 147 } else { 148 return null; 149 } 150 } 151 152 /* opens the currently attached USB accessory (device mode) */ 153 @Override 154 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 155 if (mDeviceManager != null) { 156 return mDeviceManager.openAccessory(accessory); 157 } else { 158 return null; 159 } 160 } 161 162 @Override 163 public void setDevicePackage(UsbDevice device, String packageName, int userId) { 164 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 165 getSettingsForUser(userId).setDevicePackage(device, packageName); 166 } 167 168 @Override 169 public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 170 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 171 getSettingsForUser(userId).setAccessoryPackage(accessory, packageName); 172 } 173 174 @Override 175 public boolean hasDevicePermission(UsbDevice device) { 176 final int userId = UserHandle.getCallingUserId(); 177 return getSettingsForUser(userId).hasPermission(device); 178 } 179 180 @Override 181 public boolean hasAccessoryPermission(UsbAccessory accessory) { 182 final int userId = UserHandle.getCallingUserId(); 183 return getSettingsForUser(userId).hasPermission(accessory); 184 } 185 186 @Override 187 public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 188 final int userId = UserHandle.getCallingUserId(); 189 getSettingsForUser(userId).requestPermission(device, packageName, pi); 190 } 191 192 @Override 193 public void requestAccessoryPermission( 194 UsbAccessory accessory, String packageName, PendingIntent pi) { 195 final int userId = UserHandle.getCallingUserId(); 196 getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 197 } 198 199 @Override 200 public void grantDevicePermission(UsbDevice device, int uid) { 201 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 202 final int userId = UserHandle.getUserId(uid); 203 getSettingsForUser(userId).grantDevicePermission(device, uid); 204 } 205 206 @Override 207 public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 208 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 209 final int userId = UserHandle.getUserId(uid); 210 getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 211 } 212 213 @Override 214 public boolean hasDefaults(String packageName, int userId) { 215 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 216 return getSettingsForUser(userId).hasDefaults(packageName); 217 } 218 219 @Override 220 public void clearDefaults(String packageName, int userId) { 221 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 222 getSettingsForUser(userId).clearDefaults(packageName); 223 } 224 225 @Override 226 public void setCurrentFunction(String function, boolean makeDefault) { 227 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 228 if (mDeviceManager != null) { 229 mDeviceManager.setCurrentFunctions(function, makeDefault); 230 } else { 231 throw new IllegalStateException("USB device mode not supported"); 232 } 233 } 234 235 @Override 236 public void setMassStorageBackingFile(String path) { 237 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 238 if (mDeviceManager != null) { 239 mDeviceManager.setMassStorageBackingFile(path); 240 } else { 241 throw new IllegalStateException("USB device mode not supported"); 242 } 243 } 244 245 @Override 246 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 247 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 248 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 249 } 250 251 @Override 252 public void denyUsbDebugging() { 253 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 254 mDeviceManager.denyUsbDebugging(); 255 } 256 257 @Override 258 public void clearUsbDebuggingKeys() { 259 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 260 mDeviceManager.clearUsbDebuggingKeys(); 261 } 262 263 @Override 264 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 265 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 266 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 267 268 pw.println("USB Manager State:"); 269 if (mDeviceManager != null) { 270 mDeviceManager.dump(fd, pw); 271 } 272 if (mHostManager != null) { 273 mHostManager.dump(fd, pw); 274 } 275 276 synchronized (mLock) { 277 for (int i = 0; i < mSettingsByUser.size(); i++) { 278 final int userId = mSettingsByUser.keyAt(i); 279 final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 280 pw.increaseIndent(); 281 pw.println("Settings for user " + userId + ":"); 282 settings.dump(fd, pw); 283 pw.decreaseIndent(); 284 } 285 } 286 pw.decreaseIndent(); 287 } 288 } 289