diff --git a/core/java/android/hardware/Usb.java b/core/java/android/hardware/UsbManager.java similarity index 79% rename from core/java/android/hardware/Usb.java rename to core/java/android/hardware/UsbManager.java index 57271d4b72f87..eb394c1cb1663 100644 --- a/core/java/android/hardware/Usb.java +++ b/core/java/android/hardware/UsbManager.java @@ -17,11 +17,15 @@ package android.hardware; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + /** * Class for accessing USB state information. * @hide */ -public class Usb { +public class UsbManager { /** * Broadcast Action: A broadcast for USB connected events. * @@ -96,4 +100,30 @@ public class Usb { * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast */ public static final String USB_FUNCTION_DISABLED = "disabled"; + + private static File getFunctionEnableFile(String function) { + return new File("/sys/class/usb_composite/" + function + "/enable"); + } + + /** + * Returns true if the specified USB function is supported by the kernel. + * Note that a USB function maybe supported but disabled. + */ + public static boolean isFunctionSupported(String function) { + return getFunctionEnableFile(function).exists(); + } + + /** + * Returns true if the specified USB function is currently enabled. + */ + public static boolean isFunctionEnabled(String function) { + try { + FileInputStream stream = new FileInputStream(getFunctionEnableFile(function)); + boolean enabled = (stream.read() == '1'); + stream.close(); + return enabled; + } catch (IOException e) { + return false; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java index 5c52783d3a9db..1368baaf8caa1 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java @@ -30,7 +30,7 @@ import android.content.DialogInterface.OnCancelListener; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.hardware.Usb; +import android.hardware.UsbManager; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -83,7 +83,7 @@ public class UsbStorageActivity extends Activity private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(Usb.ACTION_USB_STATE)) { + if (intent.getAction().equals(UsbManager.ACTION_USB_STATE)) { handleUsbStateChanged(intent); } } @@ -175,7 +175,7 @@ public class UsbStorageActivity extends Activity super.onResume(); mStorageManager.registerListener(mStorageListener); - registerReceiver(mUsbStateReceiver, new IntentFilter(Usb.ACTION_USB_STATE)); + registerReceiver(mUsbStateReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE)); try { mAsyncStorageHandler.post(new Runnable() { @Override @@ -199,7 +199,7 @@ public class UsbStorageActivity extends Activity } private void handleUsbStateChanged(Intent intent) { - boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED); + boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); if (!connected) { // It was disconnected from the plug, so finish finish(); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index e8c1613eb4401..6a4cb811396cf 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -38,7 +38,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.ContentObserver; -import android.hardware.Usb; +import android.hardware.UsbManager; import android.media.AudioManager; import android.net.Uri; import android.os.BatteryManager; @@ -352,13 +352,13 @@ public class NotificationManagerService extends INotificationManager.Stub mBatteryFull = batteryFull; updateLights(); } - } else if (action.equals(Usb.ACTION_USB_STATE)) { + } else if (action.equals(UsbManager.ACTION_USB_STATE)) { Bundle extras = intent.getExtras(); - boolean usbConnected = extras.getBoolean(Usb.USB_CONNECTED); - boolean adbEnabled = (Usb.USB_FUNCTION_ENABLED.equals( - extras.getString(Usb.USB_FUNCTION_ADB))); + boolean usbConnected = extras.getBoolean(UsbManager.USB_CONNECTED); + boolean adbEnabled = (UsbManager.USB_FUNCTION_ENABLED.equals( + extras.getString(UsbManager.USB_FUNCTION_ADB))); updateAdbNotification(usbConnected && adbEnabled); - } else if (action.equals(Usb.ACTION_USB_DISCONNECTED)) { + } else if (action.equals(UsbManager.ACTION_USB_DISCONNECTED)) { updateAdbNotification(false); } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || action.equals(Intent.ACTION_PACKAGE_RESTARTED) @@ -464,7 +464,7 @@ public class NotificationManagerService extends INotificationManager.Stub // register for battery changed notifications IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(Usb.ACTION_USB_STATE); + filter.addAction(UsbManager.ACTION_USB_STATE); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index df69b76c339f2..25175e239db6e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -122,7 +122,7 @@ class ServerThread extends Thread { BluetoothA2dpService bluetoothA2dp = null; HeadsetObserver headset = null; DockObserver dock = null; - UsbObserver usb = null; + UsbService usb = null; UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; ThrottleService throttle = null; @@ -399,9 +399,9 @@ class ServerThread extends Thread { try { Slog.i(TAG, "USB Observer"); // Listen for USB changes - usb = new UsbObserver(context); + usb = new UsbService(context); } catch (Throwable e) { - Slog.e(TAG, "Failure starting UsbObserver", e); + Slog.e(TAG, "Failure starting UsbService", e); } try { @@ -493,7 +493,7 @@ class ServerThread extends Thread { final BatteryService batteryF = battery; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; - final UsbObserver usbF = usb; + final UsbService usbF = usb; final ThrottleService throttleF = throttle; final UiModeManagerService uiModeF = uiMode; final AppWidgetService appWidgetF = appWidget; diff --git a/services/java/com/android/server/UsbObserver.java b/services/java/com/android/server/UsbService.java similarity index 65% rename from services/java/com/android/server/UsbObserver.java rename to services/java/com/android/server/UsbService.java index d08fe9b3964b0..ad400bfad27be 100644 --- a/services/java/com/android/server/UsbObserver.java +++ b/services/java/com/android/server/UsbService.java @@ -19,7 +19,7 @@ package com.android.server; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.hardware.Usb; +import android.hardware.UsbManager; import android.net.Uri; import android.os.Handler; import android.os.Message; @@ -34,10 +34,10 @@ import java.io.FileReader; import java.util.ArrayList; /** - *
UsbObserver monitors for changes to USB state. + *
UsbService monitors for changes to USB state.
*/
-class UsbObserver extends UEventObserver {
- private static final String TAG = UsbObserver.class.getSimpleName();
+class UsbService {
+ private static final String TAG = UsbService.class.getSimpleName();
private static final boolean LOG = false;
private static final String USB_CONFIGURATION_MATCH = "DEVPATH=/devices/virtual/switch/usb_configuration";
@@ -60,58 +60,61 @@ class UsbObserver extends UEventObserver {
private PowerManagerService mPowerManager;
- public UsbObserver(Context context) {
- mContext = context;
- init(); // set initial status
+ private final UEventObserver mUEventObserver = new UEventObserver() {
+ @Override
+ public void onUEvent(UEventObserver.UEvent event) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Slog.v(TAG, "USB UEVENT: " + event.toString());
+ }
- startObserving(USB_CONFIGURATION_MATCH);
- startObserving(USB_FUNCTIONS_MATCH);
- }
-
- @Override
- public void onUEvent(UEventObserver.UEvent event) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Slog.v(TAG, "USB UEVENT: " + event.toString());
- }
-
- synchronized (this) {
- String switchState = event.get("SWITCH_STATE");
- if (switchState != null) {
- try {
- int newConfig = Integer.parseInt(switchState);
- if (newConfig != mUsbConfig) {
- mPreviousUsbConfig = mUsbConfig;
- mUsbConfig = newConfig;
- // trigger an Intent broadcast
- if (mSystemReady) {
- update();
+ synchronized (this) {
+ String switchState = event.get("SWITCH_STATE");
+ if (switchState != null) {
+ try {
+ int newConfig = Integer.parseInt(switchState);
+ if (newConfig != mUsbConfig) {
+ mPreviousUsbConfig = mUsbConfig;
+ mUsbConfig = newConfig;
+ // trigger an Intent broadcast
+ if (mSystemReady) {
+ update();
+ }
}
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Could not parse switch state from event " + event);
}
- } catch (NumberFormatException e) {
- Slog.e(TAG, "Could not parse switch state from event " + event);
- }
- } else {
- String function = event.get("FUNCTION");
- String enabledStr = event.get("ENABLED");
- if (function != null && enabledStr != null) {
- // Note: we do not broadcast a change when a function is enabled or disabled.
- // We just record the state change for the next broadcast.
- boolean enabled = "1".equals(enabledStr);
- if (enabled) {
- if (!mEnabledFunctions.contains(function)) {
- mEnabledFunctions.add(function);
+ } else {
+ String function = event.get("FUNCTION");
+ String enabledStr = event.get("ENABLED");
+ if (function != null && enabledStr != null) {
+ // Note: we do not broadcast a change when a function is enabled or disabled.
+ // We just record the state change for the next broadcast.
+ boolean enabled = "1".equals(enabledStr);
+ if (enabled) {
+ if (!mEnabledFunctions.contains(function)) {
+ mEnabledFunctions.add(function);
+ }
+ mDisabledFunctions.remove(function);
+ } else {
+ if (!mDisabledFunctions.contains(function)) {
+ mDisabledFunctions.add(function);
+ }
+ mEnabledFunctions.remove(function);
}
- mDisabledFunctions.remove(function);
- } else {
- if (!mDisabledFunctions.contains(function)) {
- mDisabledFunctions.add(function);
- }
- mEnabledFunctions.remove(function);
}
}
}
}
+ };
+
+ public UsbService(Context context) {
+ mContext = context;
+ init(); // set initial status
+
+ mUEventObserver.startObserving(USB_CONFIGURATION_MATCH);
+ mUEventObserver.startObserving(USB_FUNCTIONS_MATCH);
}
+
private final void init() {
char[] buffer = new char[1024];
@@ -162,10 +165,10 @@ class UsbObserver extends UEventObserver {
private void addEnabledFunctions(Intent intent) {
// include state of all USB functions in our extras
for (int i = 0; i < mEnabledFunctions.size(); i++) {
- intent.putExtra(mEnabledFunctions.get(i), Usb.USB_FUNCTION_ENABLED);
+ intent.putExtra(mEnabledFunctions.get(i), UsbManager.USB_FUNCTION_ENABLED);
}
for (int i = 0; i < mDisabledFunctions.size(); i++) {
- intent.putExtra(mDisabledFunctions.get(i), Usb.USB_FUNCTION_DISABLED);
+ intent.putExtra(mDisabledFunctions.get(i), UsbManager.USB_FUNCTION_DISABLED);
}
}
@@ -186,17 +189,17 @@ class UsbObserver extends UEventObserver {
Intent intent;
boolean usbConnected = (mUsbConfig != 0);
if (usbConnected) {
- intent = new Intent(Usb.ACTION_USB_CONNECTED);
+ intent = new Intent(UsbManager.ACTION_USB_CONNECTED);
addEnabledFunctions(intent);
} else {
- intent = new Intent(Usb.ACTION_USB_DISCONNECTED);
+ intent = new Intent(UsbManager.ACTION_USB_DISCONNECTED);
}
mContext.sendBroadcast(intent);
// send a sticky broadcast for clients interested in both connect and disconnect
- intent = new Intent(Usb.ACTION_USB_STATE);
+ intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(Usb.USB_CONNECTED, usbConnected);
+ intent.putExtra(UsbManager.USB_CONNECTED, usbConnected);
addEnabledFunctions(intent);
mContext.sendStickyBroadcast(intent);
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index a73a4ce26485b..5712e60fb8d87 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -26,7 +26,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.hardware.Usb;
+import android.hardware.UsbManager;
import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.net.IConnectivityManager;
@@ -143,7 +143,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mStateReceiver = new StateReceiver();
IntentFilter filter = new IntentFilter();
- filter.addAction(Usb.ACTION_USB_STATE);
+ filter.addAction(UsbManager.ACTION_USB_STATE);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
mContext.registerReceiver(mStateReceiver, filter);
@@ -440,10 +440,10 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private class StateReceiver extends BroadcastReceiver {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
- if (action.equals(Usb.ACTION_USB_STATE)) {
+ if (action.equals(UsbManager.ACTION_USB_STATE)) {
// process connect events immediately, but delay handling disconnects
// to debounce USB configuration changes
- boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
+ boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
Message msg = Message.obtain(mUsbHandler, USB_STATE_CHANGE,
(connected ? USB_CONNECTED : USB_DISCONNECTED), 0);
mUsbHandler.removeMessages(USB_STATE_CHANGE);
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index c90879d0a166f..de8f15891febd 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \
com_android_server_LightsService.cpp \
com_android_server_PowerManagerService.cpp \
com_android_server_SystemServer.cpp \
+ com_android_server_UsbService.cpp \
com_android_server_VibratorService.cpp \
com_android_server_location_GpsLocationProvider.cpp \
onload.cpp
diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp
new file mode 100644
index 0000000000000..dff86651c8b63
--- /dev/null
+++ b/services/jni/com_android_server_UsbService.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "UsbService"
+#include "utils/Log.h"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "utils/Vector.h"
+
+#include