diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index c8db662a7f49e..7975e49541a06 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -922,7 +922,8 @@ public class CompanionDeviceManagerService extends SystemService { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, - mDevicePresenceMonitor, mTransportManager, mSystemDataTransferRequestStore) + mDevicePresenceMonitor, mTransportManager, mSystemDataTransferRequestStore, + 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 669686adddb89..c511429a37d86 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java @@ -17,14 +17,19 @@ package com.android.server.companion; import android.companion.AssociationInfo; +import android.companion.ContextSyncMessage; +import android.companion.Telecom; import android.companion.datatransfer.PermissionSyncRequest; import android.net.MacAddress; 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.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; @@ -33,22 +38,25 @@ class CompanionDeviceShellCommand extends ShellCommand { private static final String TAG = "CDM_CompanionDeviceShellCommand"; private final CompanionDeviceManagerService mService; - private final AssociationStore mAssociationStore; + private final AssociationStoreImpl mAssociationStore; private final CompanionDevicePresenceMonitor mDevicePresenceMonitor; private final CompanionTransportManager mTransportManager; private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; + private final AssociationRequestsProcessor mAssociationRequestsProcessor; CompanionDeviceShellCommand(CompanionDeviceManagerService service, - AssociationStore associationStore, + AssociationStoreImpl associationStore, CompanionDevicePresenceMonitor devicePresenceMonitor, CompanionTransportManager transportManager, - SystemDataTransferRequestStore systemDataTransferRequestStore) { + SystemDataTransferRequestStore systemDataTransferRequestStore, + AssociationRequestsProcessor associationRequestsProcessor) { mService = service; mAssociationStore = associationStore; mDevicePresenceMonitor = devicePresenceMonitor; mTransportManager = transportManager; mSystemDataTransferRequestStore = systemDataTransferRequestStore; + mAssociationRequestsProcessor = associationRequestsProcessor; } @Override @@ -117,12 +125,107 @@ class CompanionDeviceShellCommand extends ShellCommand { } break; - case "create-dummy-transport": + case "create-emulated-transport": // This command creates a RawTransport in order to test Transport listeners associationId = getNextIntArgRequired(); - mTransportManager.createDummyTransport(associationId); + mTransportManager.createEmulatedTransport(associationId); break; + case "send-context-sync-empty-message": { + associationId = getNextIntArgRequired(); + mTransportManager.createEmulatedTransport(associationId) + .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + /* sequence= */ 0, + CrossDeviceSyncController.createEmptyMessage()); + break; + } + + case "send-context-sync-call-create-message": { + associationId = getNextIntArgRequired(); + String callId = getNextArgRequired(); + String address = getNextArgRequired(); + String facilitator = getNextArgRequired(); + mTransportManager.createEmulatedTransport(associationId) + .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + /* sequence= */ 0, + CrossDeviceSyncController.createCallCreateMessage(callId, + address, facilitator)); + break; + } + + case "send-context-sync-call-control-message": { + associationId = getNextIntArgRequired(); + String callId = getNextArgRequired(); + int control = getNextIntArgRequired(); + mTransportManager.createEmulatedTransport(associationId) + .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + /* sequence= */ 0, + CrossDeviceSyncController.createCallControlMessage(callId, + control)); + break; + } + + case "send-context-sync-call-facilitators-message": { + associationId = getNextIntArgRequired(); + int numberOfFacilitators = getNextIntArgRequired(); + final ProtoOutputStream pos = new ProtoOutputStream(); + pos.write(ContextSyncMessage.VERSION, 1); + final long telecomToken = pos.start(ContextSyncMessage.TELECOM); + for (int i = 0; i < numberOfFacilitators; i++) { + final long facilitatorsToken = pos.start(Telecom.FACILITATORS); + pos.write(Telecom.CallFacilitator.NAME, "Call Facilitator App #" + i); + pos.write(Telecom.CallFacilitator.IDENTIFIER, "com.android.test" + i); + pos.end(facilitatorsToken); + } + pos.end(telecomToken); + mTransportManager.createEmulatedTransport(associationId) + .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + /* sequence= */ 0, pos.getBytes()); + break; + } + + case "send-context-sync-call-message": { + associationId = getNextIntArgRequired(); + String callId = getNextArgRequired(); + String facilitatorId = getNextArgRequired(); + final ProtoOutputStream pos = new ProtoOutputStream(); + pos.write(ContextSyncMessage.VERSION, 1); + final long telecomToken = pos.start(ContextSyncMessage.TELECOM); + final long callsToken = pos.start(Telecom.CALLS); + pos.write(Telecom.Call.ID, callId); + final long originToken = pos.start(Telecom.Call.ORIGIN); + pos.write(Telecom.Call.Origin.CALLER_ID, "Caller Name"); + final long facilitatorToken = pos.start( + Telecom.Request.CreateAction.FACILITATOR); + pos.write(Telecom.CallFacilitator.NAME, "Test App Name"); + pos.write(Telecom.CallFacilitator.IDENTIFIER, facilitatorId); + pos.end(facilitatorToken); + pos.end(originToken); + pos.write(Telecom.Call.STATUS, Telecom.Call.RINGING); + pos.write(Telecom.Call.CONTROLS, Telecom.ACCEPT); + pos.write(Telecom.Call.CONTROLS, Telecom.REJECT); + pos.end(callsToken); + pos.end(telecomToken); + mTransportManager.createEmulatedTransport(associationId) + .processMessage(Transport.MESSAGE_REQUEST_CONTEXT_SYNC, + /* sequence= */ 0, pos.getBytes()); + break; + } + + case "disable-context-sync": { + associationId = getNextIntArgRequired(); + int flag = getNextIntArgRequired(); + mAssociationRequestsProcessor.disableSystemDataSync(associationId, flag); + break; + } + + case "enable-context-sync": { + associationId = getNextIntArgRequired(); + int flag = getNextIntArgRequired(); + mAssociationRequestsProcessor.enableSystemDataSync(associationId, flag); + break; + } + case "allow-permission-sync": { int userId = getNextIntArgRequired(); associationId = getNextIntArgRequired(); @@ -202,7 +305,7 @@ class CompanionDeviceShellCommand extends ShellCommand { pw.println(" \"debug.cdm.cdmservice.cleanup_time_window\" system property). "); pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY."); - pw.println(" create-dummy-transport "); - pw.println(" Create a dummy RawTransport for testing puspose only"); + pw.println(" create-emulated-transport "); + pw.println(" Create an EmulatedTransport for testing purposes only"); } } 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 a3e095e4475b5..17bdb6085c453 100644 --- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java +++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java @@ -360,15 +360,42 @@ public class CompanionTransportManager { /** * For testing purpose only. * - * Create a dummy RawTransport and notify onTransportChanged listeners. + * Create an emulated RawTransport and notify onTransportChanged listeners. */ - public void createDummyTransport(int associationId) { + public EmulatedTransport createEmulatedTransport(int associationId) { synchronized (mTransports) { FileDescriptor fd = new FileDescriptor(); ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd); - Transport transport = new RawTransport(associationId, pfd, mContext); + EmulatedTransport transport = new EmulatedTransport(associationId, pfd, mContext); + addMessageListenersToTransport(transport); mTransports.put(associationId, transport); notifyOnTransportsChanged(); + return transport; + } + } + + /** + * For testing purposes only. + * + * Emulates a transport for incoming messages but black-holes all messages sent back through it. + */ + public static class EmulatedTransport extends RawTransport { + + EmulatedTransport(int associationId, ParcelFileDescriptor fd, Context context) { + super(associationId, fd, context); + } + + /** Process an incoming message for testing purposes. */ + public void processMessage(int messageType, int sequence, byte[] data) throws IOException { + handleMessage(messageType, sequence, data); + } + + @Override + protected void sendMessage(int messageType, int sequence, @NonNull byte[] data) + throws IOException { + Slog.e(TAG, "Black-holing emulated message type 0x" + Integer.toHexString(messageType) + + " sequence " + sequence + " length " + data.length + + " to association " + mAssociationId); } }