Loading core/java/android/companion/CompanionDeviceManager.java +35 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -180,7 +181,7 @@ public final class CompanionDeviceManager { public @interface DataSyncTypes {} /** * Used by {@link #enableSystemDataSync(int, int)}}. * Used by {@link #enableSystemDataSyncForTypes(int, int)}}. * Sync call metadata like muting, ending and silencing a call. * */ Loading Loading @@ -551,6 +552,39 @@ public final class CompanionDeviceManager { } } /** * @hide */ public void enablePermissionsSync(int associationId) { try { mService.enablePermissionsSync(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ public void disablePermissionsSync(int associationId) { try { mService.disablePermissionsSync(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ public PermissionSyncRequest getPermissionSyncRequest(int associationId) { try { return mService.getPermissionSyncRequest(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * <p>Calling this API requires a uses-feature * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> Loading core/java/android/companion/ICompanionDeviceManager.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; /** Loading Loading @@ -113,6 +114,12 @@ interface ICompanionDeviceManager { void disableSystemDataSync(int associationId, int flags); void enablePermissionsSync(int associationId); void disablePermissionsSync(int associationId); PermissionSyncRequest getPermissionSyncRequest(int associationId); @EnforcePermission("MANAGE_COMPANION_DEVICES") void enableSecureTransport(boolean enabled); Loading services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +20 −1 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import android.companion.IOnAssociationsChangedListener; import android.companion.IOnMessageReceivedListener; import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; import android.companion.datatransfer.PermissionSyncRequest; import android.companion.utils.FeatureUtils; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -872,6 +873,24 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationRequestsProcessor.disableSystemDataSync(associationId, flags); } @Override public void enablePermissionsSync(int associationId) { getAssociationWithCallerChecks(associationId); mSystemDataTransferProcessor.enablePermissionsSync(associationId); } @Override public void disablePermissionsSync(int associationId) { getAssociationWithCallerChecks(associationId); mSystemDataTransferProcessor.disablePermissionsSync(associationId); } @Override public PermissionSyncRequest getPermissionSyncRequest(int associationId) { getAssociationWithCallerChecks(associationId); return mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); } @Override @EnforcePermission(MANAGE_COMPANION_DEVICES) public void enableSecureTransport(boolean enabled) { Loading Loading @@ -1041,7 +1060,7 @@ public class CompanionDeviceManagerService extends SystemService { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferRequestStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, mAssociationRequestsProcessor) .exec(this, in, out, err, args, callback, resultReceiver); } Loading services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +52 −12 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.os.Binder; import android.os.ShellCommand; import android.util.proto.ProtoOutputStream; import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; import com.android.server.companion.datatransfer.SystemDataTransferProcessor; import com.android.server.companion.datatransfer.contextsync.BitmapUtils; import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController; import com.android.server.companion.presence.CompanionDevicePresenceMonitor; Loading @@ -44,20 +44,20 @@ class CompanionDeviceShellCommand extends ShellCommand { private final CompanionDevicePresenceMonitor mDevicePresenceMonitor; private final CompanionTransportManager mTransportManager; private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private final SystemDataTransferProcessor mSystemDataTransferProcessor; private final AssociationRequestsProcessor mAssociationRequestsProcessor; CompanionDeviceShellCommand(CompanionDeviceManagerService service, AssociationStoreImpl associationStore, CompanionDevicePresenceMonitor devicePresenceMonitor, CompanionTransportManager transportManager, SystemDataTransferRequestStore systemDataTransferRequestStore, SystemDataTransferProcessor systemDataTransferProcessor, AssociationRequestsProcessor associationRequestsProcessor) { mService = service; mAssociationStore = associationStore; mDevicePresenceMonitor = devicePresenceMonitor; mTransportManager = transportManager; mSystemDataTransferRequestStore = systemDataTransferRequestStore; mSystemDataTransferProcessor = systemDataTransferProcessor; mAssociationRequestsProcessor = associationRequestsProcessor; } Loading Loading @@ -261,16 +261,47 @@ class CompanionDeviceShellCommand extends ShellCommand { break; } case "allow-permission-sync": { int userId = getNextIntArgRequired(); case "get-perm-sync-state": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println((request == null ? "null" : request.isUserConsented())); break; } case "remove-perm-sync-state": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.removePermissionSyncRequest(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); // should print " -> null" out.println(" -> " + (request == null ? "null" : request.isUserConsented())); break; } case "enable-perm-sync": { associationId = getNextIntArgRequired(); boolean enabled = getNextBooleanArgRequired(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserId(userId); request.setUserConsented(enabled); mSystemDataTransferRequestStore.writeRequest(userId, request); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.enablePermissionsSync(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println(" -> " + request.isUserConsented()); // should print " -> true" break; } case "disable-perm-sync": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.disablePermissionsSync(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println(" -> " + request.isUserConsented()); // should print " -> false" break; } default: return handleDefaultCommands(cmd); Loading Loading @@ -346,5 +377,14 @@ class CompanionDeviceShellCommand extends ShellCommand { pw.println(" create-emulated-transport <ASSOCIATION_ID>"); pw.println(" Create an EmulatedTransport for testing purposes only"); pw.println(" enable-perm-sync <ASSOCIATION_ID>"); pw.println(" Enable perm sync for the association."); pw.println(" disable-perm-sync <ASSOCIATION_ID>"); pw.println(" Disable perm sync for the association."); pw.println(" get-perm-sync-state <ASSOCIATION_ID>"); pw.println(" Get perm sync state for the association."); pw.println(" remove-perm-sync-state <ASSOCIATION_ID>"); pw.println(" Remove perm sync state for the association."); } } services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java +61 −22 Original line number Diff line number Diff line Loading @@ -139,6 +139,13 @@ public class SystemDataTransferProcessor { @UserIdInt int userId, int associationId) { if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) { Slog.i(LOG_TAG, "User consent Intent should be skipped. Returning null."); // Auto enable perm sync for the whitelisted packages, but don't override user decision PermissionSyncRequest request = getPermissionSyncRequest(associationId); if (request == null) { PermissionSyncRequest newRequest = new PermissionSyncRequest(associationId); newRequest.setUserConsented(true); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } return null; } Loading Loading @@ -185,22 +192,11 @@ public class SystemDataTransferProcessor { final AssociationInfo association = resolveAssociation(packageName, userId, associationId); // Check if the request has been consented by the user. if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) { Slog.i(LOG_TAG, "Skip user consent check due to the same OEM package."); } else { List<SystemDataTransferRequest> storedRequests = mSystemDataTransferRequestStore.readRequestsByAssociationId(userId, associationId); boolean hasConsented = false; for (SystemDataTransferRequest storedRequest : storedRequests) { if (storedRequest instanceof PermissionSyncRequest && storedRequest.isUserConsented()) { hasConsented = true; break; } } if (!hasConsented) { String message = "User " + userId + " hasn't consented permission sync."; PermissionSyncRequest request = getPermissionSyncRequest(associationId); if (request == null || !request.isUserConsented()) { String message = "User " + userId + " hasn't consented permission sync for associationId [" + associationId + "."; Slog.e(LOG_TAG, message); try { callback.onError(message); Loading @@ -208,7 +204,6 @@ public class SystemDataTransferProcessor { } return; } } // Start permission sync final long callingIdentityToken = Binder.clearCallingIdentity(); Loading @@ -225,6 +220,50 @@ public class SystemDataTransferProcessor { } } /** * Enable perm sync for the association */ public void enablePermissionsSync(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserConsented(true); mSystemDataTransferRequestStore.writeRequest(userId, request); } /** * Disable perm sync for the association */ public void disablePermissionsSync(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserConsented(false); mSystemDataTransferRequestStore.writeRequest(userId, request); } /** * Get perm sync request for the association. */ @Nullable public PermissionSyncRequest getPermissionSyncRequest(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); List<SystemDataTransferRequest> requests = mSystemDataTransferRequestStore.readRequestsByAssociationId(userId, associationId); for (SystemDataTransferRequest request : requests) { if (request instanceof PermissionSyncRequest) { return (PermissionSyncRequest) request; } } return null; } /** * Remove perm sync request for the association. */ public void removePermissionSyncRequest(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId); } private void onReceivePermissionRestore(byte[] message) { Slog.i(LOG_TAG, "Applying permissions."); // Start applying permissions Loading Loading
core/java/android/companion/CompanionDeviceManager.java +35 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -180,7 +181,7 @@ public final class CompanionDeviceManager { public @interface DataSyncTypes {} /** * Used by {@link #enableSystemDataSync(int, int)}}. * Used by {@link #enableSystemDataSyncForTypes(int, int)}}. * Sync call metadata like muting, ending and silencing a call. * */ Loading Loading @@ -551,6 +552,39 @@ public final class CompanionDeviceManager { } } /** * @hide */ public void enablePermissionsSync(int associationId) { try { mService.enablePermissionsSync(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ public void disablePermissionsSync(int associationId) { try { mService.disablePermissionsSync(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ public PermissionSyncRequest getPermissionSyncRequest(int associationId) { try { return mService.getPermissionSyncRequest(associationId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * <p>Calling this API requires a uses-feature * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> Loading
core/java/android/companion/ICompanionDeviceManager.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; /** Loading Loading @@ -113,6 +114,12 @@ interface ICompanionDeviceManager { void disableSystemDataSync(int associationId, int flags); void enablePermissionsSync(int associationId); void disablePermissionsSync(int associationId); PermissionSyncRequest getPermissionSyncRequest(int associationId); @EnforcePermission("MANAGE_COMPANION_DEVICES") void enableSecureTransport(boolean enabled); Loading
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +20 −1 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import android.companion.IOnAssociationsChangedListener; import android.companion.IOnMessageReceivedListener; import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; import android.companion.datatransfer.PermissionSyncRequest; import android.companion.utils.FeatureUtils; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -872,6 +873,24 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationRequestsProcessor.disableSystemDataSync(associationId, flags); } @Override public void enablePermissionsSync(int associationId) { getAssociationWithCallerChecks(associationId); mSystemDataTransferProcessor.enablePermissionsSync(associationId); } @Override public void disablePermissionsSync(int associationId) { getAssociationWithCallerChecks(associationId); mSystemDataTransferProcessor.disablePermissionsSync(associationId); } @Override public PermissionSyncRequest getPermissionSyncRequest(int associationId) { getAssociationWithCallerChecks(associationId); return mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); } @Override @EnforcePermission(MANAGE_COMPANION_DEVICES) public void enableSecureTransport(boolean enabled) { Loading Loading @@ -1041,7 +1060,7 @@ public class CompanionDeviceManagerService extends SystemService { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferRequestStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, mAssociationRequestsProcessor) .exec(this, in, out, err, args, callback, resultReceiver); } Loading
services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +52 −12 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.os.Binder; import android.os.ShellCommand; import android.util.proto.ProtoOutputStream; import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; import com.android.server.companion.datatransfer.SystemDataTransferProcessor; import com.android.server.companion.datatransfer.contextsync.BitmapUtils; import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController; import com.android.server.companion.presence.CompanionDevicePresenceMonitor; Loading @@ -44,20 +44,20 @@ class CompanionDeviceShellCommand extends ShellCommand { private final CompanionDevicePresenceMonitor mDevicePresenceMonitor; private final CompanionTransportManager mTransportManager; private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private final SystemDataTransferProcessor mSystemDataTransferProcessor; private final AssociationRequestsProcessor mAssociationRequestsProcessor; CompanionDeviceShellCommand(CompanionDeviceManagerService service, AssociationStoreImpl associationStore, CompanionDevicePresenceMonitor devicePresenceMonitor, CompanionTransportManager transportManager, SystemDataTransferRequestStore systemDataTransferRequestStore, SystemDataTransferProcessor systemDataTransferProcessor, AssociationRequestsProcessor associationRequestsProcessor) { mService = service; mAssociationStore = associationStore; mDevicePresenceMonitor = devicePresenceMonitor; mTransportManager = transportManager; mSystemDataTransferRequestStore = systemDataTransferRequestStore; mSystemDataTransferProcessor = systemDataTransferProcessor; mAssociationRequestsProcessor = associationRequestsProcessor; } Loading Loading @@ -261,16 +261,47 @@ class CompanionDeviceShellCommand extends ShellCommand { break; } case "allow-permission-sync": { int userId = getNextIntArgRequired(); case "get-perm-sync-state": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println((request == null ? "null" : request.isUserConsented())); break; } case "remove-perm-sync-state": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.removePermissionSyncRequest(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); // should print " -> null" out.println(" -> " + (request == null ? "null" : request.isUserConsented())); break; } case "enable-perm-sync": { associationId = getNextIntArgRequired(); boolean enabled = getNextBooleanArgRequired(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserId(userId); request.setUserConsented(enabled); mSystemDataTransferRequestStore.writeRequest(userId, request); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.enablePermissionsSync(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println(" -> " + request.isUserConsented()); // should print " -> true" break; } case "disable-perm-sync": { associationId = getNextIntArgRequired(); PermissionSyncRequest request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.print((request == null ? "null" : request.isUserConsented())); mSystemDataTransferProcessor.disablePermissionsSync(associationId); request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId); out.println(" -> " + request.isUserConsented()); // should print " -> false" break; } default: return handleDefaultCommands(cmd); Loading Loading @@ -346,5 +377,14 @@ class CompanionDeviceShellCommand extends ShellCommand { pw.println(" create-emulated-transport <ASSOCIATION_ID>"); pw.println(" Create an EmulatedTransport for testing purposes only"); pw.println(" enable-perm-sync <ASSOCIATION_ID>"); pw.println(" Enable perm sync for the association."); pw.println(" disable-perm-sync <ASSOCIATION_ID>"); pw.println(" Disable perm sync for the association."); pw.println(" get-perm-sync-state <ASSOCIATION_ID>"); pw.println(" Get perm sync state for the association."); pw.println(" remove-perm-sync-state <ASSOCIATION_ID>"); pw.println(" Remove perm sync state for the association."); } }
services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java +61 −22 Original line number Diff line number Diff line Loading @@ -139,6 +139,13 @@ public class SystemDataTransferProcessor { @UserIdInt int userId, int associationId) { if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) { Slog.i(LOG_TAG, "User consent Intent should be skipped. Returning null."); // Auto enable perm sync for the whitelisted packages, but don't override user decision PermissionSyncRequest request = getPermissionSyncRequest(associationId); if (request == null) { PermissionSyncRequest newRequest = new PermissionSyncRequest(associationId); newRequest.setUserConsented(true); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } return null; } Loading Loading @@ -185,22 +192,11 @@ public class SystemDataTransferProcessor { final AssociationInfo association = resolveAssociation(packageName, userId, associationId); // Check if the request has been consented by the user. if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) { Slog.i(LOG_TAG, "Skip user consent check due to the same OEM package."); } else { List<SystemDataTransferRequest> storedRequests = mSystemDataTransferRequestStore.readRequestsByAssociationId(userId, associationId); boolean hasConsented = false; for (SystemDataTransferRequest storedRequest : storedRequests) { if (storedRequest instanceof PermissionSyncRequest && storedRequest.isUserConsented()) { hasConsented = true; break; } } if (!hasConsented) { String message = "User " + userId + " hasn't consented permission sync."; PermissionSyncRequest request = getPermissionSyncRequest(associationId); if (request == null || !request.isUserConsented()) { String message = "User " + userId + " hasn't consented permission sync for associationId [" + associationId + "."; Slog.e(LOG_TAG, message); try { callback.onError(message); Loading @@ -208,7 +204,6 @@ public class SystemDataTransferProcessor { } return; } } // Start permission sync final long callingIdentityToken = Binder.clearCallingIdentity(); Loading @@ -225,6 +220,50 @@ public class SystemDataTransferProcessor { } } /** * Enable perm sync for the association */ public void enablePermissionsSync(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserConsented(true); mSystemDataTransferRequestStore.writeRequest(userId, request); } /** * Disable perm sync for the association */ public void disablePermissionsSync(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); PermissionSyncRequest request = new PermissionSyncRequest(associationId); request.setUserConsented(false); mSystemDataTransferRequestStore.writeRequest(userId, request); } /** * Get perm sync request for the association. */ @Nullable public PermissionSyncRequest getPermissionSyncRequest(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); List<SystemDataTransferRequest> requests = mSystemDataTransferRequestStore.readRequestsByAssociationId(userId, associationId); for (SystemDataTransferRequest request : requests) { if (request instanceof PermissionSyncRequest) { return (PermissionSyncRequest) request; } } return null; } /** * Remove perm sync request for the association. */ public void removePermissionSyncRequest(int associationId) { int userId = mAssociationStore.getAssociationById(associationId).getUserId(); mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId); } private void onReceivePermissionRestore(byte[] message) { Slog.i(LOG_TAG, "Applying permissions."); // Start applying permissions Loading