diff --git a/core/api/current.txt b/core/api/current.txt index 29538ab0729fc..077ddd1785807 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -79,6 +79,7 @@ package android { field public static final String CONTROL_LOCATION_UPDATES = "android.permission.CONTROL_LOCATION_UPDATES"; field public static final String DELETE_CACHE_FILES = "android.permission.DELETE_CACHE_FILES"; field public static final String DELETE_PACKAGES = "android.permission.DELETE_PACKAGES"; + field public static final String DELIVER_COMPANION_MESSAGES = "android.permission.DELIVER_COMPANION_MESSAGES"; field public static final String DIAGNOSTIC = "android.permission.DIAGNOSTIC"; field public static final String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD"; field public static final String DUMP = "android.permission.DUMP"; @@ -9885,6 +9886,8 @@ package android.companion { method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); method @MainThread public abstract void onDeviceAppeared(@NonNull String); method @MainThread public abstract void onDeviceDisappeared(@NonNull String); + method @MainThread public void onSendMessage(int, int, @NonNull byte[]); + method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public final void receiveMessage(int, int, @NonNull byte[]); field public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService"; } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 6a527a555a26f..a9e9ba550696e 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -444,6 +444,35 @@ public final class CompanionDeviceManager { } } + /** + * Dispatch received message to system for processing. + * + *
Messages received from {@link CompanionDeviceService#onSendMessage}, which is implemented + * on another device, need to be dispatched to system for processing.
+ * + *Calling app must declare uses-permission + * {@link android.Manifest.permission#DELIVER_COMPANION_MESSAGES}
+ * + * @param messageId id of the message + * @param associationId association id of the associated device where data is coming from + * @param message message received from the associated device + * + * @throws DeviceNotAssociatedException if the given device was not previously associated with + * this app + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) + public void receiveMessage(int messageId, int associationId, @NonNull byte[] message) + throws DeviceNotAssociatedException { + try { + mService.receiveMessage(messageId, associationId, message); + } catch (RemoteException e) { + ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class); + throw e.rethrowFromSystemServer(); + } + } + /** * Associates given device with given app for the given user directly, without UI prompt. * diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java index 56639ea36bf6a..86d6b23c44938 100644 --- a/core/java/android/companion/CompanionDeviceService.java +++ b/core/java/android/companion/CompanionDeviceService.java @@ -20,6 +20,7 @@ package android.companion; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.app.Service; import android.content.Intent; import android.os.Handler; @@ -86,6 +87,36 @@ public abstract class CompanionDeviceService extends Service { @MainThread public abstract void onDeviceDisappeared(@NonNull String address); + /** + * Called by system whenever the system tries to send a message to an associated device. + * + * @param messageId system assigned id of the message to be sent + * @param associationId association id of the associated device + * @param message message to be sent + */ + @MainThread + public void onSendMessage(int messageId, int associationId, @NonNull byte[] message) { + // do nothing. Companion apps can override this function for system to send messages. + } + + /** + * Called when there's message received from an associated device, which needs to be dispatched + * to system for processing. + * + *Calling app must declare uses-permission + * {@link android.Manifest.permission#DELIVER_COMPANION_MESSAGES}
+ * + * @param messageId id of the message + * @param associationId id of the associated device + * @param message messaged received from the associated device + */ + @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) + public final void receiveMessage(int messageId, int associationId, @NonNull byte[] message) { + CompanionDeviceManager companionDeviceManager = + getSystemService(CompanionDeviceManager.class); + companionDeviceManager.receiveMessage(messageId, associationId, message); + } + @Nullable @Override public final IBinder onBind(@NonNull Intent intent) { @@ -112,5 +143,18 @@ public abstract class CompanionDeviceService extends Service { CompanionDeviceService::onDeviceDisappeared, CompanionDeviceService.this, address)); } + + public void onSendMessage(int messageId, int associationId, @NonNull byte[] message) { + Handler.getMain().sendMessage(PooledLambda.obtainMessage( + CompanionDeviceService::onSendMessage, + CompanionDeviceService.this, messageId, associationId, message)); + } + + public final void receiveMessage(int messageId, int associationId, + @NonNull byte[] message) { + Handler.getMain().sendMessage(PooledLambda.obtainMessage( + CompanionDeviceService::receiveMessage, + CompanionDeviceService.this, messageId, associationId, message)); + } } } diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index d113b929db383..9c2bcf2092fd4 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -54,4 +54,6 @@ interface ICompanionDeviceManager { void createAssociation(in String packageName, in String macAddress, int userId, in byte[] certificate); + + void receiveMessage(in int messageId, in int associationId, in byte[] message); } diff --git a/core/java/android/companion/ICompanionDeviceService.aidl b/core/java/android/companion/ICompanionDeviceService.aidl index f3977ca4af6fe..921c12467605e 100644 --- a/core/java/android/companion/ICompanionDeviceService.aidl +++ b/core/java/android/companion/ICompanionDeviceService.aidl @@ -16,14 +16,9 @@ package android.companion; -import android.app.PendingIntent; -import android.companion.IFindDeviceCallback; -import android.companion.Association; -import android.companion.AssociationRequest; -import android.content.ComponentName; - /** @hide */ oneway interface ICompanionDeviceService { void onDeviceAppeared(in String address); void onDeviceDisappeared(in String address); + void onSendMessage(in int messageId, in int associationId, in byte[] message); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8c28aec45d022..17c495dca72fe 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4331,6 +4331,11 @@