diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index c1f6219025f9ce427992989a0c29c6ee3a7c49c7..3baa92c18c27ee5cbc5e33dca9c037525fecd706 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -6,6 +6,7 @@ package android { field public static final String CONTROL_AUTOMOTIVE_GNSS = "android.permission.CONTROL_AUTOMOTIVE_GNSS"; field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT"; field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE"; + field public static final String USE_COMPANION_TRANSPORTS = "android.permission.USE_COMPANION_TRANSPORTS"; } } @@ -80,6 +81,29 @@ package android.app.admin { } +package android.companion { + + public final class CompanionDeviceManager { + method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnMessageReceivedListener(@NonNull java.util.concurrent.Executor, int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener); + method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener); + method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener); + method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener); + method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void sendMessage(int, @NonNull byte[], @NonNull int[]); + field public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 1667729539; // 0x63678883 + field public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 1669491075; // 0x63826983 + field public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 1669494629; // 0x63827765 + } + + public static interface CompanionDeviceManager.OnMessageReceivedListener { + method public void onMessageReceived(int, @NonNull byte[]); + } + + public static interface CompanionDeviceManager.OnTransportsChangedListener { + method public void onTransportsChanged(@NonNull java.util.List<android.companion.AssociationInfo>); + } + +} + package android.content { public abstract class ContentProvider implements android.content.ComponentCallbacks2 { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 3fb9fd931e239e5f1177d40de39d59111449f506..833d9c6d24208b9f04b5929a5124b282b5c77a7a 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -839,6 +839,7 @@ package android.companion { public final class CompanionDeviceManager { method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void enableSecureTransport(boolean); + field public static final int MESSAGE_REQUEST_PING = 1669362552; // 0x63807378 } public abstract class CompanionDeviceService extends android.app.Service { diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index e45fa1949f187f76ee20451a1caf47565e6dcfa5..69e1653eb8edc71dbebe525a66ea298417d92f14 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -20,7 +20,9 @@ import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMIN import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION; import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER; import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -208,6 +210,34 @@ public final class CompanionDeviceManager { */ public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION"; + /** + * Test message type without a designated callback. + * + * @hide + */ + @TestApi public static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN + /** + * Message header assigned to the remote authentication handshakes. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 0x63827765; // ?RMA + /** + * Message header assigned to the telecom context sync metadata. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS + /** + * Message header assigned to the permission restore request. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES + /** * Callback for applications to receive updates about and the outcome of * {@link AssociationRequest} issued via {@code associate()} call. @@ -797,28 +827,36 @@ public final class CompanionDeviceManager { } /** - * Listener for any changes to {@link com.android.server.companion.transport.Transport}. + * Listener for any changes to the list of attached transports. + * + * @see com.android.server.companion.transport.Transport * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public interface OnTransportsChangedListener { /** - * Invoked when a change occurs to any of the transports + * Invoked when a transport is attached or detached. * - * @param associations all the associations which have connected transports + * @param associations all the associations which have connected transports. */ void onTransportsChanged(@NonNull List<AssociationInfo> associations); } /** - * Register a listener for any changes to - * {@link com.android.server.companion.transport.Transport}. Your app will receive a callback to - * {@link OnTransportsChangedListener} immediately with all the existing transports. + * Adds a listener for any changes to the list of attached transports. + * {@link OnTransportsChangedListener#onTransportsChanged(List)} will be triggered with a list + * of existing transports when a transport is detached or a new transport is attached. + * + * @see com.android.server.companion.transport.Transport * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener( - @NonNull Executor executor, @NonNull OnTransportsChangedListener listener) { + @NonNull @CallbackExecutor Executor executor, + @NonNull OnTransportsChangedListener listener) { final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy( executor, listener); try { @@ -829,11 +867,14 @@ public final class CompanionDeviceManager { } /** - * Unregister a listener to stop receiving any changes to - * {@link com.android.server.companion.transport.Transport}. + * Removes the registered listener for any changes to the list of attached transports. + * + * @see com.android.server.companion.transport.Transport * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener( @NonNull OnTransportsChangedListener listener) { final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy( @@ -846,11 +887,16 @@ public final class CompanionDeviceManager { } /** - * Send a message to remote devices + * Sends a message to associated remote devices. The target associations must already have a + * connected transport. + * + * @see #attachSystemDataTransport(int, InputStream, OutputStream) * * @hide */ - public void sendMessage(int messageType, byte[] data, int[] associationIds) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) + public void sendMessage(int messageType, @NonNull byte[] data, @NonNull int[] associationIds) { try { mService.sendMessage(messageType, data, associationIds); } catch (RemoteException e) { @@ -859,28 +905,30 @@ public final class CompanionDeviceManager { } /** - * Listener when a message is received for the registered message type + * Listener that triggers a callback when a message is received through a connected transport. * * @see #addOnMessageReceivedListener(Executor, int, OnMessageReceivedListener) * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public interface OnMessageReceivedListener { /** - * Called when a message is received + * Called when a message is received. */ - void onMessageReceived(int associationId, byte[] data); + void onMessageReceived(int associationId, @NonNull byte[] data); } /** - * Register a listener to receive callbacks when a message is received by the given type - * - * @see com.android.server.companion.transport.Transport for supported message types + * Adds a listener to trigger callbacks when messages of given type are received. * * @hide */ - public void addOnMessageReceivedListener(@NonNull Executor executor, int messageType, - OnMessageReceivedListener listener) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) + public void addOnMessageReceivedListener( + @NonNull @CallbackExecutor Executor executor, int messageType, + @NonNull OnMessageReceivedListener listener) { final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy( executor, listener); try { @@ -891,15 +939,14 @@ public final class CompanionDeviceManager { } /** - * Unregister a listener to stop receiving callbacks when a message is received by the given - * type - * - * @see com.android.server.companion.transport.Transport for supported message types + * Removes the registered listener for received messages of given type. * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int messageType, - OnMessageReceivedListener listener) { + @NonNull OnMessageReceivedListener listener) { final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy( null, listener); try { diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index 2318e30016980d3c8806870b40c1069e123a73fc..463dba24fb5a888125fae848bca5ec78e85e193b 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -74,14 +74,19 @@ interface ICompanionDeviceManager { @EnforcePermission("MANAGE_COMPANION_DEVICES") void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId); + @EnforcePermission("USE_COMPANION_TRANSPORTS") void addOnTransportsChangedListener(IOnTransportsChangedListener listener); + @EnforcePermission("USE_COMPANION_TRANSPORTS") void removeOnTransportsChangedListener(IOnTransportsChangedListener listener); + @EnforcePermission("USE_COMPANION_TRANSPORTS") void sendMessage(int messageType, in byte[] data, in int[] associationIds); + @EnforcePermission("USE_COMPANION_TRANSPORTS") void addOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener); + @EnforcePermission("USE_COMPANION_TRANSPORTS") void removeOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener); void notifyDeviceAppeared(int associationId); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index baa47daa1251d9a9f0b13f530fd6e1e4d46fc916..b29a4e683a2412d263fca979d375cb589387e36c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5631,6 +5631,12 @@ android:description="@string/permdesc_deliverCompanionMessages" android:protectionLevel="normal" /> + <!-- @hide @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) + Allows an application to send and receive messages via CDM transports. + --> + <permission android:name="android.permission.USE_COMPANION_TRANSPORTS" + android:protectionLevel="signature|module" /> + <!-- Allows an application to create new companion device associations. @SystemApi @hide --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 368115b9904011785efcb9ccb7fb84603ae147af..215cc8ee3a9cab72909d50a161b2496e798edfdc 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -337,6 +337,7 @@ <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_WATCH" /> <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_GLASSES" /> <uses-permission android:name="android.permission.REQUEST_COMPANION_SELF_MANAGED" /> + <uses-permission android:name="android.permission.USE_COMPANION_TRANSPORTS" /> <uses-permission android:name="android.permission.MANAGE_APPOPS" /> <uses-permission android:name="android.permission.WATCH_APPOPS" /> diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index be52b1c8bb1b6aa90b43b3218b3a54700d142266..82d4d60b21d82678159a72fad265e75e25349303 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES; import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES; import static android.Manifest.permission.MANAGE_COMPANION_DEVICES; import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE; +import static android.Manifest.permission.USE_COMPANION_TRANSPORTS; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; import static android.content.pm.PackageManager.CERT_INPUT_SHA256; @@ -640,29 +641,44 @@ public class CompanionDeviceManagerService extends SystemService { } @Override + @EnforcePermission(USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener(IOnTransportsChangedListener listener) { + addOnTransportsChangedListener_enforcePermission(); + mTransportManager.addListener(listener); } @Override + @EnforcePermission(USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener(IOnTransportsChangedListener listener) { + removeOnTransportsChangedListener_enforcePermission(); + mTransportManager.removeListener(listener); } @Override + @EnforcePermission(USE_COMPANION_TRANSPORTS) public void sendMessage(int messageType, byte[] data, int[] associationIds) { + sendMessage_enforcePermission(); + mTransportManager.sendMessage(messageType, data, associationIds); } @Override + @EnforcePermission(USE_COMPANION_TRANSPORTS) public void addOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener) { + addOnMessageReceivedListener_enforcePermission(); + mTransportManager.addListener(messageType, listener); } @Override + @EnforcePermission(USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener) { + removeOnMessageReceivedListener_enforcePermission(); + mTransportManager.removeListener(messageType, listener); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java index c79466f350faf8305f9a815611f3b3244a50680f..94cede80aa3b2f05837eeda1c7f18acdbf949476 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java @@ -16,6 +16,8 @@ package com.android.server.companion; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC; + import android.companion.AssociationInfo; import android.companion.ContextSyncMessage; import android.companion.Telecom; @@ -30,7 +32,6 @@ import com.android.server.companion.datatransfer.contextsync.BitmapUtils; import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController; import com.android.server.companion.presence.CompanionDevicePresenceMonitor; import com.android.server.companion.transport.CompanionTransportManager; -import com.android.server.companion.transport.Transport; import java.io.PrintWriter; import java.util.List; @@ -135,7 +136,7 @@ class CompanionDeviceShellCommand extends ShellCommand { case "send-context-sync-empty-message": { associationId = getNextIntArgRequired(); mTransportManager.createEmulatedTransport(associationId) - .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + .processMessage(MESSAGE_REQUEST_CONTEXT_SYNC, /* sequence= */ 0, CrossDeviceSyncController.createEmptyMessage()); break; @@ -147,7 +148,7 @@ class CompanionDeviceShellCommand extends ShellCommand { String address = getNextArgRequired(); String facilitator = getNextArgRequired(); mTransportManager.createEmulatedTransport(associationId) - .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + .processMessage(MESSAGE_REQUEST_CONTEXT_SYNC, /* sequence= */ 0, CrossDeviceSyncController.createCallCreateMessage(callId, address, facilitator)); @@ -159,7 +160,7 @@ class CompanionDeviceShellCommand extends ShellCommand { String callId = getNextArgRequired(); int control = getNextIntArgRequired(); mTransportManager.createEmulatedTransport(associationId) - .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + .processMessage(MESSAGE_REQUEST_CONTEXT_SYNC, /* sequence= */ 0, CrossDeviceSyncController.createCallControlMessage(callId, control)); @@ -184,7 +185,7 @@ class CompanionDeviceShellCommand extends ShellCommand { } pos.end(telecomToken); mTransportManager.createEmulatedTransport(associationId) - .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + .processMessage(MESSAGE_REQUEST_CONTEXT_SYNC, /* sequence= */ 0, pos.getBytes()); break; } @@ -246,7 +247,7 @@ class CompanionDeviceShellCommand extends ShellCommand { pos.end(callsToken); pos.end(telecomToken); mTransportManager.createEmulatedTransport(associationId) - .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + .processMessage(MESSAGE_REQUEST_CONTEXT_SYNC, /* sequence= */ 0, pos.getBytes()); break; } 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 7af4957213ee94a509fa3d94dc12a3dc61117982..13f41ed2ebb1c9b5e95faad29a55380309e92f65 100644 --- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java +++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java @@ -19,10 +19,10 @@ package com.android.server.companion.datatransfer; import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_PERMISSION_RESTORE; import static android.content.ComponentName.createRelative; import static com.android.server.companion.Utils.prepareForIpc; -import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE; import android.annotation.NonNull; import android.annotation.Nullable; diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java index 9bd5af956a6ee48d5118e1aced3a560d654d4ca6..ad1eff8cebad4656f31e623cc8ccd889baf6730e 100644 --- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java +++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java @@ -16,7 +16,7 @@ package com.android.server.companion.datatransfer.contextsync; -import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_CONTEXT_SYNC; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC; import android.app.admin.DevicePolicyManager; import android.companion.AssociationInfo; diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java index 41867f9a6c223114d4034ff0dca49bdfe597cb5f..f648f09ea43db24e2bbcf9e8627effbd7d97d41a 100644 --- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java +++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java @@ -16,7 +16,7 @@ package com.android.server.companion.transport; -import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_PERMISSION_RESTORE; import android.annotation.NonNull; import android.annotation.SuppressLint; diff --git a/services/companion/java/com/android/server/companion/transport/Transport.java b/services/companion/java/com/android/server/companion/transport/Transport.java index 5af3b98d71ccd45cb7f721c32a7ae2f640676416..32d4061db1f7797524934b43b2fe8629e6418cdf 100644 --- a/services/companion/java/com/android/server/companion/transport/Transport.java +++ b/services/companion/java/com/android/server/companion/transport/Transport.java @@ -16,6 +16,11 @@ package com.android.server.companion.transport; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_PERMISSION_RESTORE; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_PING; +import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_REMOTE_AUTHENTICATION; + import android.annotation.NonNull; import android.companion.IOnMessageReceivedListener; import android.content.Context; @@ -45,10 +50,6 @@ public abstract class Transport { protected static final String TAG = "CDM_CompanionTransport"; protected static final boolean DEBUG = Build.IS_DEBUGGABLE; - static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN - public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS - public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES - static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI @@ -181,7 +182,8 @@ public abstract class Transport { sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data); break; } - case MESSAGE_REQUEST_CONTEXT_SYNC: { + case MESSAGE_REQUEST_CONTEXT_SYNC: + case MESSAGE_REQUEST_REMOTE_AUTHENTICATION: { callback(message, data); sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE); break;