Merge changes Ib48cc2b8,I3f0a12f1 into main am: 2c2c707d6c am: b41794b0f4
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2778286
Change-Id: I7c705f222e26cf5e9deb504bd88f86faeefe0f05
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index e917464..9757daa 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -22,23 +22,23 @@
// different value depending on the branch.
java_defaults {
name: "ConnectivityNextEnableDefaults",
- enabled: false,
+ enabled: true,
}
java_defaults {
name: "NetworkStackApiShimSettingsForCurrentBranch",
// API shims to include in the networking modules built from the branch. Branches that disable
// the "next" targets must use stable shims (latest stable API level) instead of current shims
// (X_current API level).
- static_libs: ["NetworkStackApiStableShims"],
+ static_libs: ["NetworkStackApiCurrentShims"],
}
apex_defaults {
name: "ConnectivityApexDefaults",
// Tethering app to include in the AOSP apex. Branches that disable the "next" targets may use
// a stable tethering app instead, but will generally override the AOSP apex to use updatable
// package names and keys, so that apex will be unused anyway.
- apps: ["Tethering"], // Replace to "Tethering" if ConnectivityNextEnableDefaults is false.
+ apps: ["TetheringNext"], // Replace to "Tethering" if ConnectivityNextEnableDefaults is false.
}
-enable_tethering_next_apex = false
+enable_tethering_next_apex = true
// This is a placeholder comment to avoid merge conflicts
// as the above target may have different "enabled" values
// depending on the branch
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index 2f7db87..d177ea9 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -19,12 +19,12 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-framework_remoteauth_srcs = [":framework-remoteauth-java-sources-udc-compat"]
-framework_remoteauth_api_srcs = [":framework-remoteauth-java-sources"]
+framework_remoteauth_srcs = [":framework-remoteauth-java-sources"]
+framework_remoteauth_api_srcs = []
java_defaults {
name: "enable-remoteauth-targets",
- enabled: false,
+ enabled: true,
}
// Include build rules from Sources.bp
diff --git a/framework-t/api/system-lint-baseline.txt b/framework-t/api/system-lint-baseline.txt
index 9baf991..c6055f6 100644
--- a/framework-t/api/system-lint-baseline.txt
+++ b/framework-t/api/system-lint-baseline.txt
@@ -5,3 +5,149 @@
GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
Methods must not throw generic exceptions (`java.lang.Throwable`)
+
+
+UnflaggedApi: android.nearby.CredentialElement#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.CredentialElement.equals(Object)
+UnflaggedApi: android.nearby.CredentialElement#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.CredentialElement.hashCode()
+UnflaggedApi: android.nearby.DataElement#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.DataElement.equals(Object)
+UnflaggedApi: android.nearby.DataElement#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.DataElement.hashCode()
+UnflaggedApi: android.nearby.NearbyDevice#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.NearbyDevice.equals(Object)
+UnflaggedApi: android.nearby.NearbyDevice#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.NearbyDevice.hashCode()
+UnflaggedApi: android.nearby.NearbyDevice#toString():
+ New API must be flagged with @FlaggedApi: method android.nearby.NearbyDevice.toString()
+UnflaggedApi: android.nearby.OffloadCapability#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.OffloadCapability.equals(Object)
+UnflaggedApi: android.nearby.OffloadCapability#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.OffloadCapability.hashCode()
+UnflaggedApi: android.nearby.OffloadCapability#toString():
+ New API must be flagged with @FlaggedApi: method android.nearby.OffloadCapability.toString()
+UnflaggedApi: android.nearby.PresenceCredential#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.PresenceCredential.equals(Object)
+UnflaggedApi: android.nearby.PresenceCredential#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.PresenceCredential.hashCode()
+UnflaggedApi: android.nearby.PublicCredential#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.PublicCredential.equals(Object)
+UnflaggedApi: android.nearby.PublicCredential#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.PublicCredential.hashCode()
+UnflaggedApi: android.nearby.ScanRequest#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.nearby.ScanRequest.equals(Object)
+UnflaggedApi: android.nearby.ScanRequest#hashCode():
+ New API must be flagged with @FlaggedApi: method android.nearby.ScanRequest.hashCode()
+UnflaggedApi: android.nearby.ScanRequest#toString():
+ New API must be flagged with @FlaggedApi: method android.nearby.ScanRequest.toString()
+UnflaggedApi: android.net.EthernetNetworkManagementException#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.net.EthernetNetworkManagementException.equals(Object)
+UnflaggedApi: android.net.EthernetNetworkManagementException#hashCode():
+ New API must be flagged with @FlaggedApi: method android.net.EthernetNetworkManagementException.hashCode()
+UnflaggedApi: android.net.EthernetNetworkUpdateRequest#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.net.EthernetNetworkUpdateRequest.equals(Object)
+UnflaggedApi: android.net.EthernetNetworkUpdateRequest#hashCode():
+ New API must be flagged with @FlaggedApi: method android.net.EthernetNetworkUpdateRequest.hashCode()
+UnflaggedApi: android.net.EthernetNetworkUpdateRequest#toString():
+ New API must be flagged with @FlaggedApi: method android.net.EthernetNetworkUpdateRequest.toString()
+UnflaggedApi: android.net.IpSecManager.IpSecTunnelInterface#finalize():
+ New API must be flagged with @FlaggedApi: method android.net.IpSecManager.IpSecTunnelInterface.finalize()
+UnflaggedApi: android.net.IpSecManager.IpSecTunnelInterface#toString():
+ New API must be flagged with @FlaggedApi: method android.net.IpSecManager.IpSecTunnelInterface.toString()
+UnflaggedApi: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
+ New API must be flagged with @FlaggedApi: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
+UnflaggedApi: android.net.NetworkStats.Entry#toString():
+ New API must be flagged with @FlaggedApi: method android.net.NetworkStats.Entry.toString()
+UnflaggedApi: android.net.nsd.NsdManager#registerOffloadEngine(String, long, long, java.util.concurrent.Executor, android.net.nsd.OffloadEngine):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.NsdManager.registerOffloadEngine(String,long,long,java.util.concurrent.Executor,android.net.nsd.OffloadEngine)
+UnflaggedApi: android.net.nsd.NsdManager#unregisterOffloadEngine(android.net.nsd.OffloadEngine):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.NsdManager.unregisterOffloadEngine(android.net.nsd.OffloadEngine)
+UnflaggedApi: android.net.nsd.OffloadEngine:
+ New API must be flagged with @FlaggedApi: class android.net.nsd.OffloadEngine
+UnflaggedApi: android.net.nsd.OffloadEngine#OFFLOAD_CAPABILITY_BYPASS_MULTICAST_LOCK:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadEngine.OFFLOAD_CAPABILITY_BYPASS_MULTICAST_LOCK
+UnflaggedApi: android.net.nsd.OffloadEngine#OFFLOAD_TYPE_FILTER_QUERIES:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadEngine.OFFLOAD_TYPE_FILTER_QUERIES
+UnflaggedApi: android.net.nsd.OffloadEngine#OFFLOAD_TYPE_FILTER_REPLIES:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadEngine.OFFLOAD_TYPE_FILTER_REPLIES
+UnflaggedApi: android.net.nsd.OffloadEngine#OFFLOAD_TYPE_REPLY:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadEngine.OFFLOAD_TYPE_REPLY
+UnflaggedApi: android.net.nsd.OffloadEngine#onOffloadServiceRemoved(android.net.nsd.OffloadServiceInfo):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadEngine.onOffloadServiceRemoved(android.net.nsd.OffloadServiceInfo)
+UnflaggedApi: android.net.nsd.OffloadEngine#onOffloadServiceUpdated(android.net.nsd.OffloadServiceInfo):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadEngine.onOffloadServiceUpdated(android.net.nsd.OffloadServiceInfo)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo:
+ New API must be flagged with @FlaggedApi: class android.net.nsd.OffloadServiceInfo
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#CONTENTS_FILE_DESCRIPTOR:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.CONTENTS_FILE_DESCRIPTOR
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#CREATOR:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.CREATOR
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#OffloadServiceInfo(android.net.nsd.OffloadServiceInfo.Key, java.util.List<java.lang.String>, String, byte[], int, long):
+ New API must be flagged with @FlaggedApi: constructor android.net.nsd.OffloadServiceInfo(android.net.nsd.OffloadServiceInfo.Key,java.util.List<java.lang.String>,String,byte[],int,long)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#PARCELABLE_STABILITY_LOCAL:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.PARCELABLE_STABILITY_LOCAL
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#PARCELABLE_STABILITY_VINTF:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.PARCELABLE_STABILITY_VINTF
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#PARCELABLE_WRITE_RETURN_VALUE:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.PARCELABLE_WRITE_RETURN_VALUE
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#describeContents():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.describeContents()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.equals(Object)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getHostname():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getHostname()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getKey():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getKey()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getOffloadPayload():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getOffloadPayload()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getOffloadType():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getOffloadType()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getPriority():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getPriority()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#getSubtypes():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.getSubtypes()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#hashCode():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.hashCode()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#toString():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.toString()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo#writeToParcel(android.os.Parcel, int):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.writeToParcel(android.os.Parcel,int)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key:
+ New API must be flagged with @FlaggedApi: class android.net.nsd.OffloadServiceInfo.Key
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#CONTENTS_FILE_DESCRIPTOR:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.Key.CONTENTS_FILE_DESCRIPTOR
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#CREATOR:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.Key.CREATOR
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#Key(String, String):
+ New API must be flagged with @FlaggedApi: constructor android.net.nsd.OffloadServiceInfo.Key(String,String)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#PARCELABLE_STABILITY_LOCAL:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.Key.PARCELABLE_STABILITY_LOCAL
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#PARCELABLE_STABILITY_VINTF:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.Key.PARCELABLE_STABILITY_VINTF
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#PARCELABLE_WRITE_RETURN_VALUE:
+ New API must be flagged with @FlaggedApi: field android.net.nsd.OffloadServiceInfo.Key.PARCELABLE_WRITE_RETURN_VALUE
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#describeContents():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.describeContents()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#equals(Object):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.equals(Object)
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#getServiceName():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.getServiceName()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#getServiceType():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.getServiceType()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#hashCode():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.hashCode()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#toString():
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.toString()
+UnflaggedApi: android.net.nsd.OffloadServiceInfo.Key#writeToParcel(android.os.Parcel, int):
+ New API must be flagged with @FlaggedApi: method android.net.nsd.OffloadServiceInfo.Key.writeToParcel(android.os.Parcel,int)
+UnflaggedApi: android.net.thread.ThreadNetworkController:
+ New API must be flagged with @FlaggedApi: class android.net.thread.ThreadNetworkController
+UnflaggedApi: android.net.thread.ThreadNetworkController#THREAD_VERSION_1_3:
+ New API must be flagged with @FlaggedApi: field android.net.thread.ThreadNetworkController.THREAD_VERSION_1_3
+UnflaggedApi: android.net.thread.ThreadNetworkController#getThreadVersion():
+ New API must be flagged with @FlaggedApi: method android.net.thread.ThreadNetworkController.getThreadVersion()
+UnflaggedApi: android.net.thread.ThreadNetworkManager:
+ New API must be flagged with @FlaggedApi: class android.net.thread.ThreadNetworkManager
+UnflaggedApi: android.net.thread.ThreadNetworkManager#getAllThreadNetworkControllers():
+ New API must be flagged with @FlaggedApi: method android.net.thread.ThreadNetworkManager.getAllThreadNetworkControllers()
diff --git a/framework/Android.bp b/framework/Android.bp
index 655a32c..182c558 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -22,10 +22,6 @@
// In the branch which does not support FlaggedAPI, use this default to ignore the annotated APIs.
java_defaults {
name: "FlaggedApiDefaults",
- api_dir: "udc-extended-api",
- droiddoc_options: [
- "--hide-annotation android.annotation.FlaggedApi",
- ],
}
// The above variables may have different values
diff --git a/remoteauth/framework-udc-compat/Android.bp b/remoteauth/framework-udc-compat/Android.bp
deleted file mode 100644
index 799ffd0..0000000
--- a/remoteauth/framework-udc-compat/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// Sources included in the framework-connectivity jar for compatibility
-// builds in udc branches. They are only compatibility stubs to make
-// the module build, since remoteauth is not available on U.
-filegroup {
- name: "framework-remoteauth-java-sources-udc-compat",
- srcs: [
- "java/**/*.java",
- ],
- path: "java",
- visibility: [
- "//packages/modules/Connectivity/framework-t:__subpackages__",
- ],
-}
-
diff --git a/remoteauth/framework-udc-compat/java/README.md b/remoteauth/framework-udc-compat/java/README.md
deleted file mode 100644
index 7a01308..0000000
--- a/remoteauth/framework-udc-compat/java/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# RemoteAuth udc compatibility framework files
-
-This directory is created to contain compatibility implementations of RemoteAuth classes for builds
-in udc branches.
diff --git a/remoteauth/service-udc-compat/Android.bp b/remoteauth/service-udc-compat/Android.bp
deleted file mode 100644
index 69c667d..0000000
--- a/remoteauth/service-udc-compat/Android.bp
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// Compatibility library included in the service-connectivity jar for
-// builds in udc branches. It only contains compatibility stubs to make
-// the module build, since remoteauth is not available on U.
-
-// Main lib for remoteauth services.
-java_library {
- name: "service-remoteauth-pre-jarjar-udc-compat",
- srcs: ["java/**/*.java"],
-
- defaults: [
- "framework-system-server-module-defaults"
- ],
- libs: [
- "androidx.annotation_annotation",
- "error_prone_annotations",
- ],
- sdk_version: "system_server_current",
- // This is included in service-connectivity which is 30+
- min_sdk_version: "30",
-
- dex_preopt: {
- enabled: false,
- app_image: false,
- },
- visibility: [
- "//packages/modules/Connectivity/service",
- "//packages/modules/Connectivity/service-t",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
diff --git a/remoteauth/service-udc-compat/java/com/android/server/remoteauth/RemoteAuthService.java b/remoteauth/service-udc-compat/java/com/android/server/remoteauth/RemoteAuthService.java
deleted file mode 100644
index ac4fde1..0000000
--- a/remoteauth/service-udc-compat/java/com/android/server/remoteauth/RemoteAuthService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 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.remoteauth;
-
-import android.os.Binder;
-import android.content.Context;
-
-/** Compatibility stub for RemoteAuthService in udc branch builds. */
-public class RemoteAuthService extends Binder {
- public static final String SERVICE_NAME = "remote_auth";
- public RemoteAuthService(Context context) {
- throw new UnsupportedOperationException("RemoteAuthService is not supported in this build");
- }
-}
diff --git a/remoteauth/service/Android.bp b/remoteauth/service/Android.bp
index 98ed2b2..8330efc 100644
--- a/remoteauth/service/Android.bp
+++ b/remoteauth/service/Android.bp
@@ -33,6 +33,7 @@
libs: [
"androidx.annotation_annotation",
"framework-bluetooth",
+ "framework-connectivity",
"error_prone_annotations",
"framework-configinfrastructure",
"framework-connectivity-pre-jarjar",
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectionInfo.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectionInfo.java
index 8bfdd36..d2a828c 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectionInfo.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectionInfo.java
@@ -34,11 +34,11 @@
// TODO(b/295407748): Change to use @DataClass.
// TODO(b/296625303): Change to VANILLA_ICE_CREAM when AssociationInfo is available in V.
@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public final class CdmConnectionInfo extends ConnectionInfo {
+public final class CdmConnectionInfo extends ConnectionInfo<AssociationInfo> {
@NonNull private final AssociationInfo mAssociationInfo;
public CdmConnectionInfo(int connectionId, @NonNull AssociationInfo associationInfo) {
- super(connectionId);
+ super(connectionId);
mAssociationInfo = associationInfo;
}
@@ -78,10 +78,6 @@
out.writeTypedObject(mAssociationInfo, 0);
}
- public AssociationInfo getAssociationInfo() {
- return mAssociationInfo;
- }
-
/** Returns a string representation of ConnectionInfo. */
@Override
public String toString() {
@@ -98,11 +94,16 @@
}
CdmConnectionInfo other = (CdmConnectionInfo) o;
- return mAssociationInfo.equals(other.getAssociationInfo());
+ return super.equals(o) && mAssociationInfo.equals(other.getConnectionParams());
}
@Override
public int hashCode() {
return Objects.hash(mAssociationInfo);
}
+
+ @Override
+ public AssociationInfo getConnectionParams() {
+ return mAssociationInfo;
+ }
}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectivityManager.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectivityManager.java
new file mode 100644
index 0000000..49745c0
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CdmConnectivityManager.java
@@ -0,0 +1,201 @@
+/*
+ * 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.remoteauth.connectivity;
+
+import static com.android.server.remoteauth.connectivity.DiscoveryFilter.DeviceType;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TargetApi;
+import android.companion.AssociationInfo;
+import android.companion.AssociationRequest;
+import android.os.Build;
+import android.util.Log;
+
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * Discovers devices associated with the companion device manager.
+ *
+ * TODO(b/296625303): Change to VANILLA_ICE_CREAM when AssociationInfo is available in V.
+ */
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
+public class CdmConnectivityManager implements ConnectivityManager {
+ private static final String TAG = "CdmConnectivityManager";
+
+ private final CompanionDeviceManagerWrapper mCompanionDeviceManagerWrapper;
+
+ private ExecutorService mExecutor;
+ private Map<DiscoveredDeviceReceiver, Future> mPendingDiscoveryCallbacks =
+ new ConcurrentHashMap<>();
+
+ public CdmConnectivityManager(
+ @NonNull ExecutorService executor,
+ @NonNull CompanionDeviceManagerWrapper companionDeviceManagerWrapper) {
+ mExecutor = executor;
+ mCompanionDeviceManagerWrapper = companionDeviceManagerWrapper;
+ }
+
+ /**
+ * Runs associated discovery callbacks for discovered devices.
+ *
+ * @param discoveredDeviceReceiver callback.
+ * @param device discovered device.
+ */
+ private void notifyOnDiscovered(
+ @NonNull DiscoveredDeviceReceiver discoveredDeviceReceiver,
+ @NonNull DiscoveredDevice device) {
+ Preconditions.checkNotNull(discoveredDeviceReceiver);
+ Preconditions.checkNotNull(device);
+
+ Log.i(TAG, "Notifying discovered device");
+ discoveredDeviceReceiver.onDiscovered(device);
+ }
+
+ /**
+ * Posts an async task to discover CDM associations and run callback if device is discovered.
+ *
+ * @param discoveryFilter filter for association.
+ * @param discoveredDeviceReceiver callback.
+ */
+ private void startDiscoveryAsync(@NonNull DiscoveryFilter discoveryFilter,
+ @NonNull DiscoveredDeviceReceiver discoveredDeviceReceiver) {
+ Preconditions.checkNotNull(discoveryFilter);
+ Preconditions.checkNotNull(discoveredDeviceReceiver);
+
+ List<AssociationInfo> associations = mCompanionDeviceManagerWrapper.getAllAssociations();
+ Log.i(TAG, "Found associations: " + associations.size());
+ for (AssociationInfo association : associations) {
+ String deviceProfile = getDeviceProfileFromType(discoveryFilter.getDeviceType());
+ // TODO(b/297574984): Include device presence signal before notifying discovery result.
+ if (mCompanionDeviceManagerWrapper.getDeviceProfile(association)
+ .equals(deviceProfile)) {
+ notifyOnDiscovered(
+ discoveredDeviceReceiver,
+ createDiscoveredDeviceFromAssociation(association));
+ }
+ }
+ }
+
+ /**
+ * Returns the device profile from association info.
+ *
+ * @param deviceType Discovery filter device type.
+ * @return Device profile string defined in {@link AssociationRequest}.
+ * @throws AssertionError if type cannot be mapped.
+ */
+ private String getDeviceProfileFromType(@DeviceType int deviceType) {
+ if (deviceType == DiscoveryFilter.WATCH) {
+ return AssociationRequest.DEVICE_PROFILE_WATCH;
+ } else {
+ // Should not reach here.
+ throw new AssertionError(deviceType);
+ }
+ }
+
+ /**
+ * Creates discovered device from association info.
+ *
+ * @param info Association info.
+ * @return discovered device object.
+ */
+ private @NonNull DiscoveredDevice createDiscoveredDeviceFromAssociation(
+ @NonNull AssociationInfo info) {
+ return new DiscoveredDevice(
+ new CdmConnectionInfo(info.getId(), info),
+ info.getDisplayName() == null ? "" : info.getDisplayName().toString());
+ }
+
+ /**
+ * Triggers the discovery for CDM associations.
+ *
+ * Runs discovery only if a callback has not been previously registered.
+ *
+ * @param discoveryFilter filter for associations.
+ * @param discoveredDeviceReceiver callback to be run on discovery result.
+ */
+ @Override
+ public void startDiscovery(
+ @NonNull DiscoveryFilter discoveryFilter,
+ @NonNull DiscoveredDeviceReceiver discoveredDeviceReceiver) {
+ Preconditions.checkNotNull(mCompanionDeviceManagerWrapper);
+ Preconditions.checkNotNull(discoveryFilter);
+ Preconditions.checkNotNull(discoveredDeviceReceiver);
+
+ try {
+ mPendingDiscoveryCallbacks.computeIfAbsent(
+ discoveredDeviceReceiver,
+ discoveryFuture -> mExecutor.submit(
+ () -> startDiscoveryAsync(discoveryFilter, discoveryFuture),
+ /* result= */ null));
+ } catch (RejectedExecutionException | NullPointerException e) {
+ Log.e(TAG, "Failed to start async discovery: " + e.getMessage());
+ }
+ }
+
+ /** Stops discovery. */
+ @Override
+ public void stopDiscovery(
+ @NonNull DiscoveryFilter discoveryFilter,
+ @NonNull DiscoveredDeviceReceiver discoveredDeviceReceiver) {
+ Preconditions.checkNotNull(discoveryFilter);
+ Preconditions.checkNotNull(discoveredDeviceReceiver);
+
+ Future<Void> discoveryFuture = mPendingDiscoveryCallbacks.remove(discoveredDeviceReceiver);
+ if (null != discoveryFuture && !discoveryFuture.cancel(/* mayInterruptIfRunning= */ true)) {
+ Log.d(TAG, "Discovery was possibly completed.");
+ }
+ }
+
+ @Nullable
+ @Override
+ public Connection connect(@NonNull ConnectionInfo connectionInfo,
+ @NonNull EventListener eventListener) {
+ // Not implemented.
+ return null;
+ }
+
+ @Override
+ public void startListening(MessageReceiver messageReceiver) {
+ // Not implemented.
+ }
+
+ @Override
+ public void stopListening(MessageReceiver messageReceiver) {
+ // Not implemented.
+ }
+
+ /**
+ * Returns whether the callback is already registered and pending.
+ *
+ * @param discoveredDeviceReceiver callback
+ * @return true if the callback is pending, false otherwise.
+ */
+ @VisibleForTesting
+ boolean hasPendingCallbacks(@NonNull DiscoveredDeviceReceiver discoveredDeviceReceiver) {
+ return mPendingDiscoveryCallbacks.containsKey(discoveredDeviceReceiver);
+ }
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/CompanionDeviceManagerWrapper.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CompanionDeviceManagerWrapper.java
new file mode 100644
index 0000000..eaf3edb
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/CompanionDeviceManagerWrapper.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.remoteauth.connectivity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TargetApi;
+import android.companion.AssociationInfo;
+import android.companion.CompanionDeviceManager;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import java.util.List;
+
+/** Wraps {@link android.companion.CompanionDeviceManager} for easier testing. */
+// TODO(b/296625303): Change to VANILLA_ICE_CREAM when AssociationInfo is available in V.
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
+public class CompanionDeviceManagerWrapper {
+ private static final String TAG = "CompanionDeviceManagerWrapper";
+
+ private Context mContext;
+ private CompanionDeviceManager mCompanionDeviceManager;
+
+ public CompanionDeviceManagerWrapper(@NonNull Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Returns device profile string from the association info.
+ *
+ * @param associationInfo the association info.
+ * @return String indicating device profile
+ */
+ @Nullable
+ public String getDeviceProfile(@NonNull AssociationInfo associationInfo) {
+ return associationInfo.getDeviceProfile();
+ }
+
+ /**
+ * Returns all associations.
+ *
+ * @return associations or null if no associated devices present.
+ */
+ @Nullable
+ public List<AssociationInfo> getAllAssociations() {
+ if (mCompanionDeviceManager == null) {
+ try {
+ mCompanionDeviceManager = mContext.getSystemService(CompanionDeviceManager.class);
+ } catch (NullPointerException e) {
+ Log.e(TAG, "CompanionDeviceManager service does not exist: " + e);
+ return null;
+ }
+ }
+
+ try {
+ return mCompanionDeviceManager.getAllAssociations();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to get CompanionDeviceManager associations: " + e.getMessage());
+ }
+ return null;
+ }
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/Connection.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/Connection.java
index eb5458d..dca8b9f 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/Connection.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/Connection.java
@@ -25,7 +25,6 @@
* A connection with the peer device.
*
* <p>Connections are used to exchange data with the peer device.
- *
*/
public interface Connection {
/** Unknown error. */
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectionInfo.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectionInfo.java
index 39bfa8d..6e0edb4 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectionInfo.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectionInfo.java
@@ -28,9 +28,10 @@
* <p>Connection information captures the details of underlying connection such as connection id,
* type of connection and peer device mac address.
*
+ * @param <T> connection params per connection type.
*/
// TODO(b/295407748) Change to use @DataClass.
-public abstract class ConnectionInfo implements Parcelable {
+public abstract class ConnectionInfo<T> implements Parcelable {
int mConnectionId;
public ConnectionInfo(int connectionId) {
@@ -85,4 +86,9 @@
public int hashCode() {
return Objects.hash(mConnectionId);
}
+
+ /**
+ * Returns connection related parameters.
+ */
+ public abstract T getConnectionParams();
}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManager.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManager.java
index bc0d77e..7b30285 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManager.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManager.java
@@ -23,9 +23,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/**
- * Performs discovery and triggers a connection to an associated device.
- */
+/** Performs discovery and triggers a connection to an associated device. */
public interface ConnectivityManager {
/**
* Starts device discovery.
@@ -63,8 +61,12 @@
/** Reason codes for connect failure. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({ERROR_REASON_UNKNOWN, ERROR_CONNECTION_TIMED_OUT, ERROR_CONNECTION_REFUSED,
- ERROR_DEVICE_UNAVAILABLE})
+ @IntDef({
+ ERROR_REASON_UNKNOWN,
+ ERROR_CONNECTION_TIMED_OUT,
+ ERROR_CONNECTION_REFUSED,
+ ERROR_DEVICE_UNAVAILABLE
+ })
@interface ReasonCode {}
/**
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManagerFactory.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManagerFactory.java
new file mode 100644
index 0000000..3407fca
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/ConnectivityManagerFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.remoteauth.connectivity;
+
+import android.annotation.NonNull;
+import android.content.Context;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Factory class to create different types of connectivity managers based on the underlying
+ * network transports (for example CompanionDeviceManager).
+ */
+public final class ConnectivityManagerFactory {
+ private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
+
+ /**
+ * Creates and returns a ConnectivityManager object depending on connection type.
+ *
+ * @param context of the caller.
+ * @return ConnectivityManager object.
+ */
+ public static ConnectivityManager getConnectivityManager(@NonNull Context context) {
+ Preconditions.checkNotNull(context);
+
+ // For now, we only have one case, but ideally this should create a new type based on some
+ // feature flag.
+ return new CdmConnectivityManager(EXECUTOR, new CompanionDeviceManagerWrapper(
+ new WeakReference<>(context.getApplicationContext()).get()));
+ }
+
+ private ConnectivityManagerFactory() {}
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveredDevice.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveredDevice.java
index a3e1e58..8cad3eb 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveredDevice.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveredDevice.java
@@ -25,8 +25,7 @@
private @NonNull ConnectionInfo mConnectionInfo;
private @Nullable String mDisplayName;
- public DiscoveredDevice(
- @NonNull ConnectionInfo connectionInfo, @Nullable String displayName) {
+ public DiscoveredDevice(@NonNull ConnectionInfo connectionInfo, @Nullable String displayName) {
this.mConnectionInfo = connectionInfo;
this.mDisplayName = displayName;
}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveryFilter.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveryFilter.java
index 36c4b60..3590f20 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveryFilter.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/DiscoveryFilter.java
@@ -31,7 +31,6 @@
* the filter criteria (device type, name or peer address).
*/
public final class DiscoveryFilter {
-
/** Device type WATCH. */
public static final int WATCH = 0;
@@ -86,7 +85,7 @@
private Builder() {}
/** Static method to create a new builder */
- public static Builder newInstance() {
+ public static Builder builder() {
return new Builder();
}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/connectivity/EventListener.java b/remoteauth/service/java/com/android/server/remoteauth/connectivity/EventListener.java
index 8ec851a..eaf57e0 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/connectivity/EventListener.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/connectivity/EventListener.java
@@ -18,9 +18,7 @@
import android.annotation.NonNull;
-/**
- * Listens to the events from underlying transport.
- */
+/** Listens to the events from underlying transport. */
public interface EventListener {
/** Called when remote device is disconnected from the underlying transport. */
void onDisconnect(@NonNull ConnectionInfo connectionInfo);
diff --git a/remoteauth/tests/unit/Android.bp b/remoteauth/tests/unit/Android.bp
index 16a8242..9636f4b 100644
--- a/remoteauth/tests/unit/Android.bp
+++ b/remoteauth/tests/unit/Android.bp
@@ -32,17 +32,20 @@
"android.test.base",
"android.test.mock",
"android.test.runner",
+ "framework-annotations-lib",
],
compile_multilib: "both",
static_libs: [
"androidx.test.ext.junit",
+ "androidx.test.ext.truth",
"androidx.test.rules",
"com.uwb.support.generic",
"framework-remoteauth-static",
"junit",
"libprotobuf-java-lite",
"mockito-target-extended-minus-junit4",
+ "mockito-target-minus-junit4",
"platform-test-annotations",
"service-remoteauth-pre-jarjar",
"truth-prebuilt",
diff --git a/remoteauth/tests/unit/AndroidManifest.xml b/remoteauth/tests/unit/AndroidManifest.xml
index 0449409..a5294c8 100644
--- a/remoteauth/tests/unit/AndroidManifest.xml
+++ b/remoteauth/tests/unit/AndroidManifest.xml
@@ -31,5 +31,6 @@
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.remoteauth.test"
- android:label="RemoteAuth Mainline Module Tests" />
+ android:label="RemoteAuth Mainline Module Tests"
+ android:directBootAware="true"/>
</manifest>
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/CdmConnectivityManagerTest.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/CdmConnectivityManagerTest.java
new file mode 100644
index 0000000..824344a
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/CdmConnectivityManagerTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.remoteauth.connectivity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.companion.AssociationInfo;
+import android.companion.AssociationRequest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/** Unit tests for {@link CdmConnectivityManager}. */
+@RunWith(AndroidJUnit4.class)
+public class CdmConnectivityManagerTest {
+ @Rule public final MockitoRule mocks = MockitoJUnit.rule();
+
+ @Mock CompanionDeviceManagerWrapper mCompanionDeviceManagerWrapper;
+
+ private CdmConnectivityManager mCdmConnectivityManager;
+ private ExecutorService mTestExecutor = Executors.newSingleThreadExecutor();
+
+ @Before
+ public void setUp() {
+ mCdmConnectivityManager =
+ new CdmConnectivityManager(mTestExecutor, mCompanionDeviceManagerWrapper);
+ }
+
+ @After
+ public void tearDown() {
+ mTestExecutor.shutdown();
+ }
+
+ @Test
+ public void testStartDiscovery_callsGetAllAssociationsOnce() throws InterruptedException {
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), Utils.getFakeDiscoveredDeviceReceiver());
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(1)).getAllAssociations();
+ }
+
+ @Test
+ public void testStartDiscovery_fetchesNoAssociations() {
+ SettableFuture<Boolean> future = SettableFuture.create();
+
+ when(mCompanionDeviceManagerWrapper.getAllAssociations())
+ .thenReturn(Utils.getFakeAssociationInfoList(0));
+
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future.set(true);
+ }
+
+ @Override
+ public void onLost(DiscoveredDevice unused) {
+ future.set(true);
+ }
+ };
+
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver);
+
+ assertThat(future.isDone()).isFalse();
+ }
+
+ @Test
+ public void testStartDiscovery_DoesNotReturnNonWatchAssociations() throws InterruptedException {
+ SettableFuture<Boolean> future = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future.set(true);
+ }
+
+ @Override
+ public void onLost(DiscoveredDevice unused) {
+ future.set(true);
+ }
+ };
+
+ when(mCompanionDeviceManagerWrapper.getDeviceProfile(any(AssociationInfo.class)))
+ .thenReturn(Utils.FAKE_DEVICE_PROFILE);
+
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver);
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(1)).getAllAssociations();
+ verify(mCompanionDeviceManagerWrapper, times(0))
+ .getDeviceProfile(any(AssociationInfo.class));
+ assertThat(future.isDone()).isFalse();
+ }
+
+ @Test
+ public void testStartDiscovery_returnsOneWatchAssociation() throws InterruptedException {
+ SettableFuture<Boolean> future = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future.set(true);
+ }
+ };
+
+ when(mCompanionDeviceManagerWrapper.getAllAssociations())
+ .thenReturn(Utils.getFakeAssociationInfoList(1));
+ when(mCompanionDeviceManagerWrapper.getDeviceProfile(any(AssociationInfo.class)))
+ .thenReturn(AssociationRequest.DEVICE_PROFILE_WATCH);
+
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver);
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(1)).getAllAssociations();
+ verify(mCompanionDeviceManagerWrapper, times(1))
+ .getDeviceProfile(any(AssociationInfo.class));
+ assertThat(future.isDone()).isTrue();
+ }
+
+ @Test
+ public void testStartDiscovery_returnsMultipleWatchAssociations() throws InterruptedException {
+ int numAssociations = 3;
+ SettableFuture<Boolean> future = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ int mNumCallbacks = 0;
+
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ ++mNumCallbacks;
+ if (mNumCallbacks == numAssociations) {
+ future.set(true);
+ }
+ }
+ };
+
+ when(mCompanionDeviceManagerWrapper.getAllAssociations())
+ .thenReturn(Utils.getFakeAssociationInfoList(numAssociations));
+ when(mCompanionDeviceManagerWrapper.getDeviceProfile(any(AssociationInfo.class)))
+ .thenReturn(AssociationRequest.DEVICE_PROFILE_WATCH);
+
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver);
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(1)).getAllAssociations();
+ verify(mCompanionDeviceManagerWrapper, times(numAssociations))
+ .getDeviceProfile(any(AssociationInfo.class));
+ assertThat(future.isDone()).isTrue();
+ }
+
+ @Test
+ public void testMultipleStartDiscovery_runsAllCallbacks() throws InterruptedException {
+ SettableFuture<Boolean> future1 = SettableFuture.create();
+ SettableFuture<Boolean> future2 = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver1 =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future1.set(true);
+ }
+ };
+ DiscoveredDeviceReceiver discoveredDeviceReceiver2 =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future2.set(true);
+ }
+ };
+
+ when(mCompanionDeviceManagerWrapper.getAllAssociations())
+ .thenReturn(Utils.getFakeAssociationInfoList(1));
+ when(mCompanionDeviceManagerWrapper.getDeviceProfile(any(AssociationInfo.class)))
+ .thenReturn(AssociationRequest.DEVICE_PROFILE_WATCH);
+
+ // Start discovery twice with different callbacks.
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver1);
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver2);
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(2)).getAllAssociations();
+ verify(mCompanionDeviceManagerWrapper, times(2))
+ .getDeviceProfile(any(AssociationInfo.class));
+ assertThat(future1.isDone()).isTrue();
+ assertThat(future2.isDone()).isTrue();
+ }
+
+ @Test
+ public void testStartDiscovery_returnsExpectedDiscoveredDevice() throws InterruptedException {
+ SettableFuture<Boolean> future = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice device) {
+ assertThat(device.getConnectionInfo() instanceof CdmConnectionInfo)
+ .isTrue();
+
+ CdmConnectionInfo connectionInfo =
+ (CdmConnectionInfo) device.getConnectionInfo();
+ if (connectionInfo.getConnectionParams().getDeviceMacAddress().toString()
+ .equals(Utils.FAKE_PEER_ADDRESS)
+ && connectionInfo.getConnectionId() == Utils.FAKE_CONNECTION_ID) {
+ future.set(true);
+ }
+ }
+ };
+
+ when(mCompanionDeviceManagerWrapper.getAllAssociations())
+ .thenReturn(Utils.getFakeAssociationInfoList(1));
+ when(mCompanionDeviceManagerWrapper.getDeviceProfile(any(AssociationInfo.class)))
+ .thenReturn(AssociationRequest.DEVICE_PROFILE_WATCH);
+
+ mCdmConnectivityManager.startDiscovery(
+ Utils.getFakeDiscoveryFilter(), discoveredDeviceReceiver);
+
+ mTestExecutor.awaitTermination(1, TimeUnit.SECONDS);
+
+ verify(mCompanionDeviceManagerWrapper, times(1)).getAllAssociations();
+ verify(mCompanionDeviceManagerWrapper, times(1))
+ .getDeviceProfile(any(AssociationInfo.class));
+ assertThat(future.isDone()).isTrue();
+ }
+
+ @Test
+ public void testStopDiscovery_removesCallback() {
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {}
+ };
+
+ DiscoveryFilter discoveryFilter = Utils.getFakeDiscoveryFilter();
+ mCdmConnectivityManager.startDiscovery(discoveryFilter, discoveredDeviceReceiver);
+
+ assertThat(mCdmConnectivityManager.hasPendingCallbacks(discoveredDeviceReceiver)).isTrue();
+
+ mCdmConnectivityManager.stopDiscovery(discoveryFilter, discoveredDeviceReceiver);
+
+ assertThat(mCdmConnectivityManager.hasPendingCallbacks(discoveredDeviceReceiver)).isFalse();
+ }
+
+ @Test
+ public void testStopDiscovery_DoesNotRunCallback() {
+ SettableFuture future = SettableFuture.create();
+ DiscoveredDeviceReceiver discoveredDeviceReceiver =
+ new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {
+ future.set(true);
+ }
+ };
+
+ DiscoveryFilter discoveryFilter = Utils.getFakeDiscoveryFilter();
+ mCdmConnectivityManager.startDiscovery(discoveryFilter, discoveredDeviceReceiver);
+ mCdmConnectivityManager.stopDiscovery(discoveryFilter, discoveredDeviceReceiver);
+
+ assertThat(future.isDone()).isFalse();
+ }
+}
+
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/ConnectivityManagerFactoryTest.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/ConnectivityManagerFactoryTest.java
new file mode 100644
index 0000000..42eff90
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/ConnectivityManagerFactoryTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.remoteauth.connectivity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link CdmConnectivityManager}. */
+@RunWith(AndroidJUnit4.class)
+public class ConnectivityManagerFactoryTest {
+
+ @Before
+ public void setUp() {}
+
+ @Test
+ public void testFactory_returnsConnectivityManager() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ ConnectivityManager connectivityManager =
+ ConnectivityManagerFactory.getConnectivityManager(context);
+
+ assertThat(connectivityManager).isNotNull();
+ }
+}
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/Utils.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/Utils.java
new file mode 100644
index 0000000..a5c992a
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/connectivity/Utils.java
@@ -0,0 +1,99 @@
+/*
+ * 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.remoteauth.connectivity;
+
+import android.companion.AssociationInfo;
+import android.companion.AssociationRequest;
+import android.content.pm.PackageManager;
+import android.net.MacAddress;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class Utils {
+ public static final int FAKE_CONNECTION_ID = 1;
+ public static final int FAKE_USER_ID = 0;
+ public static final String FAKE_DISPLAY_NAME = "FAKE-DISPLAY-NAME";
+ public static final String FAKE_PEER_ADDRESS = "ff:ff:ff:ff:ff:ff";
+ public static final String FAKE_DEVICE_PROFILE = "FAKE-DEVICE-PROFILE";
+ public static final String FAKE_PACKAGE_NAME = "FAKE-PACKAGE-NAME";
+
+ public static DiscoveryFilter getFakeDiscoveryFilter() {
+ return DiscoveryFilter.Builder.builder()
+ .setDeviceName(FAKE_DISPLAY_NAME)
+ .setPeerAddress("FAKE-PEER-ADDRESS")
+ .setDeviceType(DiscoveryFilter.WATCH)
+ .build();
+ }
+
+ public static DiscoveredDeviceReceiver getFakeDiscoveredDeviceReceiver() {
+ return new DiscoveredDeviceReceiver() {
+ @Override
+ public void onDiscovered(DiscoveredDevice unused) {}
+
+ @Override
+ public void onLost(DiscoveredDevice unused) {}
+ };
+ }
+
+ /**
+ * Returns a fake CDM connection info.
+ *
+ * @return connection info.
+ */
+ public static CdmConnectionInfo getFakeCdmConnectionInfo()
+ throws PackageManager.NameNotFoundException {
+ return new CdmConnectionInfo(FAKE_CONNECTION_ID, getFakeAssociationInfoList(1).get(0));
+ }
+
+ /**
+ * Returns a fake discovered device.
+ *
+ * @return discovered device.
+ */
+ public static DiscoveredDevice getFakeCdmDiscoveredDevice()
+ throws PackageManager.NameNotFoundException {
+ return new DiscoveredDevice(getFakeCdmConnectionInfo(), FAKE_DISPLAY_NAME);
+ }
+
+ /**
+ * Returns fake association info array.
+ *
+ * <p> Creates an AssociationInfo object with fake values.
+ *
+ * @param associationsSize number of fake association info entries to return.
+ * @return list of {@link AssociationInfo} or null.
+ */
+ public static List<AssociationInfo> getFakeAssociationInfoList(int associationsSize) {
+ if (associationsSize > 0) {
+ List<AssociationInfo> associations = new ArrayList<>();
+ // Association id starts from 1.
+ for (int i = 1; i <= associationsSize; ++i) {
+ associations.add(
+ (new AssociationInfo.Builder(i, FAKE_USER_ID, FAKE_PACKAGE_NAME))
+ .setDeviceProfile(AssociationRequest.DEVICE_PROFILE_WATCH)
+ .setDisplayName(FAKE_DISPLAY_NAME)
+ .setDeviceMacAddress(MacAddress.fromString(FAKE_PEER_ADDRESS))
+ .build());
+ }
+ return associations;
+ }
+ return new ArrayList<>();
+ }
+
+ private Utils() {}
+}
diff --git a/service-t/Android.bp b/service-t/Android.bp
index 7e588cd..bc49f0e 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -19,7 +19,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-service_remoteauth_pre_jarjar_lib = "service-remoteauth-pre-jarjar-udc-compat"
+service_remoteauth_pre_jarjar_lib = "service-remoteauth-pre-jarjar"
// Include build rules from Sources.bp
build = ["Sources.bp"]
diff --git a/service/Android.bp b/service/Android.bp
index 134517f..8e59e86 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -19,7 +19,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-service_remoteauth_pre_jarjar_lib = "service-remoteauth-pre-jarjar-udc-compat"
+service_remoteauth_pre_jarjar_lib = "service-remoteauth-pre-jarjar"
// The above variables may have different values
// depending on the branch, and this comment helps
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index 2d07224..e55ba63 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-next_app_data = []
+next_app_data = [ ":CtsHostsideNetworkTestsAppNext" ]
// The above line is put in place to prevent any future automerger merge conflict between aosp,
// downstream branches. The CtsHostsideNetworkTestsAppNext target will not exist in