Merge "Dump activities that handle when USB devices get plugged in"

This commit is contained in:
TreeHugger Robot
2018-06-03 05:32:33 +00:00
committed by Android (Google) Code Review
4 changed files with 200 additions and 26 deletions

View File

@@ -278,6 +278,8 @@ message UsbUserSettingsManagerProto {
optional int32 user_id = 1;
repeated UsbSettingsDevicePermissionProto device_permissions = 2;
repeated UsbSettingsAccessoryPermissionProto accessory_permissions = 3;
repeated UsbDeviceAttachedActivities device_attached_activities = 4;
repeated UsbAccessoryAttachedActivities accessory_attached_activities = 5;
}
message UsbSettingsDevicePermissionProto {
@@ -343,3 +345,17 @@ message UsbAccessoryFilterProto {
optional string model = 2;
optional string version = 3;
}
message UsbDeviceAttachedActivities {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
optional android.content.ComponentNameProto activity = 1;
repeated UsbDeviceFilterProto filters = 2;
}
message UsbAccessoryAttachedActivities {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
optional android.content.ComponentNameProto activity = 1;
repeated UsbAccessoryFilterProto filters = 2;
}

View File

@@ -445,38 +445,38 @@ class UsbProfileGroupSettingsManager {
});
}
// Checks to see if a package matches a device or accessory.
// Only one of device and accessory should be non-null.
private boolean packageMatchesLocked(ResolveInfo info, String metaDataName,
UsbDevice device, UsbAccessory accessory) {
if (isForwardMatch(info)) {
return true;
}
/**
* Get {@link DeviceFilter} for all devices an activity should be launched for.
*
* @param pm The package manager used to get the device filter files
* @param info The {@link ResolveInfo} for the activity that can handle usb device attached
* events
*
* @return The list of {@link DeviceFilter} the activity should be called for or {@code null} if
* none
*/
@Nullable
static ArrayList<DeviceFilter> getDeviceFilters(@NonNull PackageManager pm,
@NonNull ResolveInfo info) {
ArrayList<DeviceFilter> filters = null;
ActivityInfo ai = info.activityInfo;
XmlResourceParser parser = null;
try {
parser = ai.loadXmlMetaData(mPackageManager, metaDataName);
parser = ai.loadXmlMetaData(pm, UsbManager.ACTION_USB_DEVICE_ATTACHED);
if (parser == null) {
Slog.w(TAG, "no meta-data for " + info);
return false;
return null;
}
XmlUtils.nextElement(parser);
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
if (device != null && "usb-device".equals(tagName)) {
DeviceFilter filter = DeviceFilter.read(parser);
if (filter.matches(device)) {
return true;
}
}
else if (accessory != null && "usb-accessory".equals(tagName)) {
AccessoryFilter filter = AccessoryFilter.read(parser);
if (filter.matches(accessory)) {
return true;
if ("usb-device".equals(tagName)) {
if (filters == null) {
filters = new ArrayList<>(1);
}
filters.add(DeviceFilter.read(parser));
}
XmlUtils.nextElement(parser);
}
@@ -485,6 +485,84 @@ class UsbProfileGroupSettingsManager {
} finally {
if (parser != null) parser.close();
}
return filters;
}
/**
* Get {@link AccessoryFilter} for all accessories an activity should be launched for.
*
* @param pm The package manager used to get the accessory filter files
* @param info The {@link ResolveInfo} for the activity that can handle usb accessory attached
* events
*
* @return The list of {@link AccessoryFilter} the activity should be called for or {@code null}
* if none
*/
static @Nullable ArrayList<AccessoryFilter> getAccessoryFilters(@NonNull PackageManager pm,
@NonNull ResolveInfo info) {
ArrayList<AccessoryFilter> filters = null;
ActivityInfo ai = info.activityInfo;
XmlResourceParser parser = null;
try {
parser = ai.loadXmlMetaData(pm, UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
if (parser == null) {
Slog.w(TAG, "no meta-data for " + info);
return null;
}
XmlUtils.nextElement(parser);
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
if ("usb-accessory".equals(tagName)) {
if (filters == null) {
filters = new ArrayList<>(1);
}
filters.add(AccessoryFilter.read(parser));
}
XmlUtils.nextElement(parser);
}
} catch (Exception e) {
Slog.w(TAG, "Unable to load component info " + info.toString(), e);
} finally {
if (parser != null) parser.close();
}
return filters;
}
// Checks to see if a package matches a device or accessory.
// Only one of device and accessory should be non-null.
private boolean packageMatchesLocked(ResolveInfo info, UsbDevice device,
UsbAccessory accessory) {
if (isForwardMatch(info)) {
return true;
}
if (device != null) {
ArrayList<DeviceFilter> deviceFilters = getDeviceFilters(mPackageManager, info);
if (deviceFilters != null) {
int numDeviceFilters = deviceFilters.size();
for (int i = 0; i < numDeviceFilters; i++) {
if (deviceFilters.get(i).matches(device)) {
return true;
}
}
}
}
if (accessory != null) {
ArrayList<AccessoryFilter> accessoryFilters = getAccessoryFilters(mPackageManager,
info);
if (accessoryFilters != null) {
int numAccessoryFilters = accessoryFilters.size();
for (int i = 0; i < numAccessoryFilters; i++) {
if (accessoryFilters.get(i).matches(accessory)) {
return true;
}
}
}
}
return false;
}
@@ -502,8 +580,8 @@ class UsbProfileGroupSettingsManager {
ArrayList<ResolveInfo> resolveInfos = new ArrayList<>();
int numProfiles = profiles.size();
for (int i = 0; i < numProfiles; i++) {
resolveInfos.addAll(mPackageManager.queryIntentActivitiesAsUser(intent,
PackageManager.GET_META_DATA, profiles.get(i).id));
resolveInfos.addAll(mSettingsManager.getSettingsForUser(profiles.get(i).id)
.queryIntentActivities(intent));
}
return resolveInfos;
@@ -629,7 +707,7 @@ class UsbProfileGroupSettingsManager {
int count = resolveInfos.size();
for (int i = 0; i < count; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
if (packageMatchesLocked(resolveInfo, intent.getAction(), device, null)) {
if (packageMatchesLocked(resolveInfo, device, null)) {
matches.add(resolveInfo);
}
}
@@ -644,7 +722,7 @@ class UsbProfileGroupSettingsManager {
int count = resolveInfos.size();
for (int i = 0; i < count; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
if (packageMatchesLocked(resolveInfo, intent.getAction(), null, accessory)) {
if (packageMatchesLocked(resolveInfo, null, accessory)) {
matches.add(resolveInfo);
}
}

View File

@@ -33,6 +33,8 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.dump.DualDumpOutputStream;
import java.util.List;
/**
* Maintains all {@link UsbUserSettingsManager} for all users.
*/
@@ -140,9 +142,10 @@ class UsbSettingsManager {
long token = dump.start(idName, id);
synchronized (mSettingsByUser) {
int numUsers = mSettingsByUser.size();
List<UserInfo> users = mUserManager.getUsers();
int numUsers = users.size();
for (int i = 0; i < numUsers; i++) {
mSettingsByUser.valueAt(i).dump(dump, "user_settings",
getSettingsForUser(users.get(i).id).dump(dump, "user_settings",
UsbSettingsManagerProto.USER_SETTINGS);
}
}

View File

@@ -16,14 +16,22 @@
package com.android.server.usb;
import static com.android.internal.util.dump.DumpUtils.writeComponentName;
import static com.android.server.usb.UsbProfileGroupSettingsManager.getAccessoryFilters;
import static com.android.server.usb.UsbProfileGroupSettingsManager.getDeviceFilters;
import android.annotation.NonNull;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.hardware.usb.AccessoryFilter;
import android.hardware.usb.DeviceFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
@@ -32,6 +40,8 @@ import android.hardware.usb.UsbManager;
import android.os.Binder;
import android.os.Process;
import android.os.UserHandle;
import android.service.usb.UsbAccessoryAttachedActivities;
import android.service.usb.UsbDeviceAttachedActivities;
import android.service.usb.UsbSettingsAccessoryPermissionProto;
import android.service.usb.UsbSettingsDevicePermissionProto;
import android.service.usb.UsbUserSettingsManagerProto;
@@ -40,7 +50,9 @@ import android.util.SparseBooleanArray;
import com.android.internal.util.dump.DualDumpOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
class UsbUserSettingsManager {
private static final String TAG = "UsbUserSettingsManager";
@@ -305,6 +317,18 @@ class UsbUserSettingsManager {
}
}
/**
* Get all activities that can handle the device/accessory attached intent.
*
* @param intent The intent to handle
*
* @return The resolve infos of the activities that can handle the intent
*/
List<ResolveInfo> queryIntentActivities(@NonNull Intent intent) {
return mPackageManager.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA,
mUser.getIdentifier());
}
public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
long token = dump.start(idName, id);
@@ -341,6 +365,59 @@ class UsbUserSettingsManager {
dump.end(accessoryPermissionToken);
}
List<ResolveInfo> deviceAttachedActivities = queryIntentActivities(
new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED));
int numDeviceAttachedActivities = deviceAttachedActivities.size();
for (int activityNum = 0; activityNum < numDeviceAttachedActivities; activityNum++) {
ResolveInfo deviceAttachedActivity = deviceAttachedActivities.get(activityNum);
long deviceAttachedActivityToken = dump.start("device_attached_activities",
UsbUserSettingsManagerProto.DEVICE_ATTACHED_ACTIVITIES);
writeComponentName(dump, "activity", UsbDeviceAttachedActivities.ACTIVITY,
new ComponentName(deviceAttachedActivity.activityInfo.packageName,
deviceAttachedActivity.activityInfo.name));
ArrayList<DeviceFilter> deviceFilters = getDeviceFilters(mPackageManager,
deviceAttachedActivity);
if (deviceFilters != null) {
int numDeviceFilters = deviceFilters.size();
for (int filterNum = 0; filterNum < numDeviceFilters; filterNum++) {
deviceFilters.get(filterNum).dump(dump, "filters",
UsbDeviceAttachedActivities.FILTERS);
}
}
dump.end(deviceAttachedActivityToken);
}
List<ResolveInfo> accessoryAttachedActivities =
queryIntentActivities(new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED));
int numAccessoryAttachedActivities = accessoryAttachedActivities.size();
for (int activityNum = 0; activityNum < numAccessoryAttachedActivities; activityNum++) {
ResolveInfo accessoryAttachedActivity =
accessoryAttachedActivities.get(activityNum);
long accessoryAttachedActivityToken = dump.start("accessory_attached_activities",
UsbUserSettingsManagerProto.ACCESSORY_ATTACHED_ACTIVITIES);
writeComponentName(dump, "activity", UsbAccessoryAttachedActivities.ACTIVITY,
new ComponentName(accessoryAttachedActivity.activityInfo.packageName,
accessoryAttachedActivity.activityInfo.name));
ArrayList<AccessoryFilter> accessoryFilters = getAccessoryFilters(mPackageManager,
accessoryAttachedActivity);
if (accessoryFilters != null) {
int numAccessoryFilters = accessoryFilters.size();
for (int filterNum = 0; filterNum < numAccessoryFilters; filterNum++) {
accessoryFilters.get(filterNum).dump(dump, "filters",
UsbAccessoryAttachedActivities.FILTERS);
}
}
dump.end(accessoryAttachedActivityToken);
}
}
dump.end(token);