Commit c1aebfa0 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Clean up USB Manager and fix ADB." into mnc-dev

No related merge requests found
......@@ -82,6 +82,9 @@ interface IUsbManager
/* Clears default preferences and permissions for the package */
void clearDefaults(String packageName, int userId);
/* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function);
/* Sets the current USB function. */
void setCurrentFunction(String function);
......
......@@ -22,7 +22,6 @@ import android.content.Context;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Log;
import java.util.HashMap;
......@@ -54,8 +53,6 @@ public class UsbManager {
* <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
* <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured.
* currently zero if not configured, one for configured.
* <li> {@link #USB_FUNCTION_MASS_STORAGE} boolean extra indicating whether the
* mass storage function is enabled
* <li> {@link #USB_FUNCTION_ADB} boolean extra indicating whether the
* adb function is enabled
* <li> {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the
......@@ -152,12 +149,13 @@ public class UsbManager {
public static final String USB_DATA_UNLOCKED = "unlocked";
/**
* Name of the USB mass storage USB function.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast
* A placeholder indicating that no USB function is being specified.
* Used to distinguish between selecting no function vs. the default function in
* {@link #setCurrentFunction(String)}.
*
* {@hide}
*/
public static final String USB_FUNCTION_MASS_STORAGE = "mass_storage";
public static final String USB_FUNCTION_NONE = "none";
/**
* Name of the adb USB function.
......@@ -218,15 +216,14 @@ public class UsbManager {
/**
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and
* {@link #ACTION_USB_DEVICE_DETACHED} broadcasts
* containing the UsbDevice object for the device.
* containing the {@link UsbDevice} object for the device.
*/
public static final String EXTRA_DEVICE = "device";
/**
* Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and
* {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts
* containing the UsbAccessory object for the accessory.
* containing the {@link UsbAccessory} object for the accessory.
*/
public static final String EXTRA_ACCESSORY = "accessory";
......@@ -238,23 +235,6 @@ public class UsbManager {
*/
public static final String EXTRA_PERMISSION_GRANTED = "permission";
/**
* The persistent property which stores whether adb is enabled or not. Other values are ignored.
* Previously this value stored non-adb settings, but not anymore.
* TODO: rename this to something adb specific, rather than using usb.
*
* {@hide}
*/
public static final String ADB_PERSISTENT_PROPERTY = "persist.sys.usb.config";
/**
* The non-persistent property which stores the current USB settings.
*
* {@hide}
*/
public static final String USB_SETTINGS_PROPERTY = "sys.usb.config";
private final Context mContext;
private final IUsbManager mService;
......@@ -437,31 +417,44 @@ public class UsbManager {
}
}
private static boolean propertyContainsFunction(String property, String function) {
String functions = SystemProperties.get(property, "");
int index = functions.indexOf(function);
if (index < 0) return false;
if (index > 0 && functions.charAt(index - 1) != ',') return false;
int charAfter = index + function.length();
if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
return true;
}
/**
* Returns true if the specified USB function is currently enabled.
* Returns true if the specified USB function is currently enabled when in device mode.
* <p>
* USB functions represent interfaces which are published to the host to access
* services offered by the device.
* </p>
*
* @param function name of the USB function
* @return true if the USB function is enabled.
* @return true if the USB function is enabled
*
* {@hide}
*/
public boolean isFunctionEnabled(String function) {
return propertyContainsFunction(USB_SETTINGS_PROPERTY, function);
try {
return mService.isFunctionEnabled(function);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in setCurrentFunction", e);
return false;
}
}
/**
* Sets the current USB function.
* If function is null, then the current function is set to the default function.
* Sets the current USB function when in device mode.
* <p>
* USB functions represent interfaces which are published to the host to access
* services offered by the device.
* </p><p>
* This method is intended to select among primary USB functions. The system may
* automatically activate additional functions such as {@link #USB_FUNCTION_ADB}
* or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states.
* </p><p>
* The allowed values are: {@link #USB_FUNCTION_NONE}, {@link #USB_FUNCTION_AUDIO_SOURCE},
* {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
* or {@link #USB_FUNCTION_RNDIS}.
* </p><p>
* Note: This function is asynchronous and may fail silently without applying
* the requested changes.
* </p>
*
* @param function name of the USB function, or null to restore the default function
*
......@@ -477,8 +470,9 @@ public class UsbManager {
/**
* Sets whether USB data (for example, MTP exposed pictures) should be made available
* on the USB connection. Unlocking usb data should only be done with user involvement,
* since exposing pictures or other data could leak sensitive user information.
* on the USB connection when in device mode. Unlocking usb data should only be done with
* user involvement, since exposing pictures or other data could leak sensitive
* user information.
*
* {@hide}
*/
......@@ -491,7 +485,8 @@ public class UsbManager {
}
/**
* Returns {@code true} iff access to sensitive USB data is currently allowed.
* Returns {@code true} iff access to sensitive USB data is currently allowed when
* in device mode.
*
* {@hide}
*/
......@@ -504,4 +499,51 @@ public class UsbManager {
return false;
}
/** @hide */
public static String addFunction(String functions, String function) {
if ("none".equals(functions)) {
return function;
}
if (!containsFunction(functions, function)) {
if (functions.length() > 0) {
functions += ",";
}
functions += function;
}
return functions;
}
/** @hide */
public static String removeFunction(String functions, String function) {
String[] split = functions.split(",");
for (int i = 0; i < split.length; i++) {
if (function.equals(split[i])) {
split[i] = null;
}
}
if (split.length == 1 && split[0] == null) {
return "none";
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
String s = split[i];
if (s != null) {
if (builder.length() > 0) {
builder.append(",");
}
builder.append(s);
}
}
return builder.toString();
}
/** @hide */
public static boolean containsFunction(String functions, String function) {
int index = functions.indexOf(function);
if (index < 0) return false;
if (index > 0 && functions.charAt(index - 1) != ',') return false;
int charAfter = index + function.length();
if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
return true;
}
}
......@@ -2884,8 +2884,6 @@
<string name="usb_ptp_notification_title">USB for photo transfer</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title -->
<string name="usb_midi_notification_title">USB for MIDI</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in mass storage mode (for installer CD image). This is the title -->
<string name="usb_cd_installer_notification_title">Connected as an installer</string>
<!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title -->
<string name="usb_accessory_notification_title">Connected to a USB accessory</string>
<!-- See USB_PREFERENCES. This is the message. -->
......
......@@ -1799,7 +1799,6 @@
<java-symbol type="string" name="tethered_notification_message" />
<java-symbol type="string" name="tethered_notification_title" />
<java-symbol type="string" name="usb_accessory_notification_title" />
<java-symbol type="string" name="usb_cd_installer_notification_title" />
<java-symbol type="string" name="usb_mtp_notification_title" />
<java-symbol type="string" name="usb_charging_notification_title" />
<java-symbol type="string" name="usb_notification_message" />
......
......@@ -60,7 +60,6 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
......@@ -5446,10 +5445,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
userHandle);
} else if (UserManager.DISALLOW_USB_FILE_TRANSFER.equals(key)) {
UsbManager manager =
(UsbManager) mContext.getSystemService(Context.USB_SERVICE);
manager.setCurrentFunction("none");
} else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
......
......@@ -17,6 +17,7 @@
package com.android.server.usb;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
......@@ -25,10 +26,11 @@ import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
......@@ -63,6 +65,8 @@ public class UsbService extends IUsbManager.Stub {
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mUsbService.systemReady();
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mUsbService.bootCompleted();
}
}
}
......@@ -108,13 +112,15 @@ public class UsbService extends IUsbManager.Stub {
setCurrentUser(UserHandle.USER_OWNER);
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_SWITCHED);
userFilter.addAction(Intent.ACTION_USER_STOPPED);
mContext.registerReceiver(mUserReceiver, userFilter, null, null);
final IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiver(mReceiver, filter, null, null);
}
private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
......@@ -125,6 +131,11 @@ public class UsbService extends IUsbManager.Stub {
synchronized (mLock) {
mSettingsByUser.remove(userId);
}
} else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
.equals(action)) {
if (mDeviceManager != null) {
mDeviceManager.updateUserRestrictions();
}
}
}
};
......@@ -135,7 +146,7 @@ public class UsbService extends IUsbManager.Stub {
mHostManager.setCurrentSettings(userSettings);
}
if (mDeviceManager != null) {
mDeviceManager.setCurrentSettings(userSettings);
mDeviceManager.setCurrentUser(userId, userSettings);
}
}
......@@ -150,6 +161,12 @@ public class UsbService extends IUsbManager.Stub {
}
}
public void bootCompleted() {
if (mDeviceManager != null) {
mDeviceManager.bootCompleted();
}
}
/* Returns a list of all currently attached USB devices (host mdoe) */
@Override
public void getDeviceList(Bundle devices) {
......@@ -251,16 +268,20 @@ public class UsbService extends IUsbManager.Stub {
getSettingsForUser(userId).clearDefaults(packageName);
}
@Override
public boolean isFunctionEnabled(String function) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
}
@Override
public void setCurrentFunction(String function) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
// If attempt to change USB function while file transfer is restricted, ensure that
// the current function is set to "none", and return.
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
if (mDeviceManager != null) mDeviceManager.setCurrentFunctions("none");
return;
if (!isSupportedCurrentFunction(function)) {
Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
+ function);
function = UsbManager.USB_FUNCTION_NONE;
}
if (mDeviceManager != null) {
......@@ -270,6 +291,22 @@ public class UsbService extends IUsbManager.Stub {
}
}
private static boolean isSupportedCurrentFunction(String function) {
if (function == null) return true;
switch (function) {
case UsbManager.USB_FUNCTION_NONE:
case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
case UsbManager.USB_FUNCTION_MIDI:
case UsbManager.USB_FUNCTION_MTP:
case UsbManager.USB_FUNCTION_PTP:
case UsbManager.USB_FUNCTION_RNDIS:
return true;
}
return false;
}
@Override
public void setUsbDataUnlocked(boolean unlocked) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment