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