diff options
3 files changed, 146 insertions, 0 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 05b38a562e29..4edf74c55f9f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8206,6 +8206,14 @@ </intent-filter> </service> + <service android:name="com.android.server.companion.datatransfer.contextsync.CallMetadataSyncConnectionService" + android:permission="android.permission.BIND_CONNECTION_SERVICE" + android:exported="true"> + <intent-filter> + <action android:name="android.telecom.ConnectionService"/> + </intent-filter> + </service> + <provider android:name="com.android.server.textclassifier.IconsContentProvider" android:authorities="com.android.textclassifier.icons" diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java new file mode 100644 index 000000000000..19d8b8783d81 --- /dev/null +++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion.datatransfer.contextsync; + +import android.content.ComponentName; +import android.telecom.ConnectionService; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** Service for Telecom to bind to when call metadata is synced between devices. */ +public class CallMetadataSyncConnectionService extends ConnectionService { + + private TelecomManager mTelecomManager; + private final Map<String, PhoneAccountHandle> mPhoneAccountHandles = new HashMap<>(); + + @Override + public void onCreate() { + super.onCreate(); + mTelecomManager = getSystemService(TelecomManager.class); + } + + /** + * Registers a {@link android.telecom.PhoneAccount} for a given call-capable app on the synced + * device. + */ + public void registerPhoneAccount(String packageName, String humanReadableAppName) { + final PhoneAccount phoneAccount = createPhoneAccount(packageName, humanReadableAppName); + if (phoneAccount != null) { + mTelecomManager.registerPhoneAccount(phoneAccount); + mTelecomManager.enablePhoneAccount(mPhoneAccountHandles.get(packageName), true); + } + } + + /** + * Unregisters a {@link android.telecom.PhoneAccount} for a given call-capable app on the synced + * device. + */ + public void unregisterPhoneAccount(String packageName) { + mTelecomManager.unregisterPhoneAccount(mPhoneAccountHandles.remove(packageName)); + } + + @VisibleForTesting + PhoneAccount createPhoneAccount(String packageName, String humanReadableAppName) { + if (mPhoneAccountHandles.containsKey(packageName)) { + // Already exists! + return null; + } + final PhoneAccountHandle handle = new PhoneAccountHandle( + new ComponentName(this, CallMetadataSyncConnectionService.class), + UUID.randomUUID().toString()); + mPhoneAccountHandles.put(packageName, handle); + return new PhoneAccount.Builder(handle, humanReadableAppName) + .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER + | PhoneAccount.CAPABILITY_SELF_MANAGED).build(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionServiceTest.java new file mode 100644 index 000000000000..3ed95eb3c878 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionServiceTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion.datatransfer.contextsync; + +import static com.google.common.truth.Truth.assertWithMessage; + +import android.platform.test.annotations.Presubmit; +import android.telecom.PhoneAccount; +import android.testing.AndroidTestingRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@RunWith(AndroidTestingRunner.class) +public class CallMetadataSyncConnectionServiceTest { + + private CallMetadataSyncConnectionService mSyncConnectionService; + + @Before + public void setUp() throws Exception { + mSyncConnectionService = new CallMetadataSyncConnectionService() { + @Override + public String getPackageName() { + return "android"; + } + }; + } + + @Test + public void createPhoneAccount_success() { + final PhoneAccount phoneAccount = mSyncConnectionService.createPhoneAccount( + "com.google.test", "Test App"); + assertWithMessage("Could not create phone account").that(phoneAccount).isNotNull(); + } + + @Test + public void createPhoneAccount_alreadyExists_doesNotCreateAnother() { + final PhoneAccount phoneAccount = mSyncConnectionService.createPhoneAccount( + "com.google.test", "Test App"); + final PhoneAccount phoneAccount2 = mSyncConnectionService.createPhoneAccount( + "com.google.test", "Test App #2"); + assertWithMessage("Could not create phone account").that(phoneAccount).isNotNull(); + assertWithMessage("Unexpectedly created second phone account").that(phoneAccount2).isNull(); + } +} |