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