UsbService.java revision 460a146eb8f827e4e70f2dd93d1ba852d0feb06b
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 17package com.android.server.usb; 18 19import android.app.PendingIntent; 20import android.app.admin.DevicePolicyManager; 21import android.content.BroadcastReceiver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.pm.PackageManager; 26import android.hardware.usb.IUsbManager; 27import android.hardware.usb.UsbAccessory; 28import android.hardware.usb.UsbDevice; 29import android.hardware.usb.UsbManager; 30import android.os.Bundle; 31import android.os.ParcelFileDescriptor; 32import android.os.UserHandle; 33import android.util.Slog; 34import android.util.SparseArray; 35 36import com.android.internal.annotations.GuardedBy; 37import com.android.internal.util.IndentingPrintWriter; 38import com.android.server.SystemService; 39 40import java.io.File; 41import java.io.FileDescriptor; 42import java.io.PrintWriter; 43 44/** 45 * UsbService manages all USB related state, including both host and device support. 46 * Host related events and calls are delegated to UsbHostManager, and device related 47 * support is delegated to UsbDeviceManager. 48 */ 49public class UsbService extends IUsbManager.Stub { 50 51 public static class Lifecycle extends SystemService { 52 private UsbService mUsbService; 53 54 public Lifecycle(Context context) { 55 super(context); 56 } 57 58 @Override 59 public void onStart() { 60 mUsbService = new UsbService(getContext()); 61 publishBinderService(Context.USB_SERVICE, mUsbService); 62 } 63 64 @Override 65 public void onBootPhase(int phase) { 66 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 67 mUsbService.systemReady(); 68 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 69 mUsbService.bootCompleted(); 70 } 71 } 72 } 73 74 private static final String TAG = "UsbService"; 75 76 private final Context mContext; 77 78 private UsbDeviceManager mDeviceManager; 79 private UsbHostManager mHostManager; 80 private final UsbAlsaManager mAlsaManager; 81 82 private final Object mLock = new Object(); 83 84 /** Map from {@link UserHandle} to {@link UsbSettingsManager} */ 85 @GuardedBy("mLock") 86 private final SparseArray<UsbSettingsManager> 87 mSettingsByUser = new SparseArray<UsbSettingsManager>(); 88 89 private UsbSettingsManager getSettingsForUser(int userId) { 90 synchronized (mLock) { 91 UsbSettingsManager settings = mSettingsByUser.get(userId); 92 if (settings == null) { 93 settings = new UsbSettingsManager(mContext, new UserHandle(userId)); 94 mSettingsByUser.put(userId, settings); 95 } 96 return settings; 97 } 98 } 99 100 public UsbService(Context context) { 101 mContext = context; 102 103 mAlsaManager = new UsbAlsaManager(context); 104 105 final PackageManager pm = mContext.getPackageManager(); 106 if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 107 mHostManager = new UsbHostManager(context, mAlsaManager); 108 } 109 if (new File("/sys/class/android_usb").exists()) { 110 mDeviceManager = new UsbDeviceManager(context, mAlsaManager); 111 } 112 113 setCurrentUser(UserHandle.USER_OWNER); 114 115 final IntentFilter filter = new IntentFilter(); 116 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 117 filter.addAction(Intent.ACTION_USER_SWITCHED); 118 filter.addAction(Intent.ACTION_USER_STOPPED); 119 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 120 mContext.registerReceiver(mReceiver, filter, null, null); 121 } 122 123 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 124 @Override 125 public void onReceive(Context context, Intent intent) { 126 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 127 final String action = intent.getAction(); 128 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 129 setCurrentUser(userId); 130 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 131 synchronized (mLock) { 132 mSettingsByUser.remove(userId); 133 } 134 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 135 .equals(action)) { 136 if (mDeviceManager != null) { 137 mDeviceManager.updateUserRestrictions(); 138 } 139 } 140 } 141 }; 142 143 private void setCurrentUser(int userId) { 144 final UsbSettingsManager userSettings = getSettingsForUser(userId); 145 if (mHostManager != null) { 146 mHostManager.setCurrentSettings(userSettings); 147 } 148 if (mDeviceManager != null) { 149 mDeviceManager.setCurrentUser(userId, userSettings); 150 } 151 } 152 153 public void systemReady() { 154 mAlsaManager.systemReady(); 155 156 if (mDeviceManager != null) { 157 mDeviceManager.systemReady(); 158 } 159 if (mHostManager != null) { 160 mHostManager.systemReady(); 161 } 162 } 163 164 public void bootCompleted() { 165 if (mDeviceManager != null) { 166 mDeviceManager.bootCompleted(); 167 } 168 } 169 170 /* Returns a list of all currently attached USB devices (host mdoe) */ 171 @Override 172 public void getDeviceList(Bundle devices) { 173 if (mHostManager != null) { 174 mHostManager.getDeviceList(devices); 175 } 176 } 177 178 /* Opens the specified USB device (host mode) */ 179 @Override 180 public ParcelFileDescriptor openDevice(String deviceName) { 181 if (mHostManager != null) { 182 return mHostManager.openDevice(deviceName); 183 } else { 184 return null; 185 } 186 } 187 188 /* returns the currently attached USB accessory (device mode) */ 189 @Override 190 public UsbAccessory getCurrentAccessory() { 191 if (mDeviceManager != null) { 192 return mDeviceManager.getCurrentAccessory(); 193 } else { 194 return null; 195 } 196 } 197 198 /* opens the currently attached USB accessory (device mode) */ 199 @Override 200 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 201 if (mDeviceManager != null) { 202 return mDeviceManager.openAccessory(accessory); 203 } else { 204 return null; 205 } 206 } 207 208 @Override 209 public void setDevicePackage(UsbDevice device, String packageName, int userId) { 210 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 211 getSettingsForUser(userId).setDevicePackage(device, packageName); 212 } 213 214 @Override 215 public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 216 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 217 getSettingsForUser(userId).setAccessoryPackage(accessory, packageName); 218 } 219 220 @Override 221 public boolean hasDevicePermission(UsbDevice device) { 222 final int userId = UserHandle.getCallingUserId(); 223 return getSettingsForUser(userId).hasPermission(device); 224 } 225 226 @Override 227 public boolean hasAccessoryPermission(UsbAccessory accessory) { 228 final int userId = UserHandle.getCallingUserId(); 229 return getSettingsForUser(userId).hasPermission(accessory); 230 } 231 232 @Override 233 public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 234 final int userId = UserHandle.getCallingUserId(); 235 getSettingsForUser(userId).requestPermission(device, packageName, pi); 236 } 237 238 @Override 239 public void requestAccessoryPermission( 240 UsbAccessory accessory, String packageName, PendingIntent pi) { 241 final int userId = UserHandle.getCallingUserId(); 242 getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 243 } 244 245 @Override 246 public void grantDevicePermission(UsbDevice device, int uid) { 247 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 248 final int userId = UserHandle.getUserId(uid); 249 getSettingsForUser(userId).grantDevicePermission(device, uid); 250 } 251 252 @Override 253 public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 254 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 255 final int userId = UserHandle.getUserId(uid); 256 getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 257 } 258 259 @Override 260 public boolean hasDefaults(String packageName, int userId) { 261 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 262 return getSettingsForUser(userId).hasDefaults(packageName); 263 } 264 265 @Override 266 public void clearDefaults(String packageName, int userId) { 267 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 268 getSettingsForUser(userId).clearDefaults(packageName); 269 } 270 271 @Override 272 public boolean isFunctionEnabled(String function) { 273 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 274 return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function); 275 } 276 277 @Override 278 public void setCurrentFunction(String function) { 279 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 280 281 if (!isSupportedCurrentFunction(function)) { 282 Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: " 283 + function); 284 function = UsbManager.USB_FUNCTION_NONE; 285 } 286 287 if (mDeviceManager != null) { 288 mDeviceManager.setCurrentFunctions(function); 289 } else { 290 throw new IllegalStateException("USB device mode not supported"); 291 } 292 } 293 294 private static boolean isSupportedCurrentFunction(String function) { 295 if (function == null) return true; 296 297 switch (function) { 298 case UsbManager.USB_FUNCTION_NONE: 299 case UsbManager.USB_FUNCTION_AUDIO_SOURCE: 300 case UsbManager.USB_FUNCTION_MIDI: 301 case UsbManager.USB_FUNCTION_MTP: 302 case UsbManager.USB_FUNCTION_PTP: 303 case UsbManager.USB_FUNCTION_RNDIS: 304 return true; 305 } 306 307 return false; 308 } 309 310 @Override 311 public void setUsbDataUnlocked(boolean unlocked) { 312 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 313 mDeviceManager.setUsbDataUnlocked(unlocked); 314 } 315 316 @Override 317 public boolean isUsbDataUnlocked() { 318 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 319 return mDeviceManager.isUsbDataUnlocked(); 320 } 321 322 @Override 323 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 324 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 325 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 326 } 327 328 @Override 329 public void denyUsbDebugging() { 330 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 331 mDeviceManager.denyUsbDebugging(); 332 } 333 334 @Override 335 public void clearUsbDebuggingKeys() { 336 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 337 mDeviceManager.clearUsbDebuggingKeys(); 338 } 339 340 @Override 341 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 342 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 343 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 344 345 pw.println("USB Manager State:"); 346 if (mDeviceManager != null) { 347 mDeviceManager.dump(fd, pw); 348 } 349 if (mHostManager != null) { 350 mHostManager.dump(fd, pw); 351 } 352 mAlsaManager.dump(fd, pw); 353 354 synchronized (mLock) { 355 for (int i = 0; i < mSettingsByUser.size(); i++) { 356 final int userId = mSettingsByUser.keyAt(i); 357 final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 358 pw.increaseIndent(); 359 pw.println("Settings for user " + userId + ":"); 360 settings.dump(fd, pw); 361 pw.decreaseIndent(); 362 } 363 } 364 pw.decreaseIndent(); 365 } 366} 367