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