Loading services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +98 −82 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.companion; import static com.android.internal.util.CollectionUtils.emptyIfNull; import static com.android.internal.util.CollectionUtils.find; import static com.android.internal.util.CollectionUtils.forEach; import static com.android.internal.util.FunctionalUtils.uncheckExceptions; import static com.android.internal.util.Preconditions.checkArgument; Loading Loading @@ -131,9 +132,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, ".DeviceDiscoveryService"); // 10 min public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000; private static final boolean DEBUG = false; private static final String LOG_TAG = "CompanionDeviceManagerService"; Loading Loading @@ -593,12 +591,45 @@ public class CompanionDeviceManagerService extends SystemService implements Bind void removeAssociation(int userId, String pkg, String deviceMacAddress) { updateAssociations(associations -> CollectionUtils.filter(associations, association -> { return association.getUserId() != userId boolean notMatch = association.getUserId() != userId || !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress) || !Objects.equals(association.getPackageName(), pkg); if (!notMatch) { onAssociationPreRemove(association); } return notMatch; })); } void onAssociationPreRemove(Association association) { String deviceProfile = association.getDeviceProfile(); if (deviceProfile != null) { Association otherAssociationWithDeviceProfile = find( getAllAssociations(association.getUserId()), a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile())); if (otherAssociationWithDeviceProfile != null) { Log.i(LOG_TAG, "Not revoking " + deviceProfile + " for " + association + " - profile still present in " + otherAssociationWithDeviceProfile); } else { mRoleManager.removeRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, UserHandle.of(association.getUserId()), getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to revoke device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); } } } private void updateSpecialAccessPermissionForAssociatedPackage(Association association) { PackageInfo packageInfo = getPackageInfo( association.getPackageName(), Loading Loading @@ -636,6 +667,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid); if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddress())) { grantDeviceProfile(association); } } private void exemptFromAutoRevoke(String packageName, int uid) { Loading Loading @@ -817,49 +852,22 @@ public class CompanionDeviceManagerService extends SystemService implements Bind void onDeviceConnected(String address) { mCurrentlyConnectedDevices.add(address); Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address)); for (UserInfo user : getAllUsers()) { for (Association association : getAllAssociations(user.id)) { if (Objects.equals(address, association.getDeviceMacAddress())) { if (association.getDeviceProfile() != null) { Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile() + " to " + association.getPackageName() + " due to device connected: " + address); mRoleManager.addRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, UserHandle.of(association.getUserId()), getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to grant device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); + " due to device connected: " + association.getDeviceMacAddress()); grantDeviceProfile(association); } } } } } void onDeviceDisconnected(String address) { mCurrentlyConnectedDevices.remove(address); Handler.getMain().postDelayed(() -> { if (!mCurrentlyConnectedDevices.contains(address)) { for (UserInfo user : getAllUsers()) { for (Association association : getAllAssociations(user.id)) { if (association.getDeviceProfile() != null && Objects.equals(address, association.getDeviceMacAddress()) && !association.isKeepProfilePrivilegesWhenDeviceAway()) { Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile() + " to " + association.getPackageName() + " due to device disconnected: " + address); mRoleManager.removeRoleHolderAsUser( private void grantDeviceProfile(Association association) { mRoleManager.addRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, Loading @@ -867,22 +875,16 @@ public class CompanionDeviceManagerService extends SystemService implements Bind getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to revoke device profile role " Log.e(LOG_TAG, "Failed to grant device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); } } } } }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS); } @NonNull private String getDisconnectJobHandlerId(String address) { return "CDM_onDisconnected_" + address; void onDeviceDisconnected(String address) { mCurrentlyConnectedDevices.remove(address); } private class ShellCmd extends ShellCommand { Loading @@ -898,34 +900,48 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public int onCommand(String cmd) { try { switch (cmd) { case "list": { forEach( getAllAssociations(getNextArgInt()), a -> getOutPrintWriter() .println(a.getPackageName() + " " + a.getDeviceMacAddress())); } break; .println(a.getPackageName() + " " + a.getDeviceMacAddress())); } break; case "associate": { addAssociation(new Association(getNextArgInt(), getNextArgRequired(), getNextArgRequired(), null, false)); } break; } break; case "disassociate": { removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); } break; removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); } break; case "simulate_connect": { onDeviceConnected(getNextArgRequired()); } break; } break; case "simulate_disconnect": { onDeviceDisconnected(getNextArgRequired()); } break; } break; default: return handleDefaultCommands(cmd); default: return handleDefaultCommands(cmd); } return 0; } catch (Throwable t) { Log.e(LOG_TAG, "Error running a command: $ " + cmd, t); getErrPrintWriter().println(Log.getStackTraceString(t)); return 1; } } private int getNextArgInt() { Loading Loading
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +98 −82 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.companion; import static com.android.internal.util.CollectionUtils.emptyIfNull; import static com.android.internal.util.CollectionUtils.find; import static com.android.internal.util.CollectionUtils.forEach; import static com.android.internal.util.FunctionalUtils.uncheckExceptions; import static com.android.internal.util.Preconditions.checkArgument; Loading Loading @@ -131,9 +132,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, ".DeviceDiscoveryService"); // 10 min public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000; private static final boolean DEBUG = false; private static final String LOG_TAG = "CompanionDeviceManagerService"; Loading Loading @@ -593,12 +591,45 @@ public class CompanionDeviceManagerService extends SystemService implements Bind void removeAssociation(int userId, String pkg, String deviceMacAddress) { updateAssociations(associations -> CollectionUtils.filter(associations, association -> { return association.getUserId() != userId boolean notMatch = association.getUserId() != userId || !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress) || !Objects.equals(association.getPackageName(), pkg); if (!notMatch) { onAssociationPreRemove(association); } return notMatch; })); } void onAssociationPreRemove(Association association) { String deviceProfile = association.getDeviceProfile(); if (deviceProfile != null) { Association otherAssociationWithDeviceProfile = find( getAllAssociations(association.getUserId()), a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile())); if (otherAssociationWithDeviceProfile != null) { Log.i(LOG_TAG, "Not revoking " + deviceProfile + " for " + association + " - profile still present in " + otherAssociationWithDeviceProfile); } else { mRoleManager.removeRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, UserHandle.of(association.getUserId()), getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to revoke device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); } } } private void updateSpecialAccessPermissionForAssociatedPackage(Association association) { PackageInfo packageInfo = getPackageInfo( association.getPackageName(), Loading Loading @@ -636,6 +667,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid); if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddress())) { grantDeviceProfile(association); } } private void exemptFromAutoRevoke(String packageName, int uid) { Loading Loading @@ -817,49 +852,22 @@ public class CompanionDeviceManagerService extends SystemService implements Bind void onDeviceConnected(String address) { mCurrentlyConnectedDevices.add(address); Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address)); for (UserInfo user : getAllUsers()) { for (Association association : getAllAssociations(user.id)) { if (Objects.equals(address, association.getDeviceMacAddress())) { if (association.getDeviceProfile() != null) { Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile() + " to " + association.getPackageName() + " due to device connected: " + address); mRoleManager.addRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, UserHandle.of(association.getUserId()), getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to grant device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); + " due to device connected: " + association.getDeviceMacAddress()); grantDeviceProfile(association); } } } } } void onDeviceDisconnected(String address) { mCurrentlyConnectedDevices.remove(address); Handler.getMain().postDelayed(() -> { if (!mCurrentlyConnectedDevices.contains(address)) { for (UserInfo user : getAllUsers()) { for (Association association : getAllAssociations(user.id)) { if (association.getDeviceProfile() != null && Objects.equals(address, association.getDeviceMacAddress()) && !association.isKeepProfilePrivilegesWhenDeviceAway()) { Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile() + " to " + association.getPackageName() + " due to device disconnected: " + address); mRoleManager.removeRoleHolderAsUser( private void grantDeviceProfile(Association association) { mRoleManager.addRoleHolderAsUser( association.getDeviceProfile(), association.getPackageName(), RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, Loading @@ -867,22 +875,16 @@ public class CompanionDeviceManagerService extends SystemService implements Bind getContext().getMainExecutor(), success -> { if (!success) { Log.e(LOG_TAG, "Failed to revoke device profile role " Log.e(LOG_TAG, "Failed to grant device profile role " + association.getDeviceProfile() + " to " + association.getPackageName() + " for user " + association.getUserId()); } }); } } } } }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS); } @NonNull private String getDisconnectJobHandlerId(String address) { return "CDM_onDisconnected_" + address; void onDeviceDisconnected(String address) { mCurrentlyConnectedDevices.remove(address); } private class ShellCmd extends ShellCommand { Loading @@ -898,34 +900,48 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public int onCommand(String cmd) { try { switch (cmd) { case "list": { forEach( getAllAssociations(getNextArgInt()), a -> getOutPrintWriter() .println(a.getPackageName() + " " + a.getDeviceMacAddress())); } break; .println(a.getPackageName() + " " + a.getDeviceMacAddress())); } break; case "associate": { addAssociation(new Association(getNextArgInt(), getNextArgRequired(), getNextArgRequired(), null, false)); } break; } break; case "disassociate": { removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); } break; removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); } break; case "simulate_connect": { onDeviceConnected(getNextArgRequired()); } break; } break; case "simulate_disconnect": { onDeviceDisconnected(getNextArgRequired()); } break; } break; default: return handleDefaultCommands(cmd); default: return handleDefaultCommands(cmd); } return 0; } catch (Throwable t) { Log.e(LOG_TAG, "Error running a command: $ " + cmd, t); getErrPrintWriter().println(Log.getStackTraceString(t)); return 1; } } private int getNextArgInt() { Loading