diff options
6 files changed, 192 insertions, 37 deletions
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 4dea4a7e3aca..b17dfa62004f 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -36,6 +36,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; @@ -177,7 +178,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. * */ @@ -529,6 +530,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> * diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index b5e2670e5299..4d05a286848f 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -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; /** @@ -101,5 +102,11 @@ interface ICompanionDeviceManager { void disableSystemDataSync(int associationId, int flags); + void enablePermissionsSync(int associationId); + + void disablePermissionsSync(int associationId); + + PermissionSyncRequest getPermissionSyncRequest(int associationId); + void enableSecureTransport(boolean enabled); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 9d6283b85bd4..2511b50c2106 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -64,6 +64,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; @@ -794,6 +795,24 @@ public class CompanionDeviceManagerService extends SystemService { } @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 public void enableSecureTransport(boolean enabled) { mTransportManager.enableSecureTransport(enabled); } @@ -934,7 +953,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); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java index 04fbab434d1f..d56436b17689 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java @@ -25,7 +25,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; @@ -43,20 +43,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; } @@ -265,16 +265,47 @@ class CompanionDeviceShellCommand extends ShellCommand { break; } - case "allow-permission-sync": { - int userId = getNextIntArgRequired(); + case "get-perm-sync-state": { 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.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(); + 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; } - break; default: return handleDefaultCommands(cmd); @@ -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."); } } diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java index 800a3d9f6852..aeb273be0207 100644 --- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java +++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java @@ -138,6 +138,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 allowlisted 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; } @@ -184,29 +191,17 @@ 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."; - Slog.e(LOG_TAG, message); - try { - callback.onError(message); - } catch (RemoteException ignored) { - } - return; + 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); + } catch (RemoteException ignored) { } + return; } // Start permission sync @@ -224,6 +219,66 @@ public class SystemDataTransferProcessor { } } + /** + * Enable perm sync for the association + */ + public void enablePermissionsSync(int associationId) { + final long callingIdentityToken = Binder.clearCallingIdentity(); + try { + int userId = mAssociationStore.getAssociationById(associationId).getUserId(); + PermissionSyncRequest request = new PermissionSyncRequest(associationId); + request.setUserConsented(true); + mSystemDataTransferRequestStore.writeRequest(userId, request); + } finally { + Binder.restoreCallingIdentity(callingIdentityToken); + } + } + + /** + * Disable perm sync for the association + */ + public void disablePermissionsSync(int associationId) { + final long callingIdentityToken = Binder.clearCallingIdentity(); + try { + int userId = mAssociationStore.getAssociationById(associationId).getUserId(); + PermissionSyncRequest request = new PermissionSyncRequest(associationId); + request.setUserConsented(false); + mSystemDataTransferRequestStore.writeRequest(userId, request); + } finally { + Binder.restoreCallingIdentity(callingIdentityToken); + } + } + + /** + * Get perm sync request for the association. + */ + @Nullable + public PermissionSyncRequest getPermissionSyncRequest(int associationId) { + final long callingIdentityToken = Binder.clearCallingIdentity(); + try { + 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; + } finally { + Binder.restoreCallingIdentity(callingIdentityToken); + } + } + + /** + * 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 diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java index 720cefa11d7c..9f489e8d613a 100644 --- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java +++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java @@ -104,7 +104,7 @@ public class SystemDataTransferRequestStore { } @NonNull - List<SystemDataTransferRequest> readRequestsByAssociationId(@UserIdInt int userId, + public List<SystemDataTransferRequest> readRequestsByAssociationId(@UserIdInt int userId, int associationId) { List<SystemDataTransferRequest> cachedRequests; synchronized (mLock) { |