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