blob: 5a60de0f269b8ffaa88127769fc60e3ca99f4401 [file] [log] [blame]
Mike Lockwood46d0adf2011-05-26 10:27:39 -04001/*
2 * Copyright (C) 2011 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
Mike Lockwood541c9942011-06-12 19:35:45 -040019import android.app.Notification;
20import android.app.NotificationManager;
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -070021import android.app.PendingIntent;
Mike Lockwoodd462ecf2011-07-21 13:55:16 -070022import android.content.BroadcastReceiver;
Mike Lockwood541c9942011-06-12 19:35:45 -040023import android.content.ComponentName;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040024import android.content.ContentResolver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.PackageManager;
Mike Lockwood541c9942011-06-12 19:35:45 -040029import android.content.res.Resources;
30import android.database.ContentObserver;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040031import android.hardware.usb.UsbAccessory;
32import android.hardware.usb.UsbManager;
Mike Lockwood02e45692011-06-14 15:43:51 -040033import android.os.FileUtils;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040034import android.os.Handler;
Mike Lockwood02e45692011-06-14 15:43:51 -040035import android.os.Looper;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040036import android.os.Message;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040037import android.os.ParcelFileDescriptor;
RoboErikdab20722012-03-07 17:53:36 -080038import android.os.SystemClock;
Mike Lockwood541c9942011-06-12 19:35:45 -040039import android.os.SystemProperties;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040040import android.os.UEventObserver;
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -070041import android.os.UserHandle;
42import android.os.storage.StorageManager;
43import android.os.storage.StorageVolume;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040044import android.provider.Settings;
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -060045import android.util.Pair;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040046import android.util.Slog;
47
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -080048import com.android.internal.annotations.GuardedBy;
Dianne Hackborn8d044e82013-04-30 17:24:15 -070049import com.android.server.FgThread;
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -080050
Mike Lockwood46d0adf2011-05-26 10:27:39 -040051import java.io.File;
52import java.io.FileDescriptor;
53import java.io.FileNotFoundException;
Mike Lockwood02e45692011-06-14 15:43:51 -040054import java.io.IOException;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040055import java.io.PrintWriter;
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -070056import java.util.HashMap;
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -060057import java.util.LinkedList;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040058import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070059import java.util.Locale;
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -060060import java.util.Map;
Mike Lockwood9d5a4be2012-04-06 09:41:32 -070061import java.util.Scanner;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040062
63/**
64 * UsbDeviceManager manages USB state in device mode.
65 */
66public class UsbDeviceManager {
Mike Lockwood02e45692011-06-14 15:43:51 -040067
Mike Lockwood46d0adf2011-05-26 10:27:39 -040068 private static final String TAG = UsbDeviceManager.class.getSimpleName();
Mike Lockwoodfdc0c292011-07-01 11:17:43 -040069 private static final boolean DEBUG = false;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040070
Mike Lockwood02e45692011-06-14 15:43:51 -040071 private static final String USB_STATE_MATCH =
72 "DEVPATH=/devices/virtual/android_usb/android0";
73 private static final String ACCESSORY_START_MATCH =
74 "DEVPATH=/devices/virtual/misc/usb_accessory";
75 private static final String FUNCTIONS_PATH =
76 "/sys/class/android_usb/android0/functions";
77 private static final String STATE_PATH =
78 "/sys/class/android_usb/android0/state";
79 private static final String MASS_STORAGE_FILE_PATH =
Mike Lockwood629b1492011-07-06 12:47:21 -040080 "/sys/class/android_usb/android0/f_mass_storage/lun/file";
81 private static final String RNDIS_ETH_ADDR_PATH =
82 "/sys/class/android_usb/android0/f_rndis/ethaddr";
Mike Lockwood9d5a4be2012-04-06 09:41:32 -070083 private static final String AUDIO_SOURCE_PCM_PATH =
84 "/sys/class/android_usb/android0/f_audio_source/pcm";
Mike Lockwood46d0adf2011-05-26 10:27:39 -040085
86 private static final int MSG_UPDATE_STATE = 0;
Mike Lockwood02e45692011-06-14 15:43:51 -040087 private static final int MSG_ENABLE_ADB = 1;
Mike Lockwood166b05e2012-04-24 10:45:18 -070088 private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
Mike Lockwoodf59717d2011-06-22 15:19:33 -040089 private static final int MSG_SYSTEM_READY = 3;
Mike Lockwoodd462ecf2011-07-21 13:55:16 -070090 private static final int MSG_BOOT_COMPLETED = 4;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -070091 private static final int MSG_USER_SWITCHED = 5;
Mike Lockwood46d0adf2011-05-26 10:27:39 -040092
Mike Lockwood166b05e2012-04-24 10:45:18 -070093 private static final int AUDIO_MODE_NONE = 0;
94 private static final int AUDIO_MODE_SOURCE = 1;
95
Mike Lockwood46d0adf2011-05-26 10:27:39 -040096 // Delay for debouncing USB disconnects.
97 // We often get rapid connect/disconnect events when enabling USB functions,
98 // which need debouncing.
99 private static final int UPDATE_DELAY = 1000;
100
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600101 private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
102
Mike Lockwood02e45692011-06-14 15:43:51 -0400103 private UsbHandler mHandler;
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700104 private boolean mBootCompleted;
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400105
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700106 private final Object mLock = new Object();
107
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400108 private final Context mContext;
Mike Lockwood02e45692011-06-14 15:43:51 -0400109 private final ContentResolver mContentResolver;
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800110 @GuardedBy("mLock")
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700111 private UsbSettingsManager mCurrentSettings;
Mike Lockwood541c9942011-06-12 19:35:45 -0400112 private NotificationManager mNotificationManager;
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400113 private final boolean mHasUsbAccessory;
Mike Lockwood5787a2d2011-06-17 12:21:39 -0400114 private boolean mUseUsbNotification;
Mike Lockwood541c9942011-06-12 19:35:45 -0400115 private boolean mAdbEnabled;
Mike Lockwood9d5a4be2012-04-06 09:41:32 -0700116 private boolean mAudioSourceEnabled;
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600117 private Map<String, List<Pair<String, String>>> mOemModeMap;
Mike Lockwood166b05e2012-04-24 10:45:18 -0700118 private String[] mAccessoryStrings;
Benoit Goby4e68bd42012-04-25 18:06:00 -0700119 private UsbDebuggingManager mDebuggingManager;
Mike Lockwood541c9942011-06-12 19:35:45 -0400120
121 private class AdbSettingsObserver extends ContentObserver {
122 public AdbSettingsObserver() {
123 super(null);
124 }
125 @Override
126 public void onChange(boolean selfChange) {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700127 boolean enable = (Settings.Global.getInt(mContentResolver,
128 Settings.Global.ADB_ENABLED, 0) > 0);
Mike Lockwood02e45692011-06-14 15:43:51 -0400129 mHandler.sendMessage(MSG_ENABLE_ADB, enable);
Mike Lockwood541c9942011-06-12 19:35:45 -0400130 }
131 }
132
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400133 /*
134 * Listens for uevent messages from the kernel to monitor the USB state
135 */
136 private final UEventObserver mUEventObserver = new UEventObserver() {
137 @Override
138 public void onUEvent(UEventObserver.UEvent event) {
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400139 if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400140
Mike Lockwood02e45692011-06-14 15:43:51 -0400141 String state = event.get("USB_STATE");
142 String accessory = event.get("ACCESSORY");
143 if (state != null) {
144 mHandler.updateState(state);
145 } else if ("START".equals(accessory)) {
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400146 if (DEBUG) Slog.d(TAG, "got accessory start");
Mike Lockwood166b05e2012-04-24 10:45:18 -0700147 startAccessoryMode();
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400148 }
149 }
150 };
151
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700152 public UsbDeviceManager(Context context) {
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400153 mContext = context;
Mike Lockwood541c9942011-06-12 19:35:45 -0400154 mContentResolver = context.getContentResolver();
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400155 PackageManager pm = mContext.getPackageManager();
156 mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
Mike Lockwood629b1492011-07-06 12:47:21 -0400157 initRndisAddress();
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400158
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600159 readOemUsbOverrideConfig();
160
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700161 mHandler = new UsbHandler(FgThread.get().getLooper());
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700162
163 if (nativeIsStartRequested()) {
164 if (DEBUG) Slog.d(TAG, "accessory attached at boot");
Mike Lockwood166b05e2012-04-24 10:45:18 -0700165 startAccessoryMode();
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700166 }
Benoit Goby4e68bd42012-04-25 18:06:00 -0700167
Benoit Goby78a96872013-01-25 16:58:13 -0800168 boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
169 boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
170 if (secureAdbEnabled && !dataEncrypted) {
Benoit Goby4e68bd42012-04-25 18:06:00 -0700171 mDebuggingManager = new UsbDebuggingManager(context);
172 }
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400173 }
174
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700175 public void setCurrentSettings(UsbSettingsManager settings) {
176 synchronized (mLock) {
177 mCurrentSettings = settings;
178 }
179 }
180
181 private UsbSettingsManager getCurrentSettings() {
182 synchronized (mLock) {
183 return mCurrentSettings;
184 }
185 }
186
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400187 public void systemReady() {
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700188 if (DEBUG) Slog.d(TAG, "systemReady");
Mike Lockwood541c9942011-06-12 19:35:45 -0400189
Mike Lockwood02e45692011-06-14 15:43:51 -0400190 mNotificationManager = (NotificationManager)
191 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
192
Mike Lockwood5787a2d2011-06-17 12:21:39 -0400193 // We do not show the USB notification if the primary volume supports mass storage.
194 // The legacy mass storage UI will be used instead.
195 boolean massStorageSupported = false;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700196 final StorageManager storageManager = StorageManager.from(mContext);
197 final StorageVolume primary = storageManager.getPrimaryVolume();
198 massStorageSupported = primary != null && primary.allowMassStorage();
Mike Lockwood5787a2d2011-06-17 12:21:39 -0400199 mUseUsbNotification = !massStorageSupported;
200
Mike Lockwood02e45692011-06-14 15:43:51 -0400201 // make sure the ADB_ENABLED setting value matches the current state
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700202 Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
Mike Lockwood02e45692011-06-14 15:43:51 -0400203
204 mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
205 }
206
Mike Lockwood166b05e2012-04-24 10:45:18 -0700207 private void startAccessoryMode() {
208 mAccessoryStrings = nativeGetAccessoryStrings();
209 boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
210 // don't start accessory mode if our mandatory strings have not been set
211 boolean enableAccessory = (mAccessoryStrings != null &&
212 mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
213 mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
214 String functions = null;
215
216 if (enableAccessory && enableAudio) {
217 functions = UsbManager.USB_FUNCTION_ACCESSORY + ","
218 + UsbManager.USB_FUNCTION_AUDIO_SOURCE;
219 } else if (enableAccessory) {
220 functions = UsbManager.USB_FUNCTION_ACCESSORY;
221 } else if (enableAudio) {
222 functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
223 }
224
225 if (functions != null) {
226 setCurrentFunctions(functions, false);
227 }
228 }
229
Mike Lockwood629b1492011-07-06 12:47:21 -0400230 private static void initRndisAddress() {
231 // configure RNDIS ethernet address based on our serial number using the same algorithm
232 // we had been previously using in kernel board files
233 final int ETH_ALEN = 6;
234 int address[] = new int[ETH_ALEN];
235 // first byte is 0x02 to signify a locally administered address
236 address[0] = 0x02;
237
238 String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF");
239 int serialLength = serial.length();
240 // XOR the USB serial across the remaining 5 bytes
241 for (int i = 0; i < serialLength; i++) {
242 address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i);
243 }
Jeff Sharkeyfea17de2013-06-11 14:13:09 -0700244 String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
Mike Lockwood629b1492011-07-06 12:47:21 -0400245 address[0], address[1], address[2], address[3], address[4], address[5]);
246 try {
247 FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString);
248 } catch (IOException e) {
249 Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH);
250 }
251 }
252
Mike Lockwood02e45692011-06-14 15:43:51 -0400253 private static String addFunction(String functions, String function) {
RoboErikdab20722012-03-07 17:53:36 -0800254 if ("none".equals(functions)) {
255 return function;
256 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400257 if (!containsFunction(functions, function)) {
258 if (functions.length() > 0) {
259 functions += ",";
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400260 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400261 functions += function;
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400262 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400263 return functions;
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400264 }
265
Mike Lockwood02e45692011-06-14 15:43:51 -0400266 private static String removeFunction(String functions, String function) {
267 String[] split = functions.split(",");
268 for (int i = 0; i < split.length; i++) {
269 if (function.equals(split[i])) {
270 split[i] = null;
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400271 }
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400272 }
RoboErikdab20722012-03-07 17:53:36 -0800273 if (split.length == 1 && split[0] == null) {
274 return "none";
275 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400276 StringBuilder builder = new StringBuilder();
277 for (int i = 0; i < split.length; i++) {
278 String s = split[i];
279 if (s != null) {
280 if (builder.length() > 0) {
281 builder.append(",");
282 }
283 builder.append(s);
284 }
285 }
286 return builder.toString();
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400287 }
288
Mike Lockwood02e45692011-06-14 15:43:51 -0400289 private static boolean containsFunction(String functions, String function) {
290 int index = functions.indexOf(function);
291 if (index < 0) return false;
292 if (index > 0 && functions.charAt(index - 1) != ',') return false;
293 int charAfter = index + function.length();
294 if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
295 return true;
296 }
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400297
Mike Lockwood02e45692011-06-14 15:43:51 -0400298 private final class UsbHandler extends Handler {
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400299
Mike Lockwood02e45692011-06-14 15:43:51 -0400300 // current USB state
301 private boolean mConnected;
302 private boolean mConfigured;
303 private String mCurrentFunctions;
304 private String mDefaultFunctions;
305 private UsbAccessory mCurrentAccessory;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400306 private int mUsbNotificationId;
307 private boolean mAdbNotificationShown;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -0700308 private int mCurrentUser = UserHandle.USER_NULL;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400309
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700310 private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
Jeff Sharkey27bd34d2012-09-16 12:49:00 -0700311 @Override
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700312 public void onReceive(Context context, Intent intent) {
313 if (DEBUG) Slog.d(TAG, "boot completed");
314 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
315 }
316 };
317
Jeff Sharkey27bd34d2012-09-16 12:49:00 -0700318 private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
319 @Override
320 public void onReceive(Context context, Intent intent) {
321 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
322 mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
323 }
324 };
325
Mike Lockwood3fd13eb2011-07-13 09:23:45 -0400326 public UsbHandler(Looper looper) {
327 super(looper);
Mike Lockwood02e45692011-06-14 15:43:51 -0400328 try {
Mike Lockwoodc264afeb52011-07-10 11:48:18 -0400329 // persist.sys.usb.config should never be unset. But if it is, set it to "adb"
330 // so we have a chance of debugging what happened.
331 mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb");
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600332
333 // Check if USB mode needs to be overridden depending on OEM specific bootmode.
334 mDefaultFunctions = processOemUsbOverride(mDefaultFunctions);
335
Mike Lockwoodde296f62011-07-01 14:05:25 -0400336 // sanity check the sys.usb.config system property
337 // this may be necessary if we crashed while switching USB configurations
338 String config = SystemProperties.get("sys.usb.config", "none");
Mike Lockwoodc264afeb52011-07-10 11:48:18 -0400339 if (!config.equals(mDefaultFunctions)) {
340 Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions);
341 SystemProperties.set("sys.usb.config", mDefaultFunctions);
Mike Lockwoodde296f62011-07-01 14:05:25 -0400342 }
343
Mike Lockwoodc264afeb52011-07-10 11:48:18 -0400344 mCurrentFunctions = mDefaultFunctions;
Mike Lockwood02e45692011-06-14 15:43:51 -0400345 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
346 updateState(state);
Mike Lockwood02e45692011-06-14 15:43:51 -0400347 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400348
Mike Lockwood02e45692011-06-14 15:43:51 -0400349 // Upgrade step for previous versions that used persist.service.adb.enable
350 String value = SystemProperties.get("persist.service.adb.enable", "");
351 if (value.length() > 0) {
352 char enable = value.charAt(0);
353 if (enable == '1') {
354 setAdbEnabled(true);
355 } else if (enable == '0') {
356 setAdbEnabled(false);
357 }
358 SystemProperties.set("persist.service.adb.enable", "");
359 }
360
361 // register observer to listen for settings changes
362 mContentResolver.registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700363 Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
Mike Lockwood02e45692011-06-14 15:43:51 -0400364 false, new AdbSettingsObserver());
365
366 // Watch for USB configuration changes
367 mUEventObserver.startObserving(USB_STATE_MATCH);
368 mUEventObserver.startObserving(ACCESSORY_START_MATCH);
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700369
Jeff Sharkey27bd34d2012-09-16 12:49:00 -0700370 mContext.registerReceiver(
371 mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
372 mContext.registerReceiver(
373 mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
Mike Lockwood02e45692011-06-14 15:43:51 -0400374 } catch (Exception e) {
375 Slog.e(TAG, "Error initializing UsbHandler", e);
376 }
377 }
378
379 public void sendMessage(int what, boolean arg) {
380 removeMessages(what);
381 Message m = Message.obtain(this, what);
382 m.arg1 = (arg ? 1 : 0);
383 sendMessage(m);
384 }
385
386 public void sendMessage(int what, Object arg) {
387 removeMessages(what);
388 Message m = Message.obtain(this, what);
389 m.obj = arg;
390 sendMessage(m);
391 }
392
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400393 public void sendMessage(int what, Object arg0, boolean arg1) {
394 removeMessages(what);
395 Message m = Message.obtain(this, what);
396 m.obj = arg0;
397 m.arg1 = (arg1 ? 1 : 0);
398 sendMessage(m);
399 }
400
Mike Lockwood02e45692011-06-14 15:43:51 -0400401 public void updateState(String state) {
402 int connected, configured;
403
404 if ("DISCONNECTED".equals(state)) {
405 connected = 0;
406 configured = 0;
407 } else if ("CONNECTED".equals(state)) {
408 connected = 1;
409 configured = 0;
410 } else if ("CONFIGURED".equals(state)) {
411 connected = 1;
412 configured = 1;
413 } else {
414 Slog.e(TAG, "unknown state " + state);
415 return;
416 }
417 removeMessages(MSG_UPDATE_STATE);
418 Message msg = Message.obtain(this, MSG_UPDATE_STATE);
419 msg.arg1 = connected;
420 msg.arg2 = configured;
421 // debounce disconnects to avoid problems bringing up USB tethering
422 sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
423 }
424
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400425 private boolean waitForState(String state) {
Mike Lockwood02e45692011-06-14 15:43:51 -0400426 // wait for the transition to complete.
427 // give up after 1 second.
428 for (int i = 0; i < 20; i++) {
Mike Lockwood68736cb2011-07-29 11:32:28 -0400429 // State transition is done when sys.usb.state is set to the new configuration
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400430 if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
RoboErikdab20722012-03-07 17:53:36 -0800431 SystemClock.sleep(50);
Mike Lockwood02e45692011-06-14 15:43:51 -0400432 }
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400433 Slog.e(TAG, "waitForState(" + state + ") FAILED");
Mike Lockwood02e45692011-06-14 15:43:51 -0400434 return false;
435 }
436
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400437 private boolean setUsbConfig(String config) {
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400438 if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400439 // set the new configuration
440 SystemProperties.set("sys.usb.config", config);
441 return waitForState(config);
442 }
443
Mike Lockwood02e45692011-06-14 15:43:51 -0400444 private void setAdbEnabled(boolean enable) {
Mike Lockwoodde296f62011-07-01 14:05:25 -0400445 if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
Mike Lockwood02e45692011-06-14 15:43:51 -0400446 if (enable != mAdbEnabled) {
447 mAdbEnabled = enable;
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400448 // Due to the persist.sys.usb.config property trigger, changing adb state requires
449 // switching to default function
Mike Lockwood1984e792011-08-03 17:10:43 -0400450 setEnabledFunctions(mDefaultFunctions, true);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400451 updateAdbNotification();
Mike Lockwood02e45692011-06-14 15:43:51 -0400452 }
Benoit Goby4e68bd42012-04-25 18:06:00 -0700453 if (mDebuggingManager != null) {
454 mDebuggingManager.setAdbEnabled(mAdbEnabled);
455 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400456 }
457
Mike Lockwood68736cb2011-07-29 11:32:28 -0400458 private void setEnabledFunctions(String functions, boolean makeDefault) {
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600459
460 // Do not update persystent.sys.usb.config if the device is booted up
461 // with OEM specific mode.
462 if (functions != null && makeDefault && !needsOemUsbOverride()) {
463
Mike Lockwood8b4d36e2011-08-02 18:16:26 -0400464 if (mAdbEnabled) {
465 functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
466 } else {
467 functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
468 }
Mike Lockwood68736cb2011-07-29 11:32:28 -0400469 if (!mDefaultFunctions.equals(functions)) {
470 if (!setUsbConfig("none")) {
471 Slog.e(TAG, "Failed to disable USB");
472 // revert to previous configuration if we fail
473 setUsbConfig(mCurrentFunctions);
474 return;
475 }
476 // setting this property will also change the current USB state
477 // via a property trigger
478 SystemProperties.set("persist.sys.usb.config", functions);
479 if (waitForState(functions)) {
480 mCurrentFunctions = functions;
481 mDefaultFunctions = functions;
482 } else {
483 Slog.e(TAG, "Failed to switch persistent USB config to " + functions);
484 // revert to previous configuration if we fail
485 SystemProperties.set("persist.sys.usb.config", mDefaultFunctions);
486 }
487 }
488 } else {
489 if (functions == null) {
490 functions = mDefaultFunctions;
491 }
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600492
493 // Override with bootmode specific usb mode if needed
494 functions = processOemUsbOverride(functions);
495
Mike Lockwood8b4d36e2011-08-02 18:16:26 -0400496 if (mAdbEnabled) {
497 functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
498 } else {
499 functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
500 }
Mike Lockwood68736cb2011-07-29 11:32:28 -0400501 if (!mCurrentFunctions.equals(functions)) {
502 if (!setUsbConfig("none")) {
503 Slog.e(TAG, "Failed to disable USB");
504 // revert to previous configuration if we fail
505 setUsbConfig(mCurrentFunctions);
506 return;
507 }
508 if (setUsbConfig(functions)) {
509 mCurrentFunctions = functions;
510 } else {
511 Slog.e(TAG, "Failed to switch USB config to " + functions);
512 // revert to previous configuration if we fail
513 setUsbConfig(mCurrentFunctions);
514 }
515 }
516 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400517 }
518
519 private void updateCurrentAccessory() {
520 if (!mHasUsbAccessory) return;
521
522 if (mConfigured) {
Mike Lockwood166b05e2012-04-24 10:45:18 -0700523 if (mAccessoryStrings != null) {
524 mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400525 Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
Mike Lockwood02e45692011-06-14 15:43:51 -0400526 // defer accessoryAttached if system is not ready
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700527 if (mBootCompleted) {
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700528 getCurrentSettings().accessoryAttached(mCurrentAccessory);
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700529 } // else handle in mBootCompletedReceiver
Mike Lockwood02e45692011-06-14 15:43:51 -0400530 } else {
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400531 Slog.e(TAG, "nativeGetAccessoryStrings failed");
Mike Lockwood02e45692011-06-14 15:43:51 -0400532 }
533 } else if (!mConnected) {
534 // make sure accessory mode is off
535 // and restore default functions
Mike Lockwoodfdc0c292011-07-01 11:17:43 -0400536 Slog.d(TAG, "exited USB accessory mode");
Mike Lockwood68736cb2011-07-29 11:32:28 -0400537 setEnabledFunctions(mDefaultFunctions, false);
Mike Lockwood02e45692011-06-14 15:43:51 -0400538
539 if (mCurrentAccessory != null) {
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700540 if (mBootCompleted) {
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700541 getCurrentSettings().accessoryDetached(mCurrentAccessory);
Mike Lockwood02e45692011-06-14 15:43:51 -0400542 }
543 mCurrentAccessory = null;
Mike Lockwood166b05e2012-04-24 10:45:18 -0700544 mAccessoryStrings = null;
Mike Lockwood02e45692011-06-14 15:43:51 -0400545 }
546 }
547 }
548
549 private void updateUsbState() {
550 // send a sticky broadcast containing current USB state
551 Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
552 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
553 intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
554 intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
555
556 if (mCurrentFunctions != null) {
557 String[] functions = mCurrentFunctions.split(",");
558 for (int i = 0; i < functions.length; i++) {
559 intent.putExtra(functions[i], true);
560 }
561 }
562
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700563 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood02e45692011-06-14 15:43:51 -0400564 }
565
Mike Lockwoodbf910462012-05-09 16:19:20 -0700566 private void updateAudioSourceFunction() {
567 boolean enabled = containsFunction(mCurrentFunctions,
568 UsbManager.USB_FUNCTION_AUDIO_SOURCE);
569 if (enabled != mAudioSourceEnabled) {
570 // send a sticky broadcast containing current USB state
571 Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
572 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
573 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
574 intent.putExtra("state", (enabled ? 1 : 0));
575 if (enabled) {
576 try {
577 Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
578 int card = scanner.nextInt();
579 int device = scanner.nextInt();
580 intent.putExtra("card", card);
581 intent.putExtra("device", device);
582 } catch (FileNotFoundException e) {
583 Slog.e(TAG, "could not open audio source PCM file", e);
584 }
Mike Lockwood9d5a4be2012-04-06 09:41:32 -0700585 }
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700586 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwoodbf910462012-05-09 16:19:20 -0700587 mAudioSourceEnabled = enabled;
Mike Lockwood9d5a4be2012-04-06 09:41:32 -0700588 }
Mike Lockwood9d5a4be2012-04-06 09:41:32 -0700589 }
590
Mike Lockwood02e45692011-06-14 15:43:51 -0400591 @Override
592 public void handleMessage(Message msg) {
Mike Lockwood02e45692011-06-14 15:43:51 -0400593 switch (msg.what) {
594 case MSG_UPDATE_STATE:
595 mConnected = (msg.arg1 == 1);
596 mConfigured = (msg.arg2 == 1);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400597 updateUsbNotification();
598 updateAdbNotification();
Mike Lockwood02e45692011-06-14 15:43:51 -0400599 if (containsFunction(mCurrentFunctions,
600 UsbManager.USB_FUNCTION_ACCESSORY)) {
601 updateCurrentAccessory();
602 }
603
604 if (!mConnected) {
605 // restore defaults when USB is disconnected
Mike Lockwood68736cb2011-07-29 11:32:28 -0400606 setEnabledFunctions(mDefaultFunctions, false);
Mike Lockwood02e45692011-06-14 15:43:51 -0400607 }
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700608 if (mBootCompleted) {
Mike Lockwood02e45692011-06-14 15:43:51 -0400609 updateUsbState();
Mike Lockwoodbf910462012-05-09 16:19:20 -0700610 updateAudioSourceFunction();
Mike Lockwood02e45692011-06-14 15:43:51 -0400611 }
612 break;
613 case MSG_ENABLE_ADB:
614 setAdbEnabled(msg.arg1 == 1);
615 break;
Mike Lockwood166b05e2012-04-24 10:45:18 -0700616 case MSG_SET_CURRENT_FUNCTIONS:
617 String functions = (String)msg.obj;
Mike Lockwoodf59717d2011-06-22 15:19:33 -0400618 boolean makeDefault = (msg.arg1 == 1);
Mike Lockwood166b05e2012-04-24 10:45:18 -0700619 setEnabledFunctions(functions, makeDefault);
Mike Lockwood02e45692011-06-14 15:43:51 -0400620 break;
621 case MSG_SYSTEM_READY:
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400622 updateUsbNotification();
623 updateAdbNotification();
Mike Lockwood02e45692011-06-14 15:43:51 -0400624 updateUsbState();
Mike Lockwoodbf910462012-05-09 16:19:20 -0700625 updateAudioSourceFunction();
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700626 break;
627 case MSG_BOOT_COMPLETED:
628 mBootCompleted = true;
629 if (mCurrentAccessory != null) {
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700630 getCurrentSettings().accessoryAttached(mCurrentAccessory);
Mike Lockwood02e45692011-06-14 15:43:51 -0400631 }
Benoit Goby4e68bd42012-04-25 18:06:00 -0700632 if (mDebuggingManager != null) {
633 mDebuggingManager.setAdbEnabled(mAdbEnabled);
634 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400635 break;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -0700636 case MSG_USER_SWITCHED: {
637 final boolean mtpActive =
638 containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
639 || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
640 if (mtpActive && mCurrentUser != UserHandle.USER_NULL) {
641 Slog.v(TAG, "Current user switched; resetting USB host stack for MTP");
642 setUsbConfig("none");
643 setUsbConfig(mCurrentFunctions);
644 }
645 mCurrentUser = msg.arg1;
646 break;
647 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400648 }
649 }
650
651 public UsbAccessory getCurrentAccessory() {
652 return mCurrentAccessory;
653 }
654
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400655 private void updateUsbNotification() {
656 if (mNotificationManager == null || !mUseUsbNotification) return;
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700657 int id = 0;
Mike Lockwooda5010432011-07-27 09:50:06 -0400658 Resources r = mContext.getResources();
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400659 if (mConnected) {
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400660 if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700661 id = com.android.internal.R.string.usb_mtp_notification_title;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400662 } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700663 id = com.android.internal.R.string.usb_ptp_notification_title;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400664 } else if (containsFunction(mCurrentFunctions,
665 UsbManager.USB_FUNCTION_MASS_STORAGE)) {
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700666 id = com.android.internal.R.string.usb_cd_installer_notification_title;
Mike Lockwood6e680de2011-07-21 15:36:09 -0700667 } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700668 id = com.android.internal.R.string.usb_accessory_notification_title;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400669 } else {
Mike Lockwooda5010432011-07-27 09:50:06 -0400670 // There is a different notification for USB tethering so we don't need one here
Dianne Hackborn7ff30112012-11-08 11:12:09 -0800671 //if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
672 // Slog.e(TAG, "No known USB function in updateUsbNotification");
673 //}
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400674 }
Mike Lockwooda5010432011-07-27 09:50:06 -0400675 }
676 if (id != mUsbNotificationId) {
677 // clear notification if title needs changing
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700678 if (mUsbNotificationId != 0) {
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700679 mNotificationManager.cancelAsUser(null, mUsbNotificationId,
680 UserHandle.ALL);
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700681 mUsbNotificationId = 0;
Mike Lockwooda5010432011-07-27 09:50:06 -0400682 }
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700683 if (id != 0) {
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400684 CharSequence message = r.getText(
685 com.android.internal.R.string.usb_notification_message);
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700686 CharSequence title = r.getText(id);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400687
688 Notification notification = new Notification();
689 notification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
690 notification.when = 0;
691 notification.flags = Notification.FLAG_ONGOING_EVENT;
692 notification.tickerText = title;
693 notification.defaults = 0; // please be quiet
694 notification.sound = null;
695 notification.vibrate = null;
Daniel Sandler49a2ad12012-03-28 15:46:39 -0400696 notification.priority = Notification.PRIORITY_MIN;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400697
Christopher Tate765f97d2011-08-23 20:14:33 -0700698 Intent intent = Intent.makeRestartActivityTask(
699 new ComponentName("com.android.settings",
700 "com.android.settings.UsbSettings"));
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700701 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
702 intent, 0, null, UserHandle.CURRENT);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400703 notification.setLatestEventInfo(mContext, title, message, pi);
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700704 mNotificationManager.notifyAsUser(null, id, notification,
705 UserHandle.ALL);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400706 mUsbNotificationId = id;
707 }
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400708 }
709 }
710
711 private void updateAdbNotification() {
712 if (mNotificationManager == null) return;
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700713 final int id = com.android.internal.R.string.adb_active_notification_title;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400714 if (mAdbEnabled && mConnected) {
715 if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
716
717 if (!mAdbNotificationShown) {
718 Resources r = mContext.getResources();
Mike Lockwoodfadd2b82011-08-16 13:34:34 -0700719 CharSequence title = r.getText(id);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400720 CharSequence message = r.getText(
721 com.android.internal.R.string.adb_active_notification_message);
722
723 Notification notification = new Notification();
724 notification.icon = com.android.internal.R.drawable.stat_sys_adb;
725 notification.when = 0;
726 notification.flags = Notification.FLAG_ONGOING_EVENT;
727 notification.tickerText = title;
728 notification.defaults = 0; // please be quiet
729 notification.sound = null;
730 notification.vibrate = null;
Daniel Sandlera25079e2012-05-10 10:48:56 -0400731 notification.priority = Notification.PRIORITY_LOW;
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400732
Christopher Tate765f97d2011-08-23 20:14:33 -0700733 Intent intent = Intent.makeRestartActivityTask(
734 new ComponentName("com.android.settings",
735 "com.android.settings.DevelopmentSettings"));
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700736 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
737 intent, 0, null, UserHandle.CURRENT);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400738 notification.setLatestEventInfo(mContext, title, message, pi);
739 mAdbNotificationShown = true;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700740 mNotificationManager.notifyAsUser(null, id, notification,
741 UserHandle.ALL);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400742 }
743 } else if (mAdbNotificationShown) {
744 mAdbNotificationShown = false;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700745 mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
Mike Lockwoodd8404d22011-06-23 16:04:29 -0400746 }
747 }
748
Mike Lockwood02e45692011-06-14 15:43:51 -0400749 public void dump(FileDescriptor fd, PrintWriter pw) {
750 pw.println(" USB Device State:");
751 pw.println(" Current Functions: " + mCurrentFunctions);
752 pw.println(" Default Functions: " + mDefaultFunctions);
753 pw.println(" mConnected: " + mConnected);
754 pw.println(" mConfigured: " + mConfigured);
755 pw.println(" mCurrentAccessory: " + mCurrentAccessory);
Mike Lockwood6ea146c2011-07-10 12:01:16 -0400756 try {
757 pw.println(" Kernel state: "
758 + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
759 pw.println(" Kernel function list: "
760 + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
761 pw.println(" Mass storage backing file: "
762 + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim());
763 } catch (IOException e) {
764 pw.println("IOException: " + e);
765 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400766 }
767 }
768
769 /* returns the currently attached USB accessory */
770 public UsbAccessory getCurrentAccessory() {
771 return mHandler.getCurrentAccessory();
772 }
773
774 /* opens the currently attached USB accessory */
Mike Lockwoodabc4ac62011-07-11 10:34:35 -0400775 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
776 UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
777 if (currentAccessory == null) {
778 throw new IllegalArgumentException("no accessory attached");
Mike Lockwood02e45692011-06-14 15:43:51 -0400779 }
Mike Lockwoodabc4ac62011-07-11 10:34:35 -0400780 if (!currentAccessory.equals(accessory)) {
781 String error = accessory.toString()
782 + " does not match current accessory "
783 + currentAccessory;
784 throw new IllegalArgumentException(error);
785 }
Jeff Sharkeyfc3f24b2012-10-01 21:45:52 -0700786 getCurrentSettings().checkPermission(accessory);
Mike Lockwoodabc4ac62011-07-11 10:34:35 -0400787 return nativeOpenAccessory();
788 }
Mike Lockwood02e45692011-06-14 15:43:51 -0400789
Mike Lockwood166b05e2012-04-24 10:45:18 -0700790 public void setCurrentFunctions(String functions, boolean makeDefault) {
791 if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ") default: " + makeDefault);
792 mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault);
Mike Lockwood02e45692011-06-14 15:43:51 -0400793 }
794
795 public void setMassStorageBackingFile(String path) {
796 if (path == null) path = "";
797 try {
798 FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path);
799 } catch (IOException e) {
800 Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH);
801 }
802 }
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400803
Kazuhiro Ondoafd8f182012-02-06 17:35:50 -0600804 private void readOemUsbOverrideConfig() {
805 String[] configList = mContext.getResources().getStringArray(
806 com.android.internal.R.array.config_oemUsbModeOverride);
807
808 if (configList != null) {
809 for (String config: configList) {
810 String[] items = config.split(":");
811 if (items.length == 3) {
812 if (mOemModeMap == null) {
813 mOemModeMap = new HashMap<String, List<Pair<String, String>>>();
814 }
815 List overrideList = mOemModeMap.get(items[0]);
816 if (overrideList == null) {
817 overrideList = new LinkedList<Pair<String, String>>();
818 mOemModeMap.put(items[0], overrideList);
819 }
820 overrideList.add(new Pair<String, String>(items[1], items[2]));
821 }
822 }
823 }
824 }
825
826 private boolean needsOemUsbOverride() {
827 if (mOemModeMap == null) return false;
828
829 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
830 return (mOemModeMap.get(bootMode) != null) ? true : false;
831 }
832
833 private String processOemUsbOverride(String usbFunctions) {
834 if ((usbFunctions == null) || (mOemModeMap == null)) return usbFunctions;
835
836 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
837
838 List<Pair<String, String>> overrides = mOemModeMap.get(bootMode);
839 if (overrides != null) {
840 for (Pair<String, String> pair: overrides) {
841 if (pair.first.equals(usbFunctions)) {
842 Slog.d(TAG, "OEM USB override: " + pair.first + " ==> " + pair.second);
843 return pair.second;
844 }
845 }
846 }
847 // return passed in functions as is.
848 return usbFunctions;
849 }
850
Benoit Goby4e68bd42012-04-25 18:06:00 -0700851 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
852 if (mDebuggingManager != null) {
853 mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
854 }
855 }
856
857 public void denyUsbDebugging() {
858 if (mDebuggingManager != null) {
859 mDebuggingManager.denyUsbDebugging();
860 }
861 }
862
Benoit Gobycd7a17c2012-12-21 16:44:50 -0800863 public void clearUsbDebuggingKeys() {
864 if (mDebuggingManager != null) {
865 mDebuggingManager.clearUsbDebuggingKeys();
866 } else {
867 throw new RuntimeException("Cannot clear Usb Debugging keys, "
868 + "UsbDebuggingManager not enabled");
869 }
870 }
871
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400872 public void dump(FileDescriptor fd, PrintWriter pw) {
Mike Lockwood02e45692011-06-14 15:43:51 -0400873 if (mHandler != null) {
874 mHandler.dump(fd, pw);
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400875 }
Benoit Goby4e68bd42012-04-25 18:06:00 -0700876 if (mDebuggingManager != null) {
877 mDebuggingManager.dump(fd, pw);
878 }
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400879 }
880
881 private native String[] nativeGetAccessoryStrings();
882 private native ParcelFileDescriptor nativeOpenAccessory();
Mike Lockwoodd462ecf2011-07-21 13:55:16 -0700883 private native boolean nativeIsStartRequested();
Mike Lockwood166b05e2012-04-24 10:45:18 -0700884 private native int nativeGetAudioMode();
Mike Lockwood46d0adf2011-05-26 10:27:39 -0400885}