UsbService.java revision c1aebfa02c393471fb344c3a94ee2ae62bb78f93
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 // If attempt to change USB function while file transfer is restricted, ensure that 314 // usb data is always locked, and return. 315 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 316 if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) { 317 if (mDeviceManager != null) mDeviceManager.setUsbDataUnlocked(false); 318 return; 319 } 320 mDeviceManager.setUsbDataUnlocked(unlocked); 321 } 322 323 @Override 324 public boolean isUsbDataUnlocked() { 325 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 326 return mDeviceManager.isUsbDataUnlocked(); 327 } 328 329 @Override 330 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 331 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 332 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 333 } 334 335 @Override 336 public void denyUsbDebugging() { 337 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 338 mDeviceManager.denyUsbDebugging(); 339 } 340 341 @Override 342 public void clearUsbDebuggingKeys() { 343 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 344 mDeviceManager.clearUsbDebuggingKeys(); 345 } 346 347 @Override 348 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 349 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 350 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 351 352 pw.println("USB Manager State:"); 353 if (mDeviceManager != null) { 354 mDeviceManager.dump(fd, pw); 355 } 356 if (mHostManager != null) { 357 mHostManager.dump(fd, pw); 358 } 359 mAlsaManager.dump(fd, pw); 360 361 synchronized (mLock) { 362 for (int i = 0; i < mSettingsByUser.size(); i++) { 363 final int userId = mSettingsByUser.keyAt(i); 364 final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 365 pw.increaseIndent(); 366 pw.println("Settings for user " + userId + ":"); 367 settings.dump(fd, pw); 368 pw.decreaseIndent(); 369 } 370 } 371 pw.decreaseIndent(); 372 } 373} 374