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