diff options
-rw-r--r-- | core/java/android/hardware/usb/IUsbManager.aidl | 6 | ||||
-rw-r--r-- | core/java/android/hardware/usb/UsbManager.java | 27 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 2 | ||||
-rw-r--r-- | media/java/android/mtp/MtpServer.java | 5 | ||||
-rw-r--r-- | media/jni/android_mtp_MtpServer.cpp | 18 | ||||
-rw-r--r-- | services/core/jni/Android.bp | 1 | ||||
-rw-r--r-- | services/core/jni/com_android_server_UsbDeviceManager.cpp | 35 | ||||
-rw-r--r-- | services/usb/java/com/android/server/usb/UsbDeviceManager.java | 52 | ||||
-rw-r--r-- | services/usb/java/com/android/server/usb/UsbService.java | 7 |
9 files changed, 120 insertions, 33 deletions
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index 91bbdc7dde80..6d9c913dfab7 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -105,6 +105,12 @@ interface IUsbManager /* Gets the current screen unlocked functions. */ long getScreenUnlockedFunctions(); + /* Get the functionfs control handle for the given function. Usb + * descriptors will already be written, and the handle will be + * ready to use. + */ + ParcelFileDescriptor getControlFd(long function); + /* Allow USB debugging from the attached host. If alwaysAllow is true, add the * the public key to list of host keys that the user has approved. */ diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 572c58564c8d..46142e35038d 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -192,14 +192,6 @@ public class UsbManager { public static final String USB_DATA_UNLOCKED = "unlocked"; /** - * Boolean extra indicating whether the intent represents a change in the usb - * configuration (as opposed to a state update). - * - * {@hide} - */ - public static final String USB_CONFIG_CHANGED = "config_changed"; - - /** * A placeholder indicating that no USB function is being specified. * Used for compatibility with old init scripts to indicate no functions vs. charging function. * @@ -471,6 +463,25 @@ public class UsbManager { } /** + * Gets the functionfs control file descriptor for the given function, with + * the usb descriptors and strings already written. The file descriptor is used + * by the function implementation to handle events and control requests. + * + * @param function to get control fd for. Currently {@link #FUNCTION_MTP} and + * {@link #FUNCTION_PTP} are supported. + * @return A ParcelFileDescriptor holding the valid fd, or null if the fd was not found. + * + * {@hide} + */ + public ParcelFileDescriptor getControlFd(long function) { + try { + return mService.getControlFd(function); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Returns true if the caller has permission to access the device. * Permission might have been granted temporarily via * {@link #requestPermission(UsbDevice, PendingIntent)} or diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 66035f499b94..9467eccd3ff7 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -652,7 +652,7 @@ public class ZygoteInit { String args[] = { "--setuid=1000", "--setgid=1000", - "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,1065,3001,3002,3003,3006,3007,3009,3010", + "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java index f2b110680af1..8af5ff7ac1fc 100644 --- a/media/java/android/mtp/MtpServer.java +++ b/media/java/android/mtp/MtpServer.java @@ -18,6 +18,8 @@ package android.mtp; import com.android.internal.util.Preconditions; +import java.io.FileDescriptor; + /** * Java wrapper for MTP/PTP support as USB responder. * {@hide} @@ -34,6 +36,7 @@ public class MtpServer implements Runnable { public MtpServer( MtpDatabase database, + FileDescriptor controlFd, boolean usePtp, Runnable onTerminate, String deviceInfoManufacturer, @@ -44,6 +47,7 @@ public class MtpServer implements Runnable { mOnTerminate = Preconditions.checkNotNull(onTerminate); native_setup( database, + controlFd, usePtp, deviceInfoManufacturer, deviceInfoModel, @@ -92,6 +96,7 @@ public class MtpServer implements Runnable { public static native final void native_configure(boolean usePtp); private native final void native_setup( MtpDatabase database, + FileDescriptor controlFd, boolean usePtp, String deviceInfoManufacturer, String deviceInfoModel, diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp index c76cebebc730..8730e0622200 100644 --- a/media/jni/android_mtp_MtpServer.cpp +++ b/media/jni/android_mtp_MtpServer.cpp @@ -55,22 +55,17 @@ static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) { return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext); } -static void android_mtp_configure(JNIEnv *, jobject, jboolean usePtp) { - MtpServer::configure(usePtp); -} - static void -android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp, - jstring deviceInfoManufacturer, - jstring deviceInfoModel, - jstring deviceInfoDeviceVersion, - jstring deviceInfoSerialNumber) +android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jobject jControlFd, + jboolean usePtp, jstring deviceInfoManufacturer, jstring deviceInfoModel, + jstring deviceInfoDeviceVersion, jstring deviceInfoSerialNumber) { const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL); const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL); const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL); const char *deviceInfoSerialNumberStr = env->GetStringUTFChars(deviceInfoSerialNumber, NULL); - MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase), + int controlFd = dup(jniGetFDFromFileDescriptor(env, jControlFd)); + MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase), controlFd, usePtp, MtpString((deviceInfoManufacturerStr != NULL) ? deviceInfoManufacturerStr : ""), MtpString((deviceInfoModelStr != NULL) ? deviceInfoModelStr : ""), @@ -201,8 +196,7 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { - {"native_configure", "(Z)V", (void *)android_mtp_configure}, - {"native_setup", "(Landroid/mtp/MtpDatabase;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", + {"native_setup", "(Landroid/mtp/MtpDatabase;Ljava/io/FileDescriptor;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void *)android_mtp_MtpServer_setup}, {"native_run", "()V", (void *)android_mtp_MtpServer_run}, {"native_cleanup", "()V", (void *)android_mtp_MtpServer_cleanup}, diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 427b9d2da948..89efe12927ba 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -86,6 +86,7 @@ cc_defaults { "libhardware_legacy", "libhidlbase", "libkeystore_binder", + "libmtp", "libnativehelper", "libutils", "libui", diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp index f37f87060fa6..ff1ec04cb23e 100644 --- a/services/core/jni/com_android_server_UsbDeviceManager.cpp +++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp @@ -21,6 +21,7 @@ #include <nativehelper/JNIHelp.h> #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" +#include "MtpDescriptors.h" #include <stdio.h> #include <asm/byteorder.h> @@ -118,6 +119,38 @@ static jint android_server_UsbDeviceManager_getAudioMode(JNIEnv* /* env */, jobj return result; } +static jobject android_server_UsbDeviceManager_openControl(JNIEnv *env, jobject /* thiz */, jstring jFunction) { + const char *function = env->GetStringUTFChars(jFunction, NULL); + bool ptp = false; + int fd = -1; + if (!strcmp(function, "ptp")) { + ptp = true; + } + if (!strcmp(function, "mtp") || ptp) { + fd = TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP0 : FFS_MTP_EP0, O_RDWR)); + if (fd < 0) { + ALOGE("could not open control for %s %s", function, strerror(errno)); + goto error; + } + if (!writeDescriptors(fd, ptp)) { + goto error; + } + } + + if (function != NULL) { + env->ReleaseStringUTFChars(jFunction, function); + } + return jniCreateFileDescriptor(env, fd); +error: + if (fd != -1) { + close(fd); + } + if (function != NULL) { + env->ReleaseStringUTFChars(jFunction, function); + } + return NULL; +} + static const JNINativeMethod method_table[] = { { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void*)android_server_UsbDeviceManager_getAccessoryStrings }, @@ -127,6 +160,8 @@ static const JNINativeMethod method_table[] = { (void*)android_server_UsbDeviceManager_isStartRequested }, { "nativeGetAudioMode", "()I", (void*)android_server_UsbDeviceManager_getAudioMode }, + { "nativeOpenControl", "(Ljava/lang/String;)Ljava/io/FileDescriptor;", + (void*)android_server_UsbDeviceManager_openControl }, }; int register_android_server_UsbDeviceManager(JNIEnv *env) diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index ef0780a0eeff..9f8042c844de 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -83,6 +83,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; @@ -181,6 +182,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver private final UEventObserver mUEventObserver; private static Set<Integer> sBlackListedInterfaces; + private HashMap<Long, FileDescriptor> mControlFds; static { sBlackListedInterfaces = new HashSet<>(); @@ -270,6 +272,18 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver Slog.i(TAG, "USB GADGET HAL not present in the device", e); } + mControlFds = new HashMap<>(); + FileDescriptor mtpFd = nativeOpenControl(UsbManager.USB_FUNCTION_MTP); + if (mtpFd == null) { + Slog.e(TAG, "Failed to open control for mtp"); + } + mControlFds.put(UsbManager.FUNCTION_MTP, mtpFd); + FileDescriptor ptpFd = nativeOpenControl(UsbManager.USB_FUNCTION_PTP); + if (mtpFd == null) { + Slog.e(TAG, "Failed to open control for mtp"); + } + mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd); + boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false); boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt")); if (secureAdbEnabled && !dataEncrypted) { @@ -704,8 +718,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver return false; } - protected void updateUsbStateBroadcastIfNeeded(long functions, - boolean configChanged) { + protected void updateUsbStateBroadcastIfNeeded(long functions) { // send a sticky broadcast containing current USB state Intent intent = new Intent(UsbManager.ACTION_USB_STATE); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING @@ -716,7 +729,6 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured); intent.putExtra(UsbManager.USB_DATA_UNLOCKED, isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions)); - intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged); long remainingFunctions = functions; while (remainingFunctions != 0) { @@ -726,7 +738,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver } // send broadcast intent only if the USB state has changed - if (!isUsbStateChanged(intent) && !configChanged) { + if (!isUsbStateChanged(intent)) { if (DEBUG) { Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras()); } @@ -798,8 +810,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver updateUsbNotification(false); updateAdbNotification(false); if (mBootCompleted) { - updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), - false); + updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions)); } if ((mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) != 0) { updateCurrentAccessory(); @@ -812,7 +823,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) { setScreenUnlockedFunctions(); } else { - setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled); + setEnabledFunctions(UsbManager.FUNCTION_NONE, false); } } updateUsbFunctions(); @@ -847,8 +858,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver updateUsbNotification(false); if (mBootCompleted) { if (mHostConnected || prevHostConnected) { - updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), - false); + updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions)); } } else { mPendingBootBroadcast = true; @@ -994,7 +1004,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver protected void finishBoot() { if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) { if (mPendingBootBroadcast) { - updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), false); + updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions)); mPendingBootBroadcast = false; } if (!mScreenLocked @@ -1597,7 +1607,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver /** * Start up dependent services. */ - updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), true); + updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions)); } if (!waitForState(oemFunctions)) { @@ -1943,7 +1953,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver if (mBootCompleted && isUsbDataTransferActive(functions)) { // Start up dependent services. - updateUsbStateBroadcastIfNeeded(functions, true); + updateUsbStateBroadcastIfNeeded(functions); } } } @@ -1979,6 +1989,22 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver return mHandler.getEnabledFunctions(); } + /** + * Returns a dup of the control file descriptor for the given function. + */ + public ParcelFileDescriptor getControlFd(long usbFunction) { + FileDescriptor fd = mControlFds.get(usbFunction); + if (fd == null) { + return null; + } + try { + return ParcelFileDescriptor.dup(fd); + } catch (IOException e) { + Slog.e(TAG, "Could not dup fd for " + usbFunction); + return null; + } + } + public long getScreenUnlockedFunctions() { return mHandler.getScreenUnlockedFunctions(); } @@ -2063,6 +2089,8 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver private native ParcelFileDescriptor nativeOpenAccessory(); + private native FileDescriptor nativeOpenControl(String usbFunction); + private native boolean nativeIsStartRequested(); private native int nativeGetAudioMode(); diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index c1a75912425a..e92bd74fadf2 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -304,6 +304,13 @@ public class UsbService extends IUsbManager.Stub { return null; } + /* Returns a dup of the control file descriptor for the given function. */ + @Override + public ParcelFileDescriptor getControlFd(long function) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_MTP, null); + return mDeviceManager.getControlFd(function); + } + @Override public void setDevicePackage(UsbDevice device, String packageName, int userId) { device = Preconditions.checkNotNull(device); |