Merge "Add RemoteAuthService" into main
This commit is contained in:
@@ -203,6 +203,8 @@ bootclasspath_fragment {
|
||||
// result in a build failure due to inconsistent flags.
|
||||
package_prefixes: [
|
||||
"android.nearby.aidl",
|
||||
"android.remoteauth.aidl",
|
||||
"android.remoteauth",
|
||||
"android.net.apf",
|
||||
"android.net.connectivity",
|
||||
"android.net.http.apihelpers",
|
||||
|
||||
@@ -43,6 +43,7 @@ java_defaults {
|
||||
":framework-connectivity-tiramisu-updatable-sources",
|
||||
":framework-nearby-java-sources",
|
||||
":framework-thread-sources",
|
||||
":framework-remoteauth-java-sources",
|
||||
],
|
||||
libs: [
|
||||
"unsupportedappusage",
|
||||
@@ -130,8 +131,10 @@ java_sdk_library {
|
||||
"android.net",
|
||||
"android.net.nsd",
|
||||
"android.nearby",
|
||||
"android.remoteauth",
|
||||
"com.android.connectivity",
|
||||
"com.android.nearby",
|
||||
"com.android.remoteauth",
|
||||
],
|
||||
|
||||
hidden_api: {
|
||||
@@ -153,6 +156,7 @@ java_sdk_library {
|
||||
"//packages/modules/Connectivity/service", // For R8 only
|
||||
"//packages/modules/Connectivity/service-t",
|
||||
"//packages/modules/Connectivity/nearby:__subpackages__",
|
||||
"//packages/modules/Connectivity/remoteauth:__subpackages__",
|
||||
"//frameworks/base",
|
||||
|
||||
// Tests using hidden APIs
|
||||
|
||||
@@ -207,3 +207,43 @@ package android.net {
|
||||
|
||||
}
|
||||
|
||||
package android.remoteauth {
|
||||
|
||||
public interface DeviceDiscoveryCallback {
|
||||
method public void onDeviceUpdate(@NonNull android.remoteauth.RemoteDevice, int);
|
||||
method public void onTimeout();
|
||||
field public static final int STATE_LOST = 0; // 0x0
|
||||
field public static final int STATE_SEEN = 1; // 0x1
|
||||
}
|
||||
|
||||
public final class RemoteAuthFrameworkInitializer {
|
||||
method public static void registerServiceWrappers();
|
||||
}
|
||||
|
||||
public class RemoteAuthManager {
|
||||
method public boolean isRemoteAuthSupported();
|
||||
method public boolean startDiscovery(int, @NonNull java.util.concurrent.Executor, @NonNull android.remoteauth.DeviceDiscoveryCallback);
|
||||
method public void stopDiscovery(@NonNull android.remoteauth.DeviceDiscoveryCallback);
|
||||
}
|
||||
|
||||
public final class RemoteDevice implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public int getConnectionId();
|
||||
method @Nullable public String getName();
|
||||
method public int getRegistrationState();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.remoteauth.RemoteDevice> CREATOR;
|
||||
field public static final int STATE_NOT_REGISTERED = 0; // 0x0
|
||||
field public static final int STATE_REGISTERED = 1; // 0x1
|
||||
}
|
||||
|
||||
public static final class RemoteDevice.Builder {
|
||||
ctor public RemoteDevice.Builder(int);
|
||||
method @NonNull public android.remoteauth.RemoteDevice build();
|
||||
method @NonNull public android.remoteauth.RemoteDevice.Builder setConnectionId(int);
|
||||
method @NonNull public android.remoteauth.RemoteDevice.Builder setName(@Nullable String);
|
||||
method @NonNull public android.remoteauth.RemoteDevice.Builder setRegistrationState(int);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ java_defaults {
|
||||
":framework-connectivity-sources",
|
||||
":net-utils-framework-common-srcs",
|
||||
":framework-connectivity-api-shared-srcs",
|
||||
":framework-remoteauth-java-sources",
|
||||
],
|
||||
aidl: {
|
||||
generate_get_transaction_name: true,
|
||||
@@ -153,7 +152,6 @@ java_sdk_library {
|
||||
"//packages/modules/Connectivity/framework-t",
|
||||
"//packages/modules/Connectivity/service",
|
||||
"//packages/modules/Connectivity/service-t",
|
||||
"//packages/modules/Connectivity/remoteauth:__subpackages__",
|
||||
"//frameworks/base/packages/Connectivity/service",
|
||||
"//frameworks/base",
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// TODO(b/193602229): uncomment once it's supported.
|
||||
//"mainline-presubmit": [
|
||||
// {
|
||||
// "name": "RemoteAuthUnitTests[com.google.android.tethering.apex]"
|
||||
// "name": "RemoteAuthUnitTests[com.google.android.remoteauth.apex]"
|
||||
// }
|
||||
//]
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ filegroup {
|
||||
],
|
||||
path: "java",
|
||||
visibility: [
|
||||
"//packages/modules/Connectivity/framework:__subpackages__",
|
||||
"//packages/modules/Connectivity/framework-t:__subpackages__",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -43,7 +43,13 @@ java_library {
|
||||
name: "framework-remoteauth-static",
|
||||
srcs: [":framework-remoteauth-java-sources"],
|
||||
sdk_version: "module_current",
|
||||
libs: [],
|
||||
static_libs: [],
|
||||
libs: [
|
||||
"androidx.annotation_annotation",
|
||||
"framework-annotations-lib",
|
||||
"framework-bluetooth",
|
||||
],
|
||||
static_libs: [
|
||||
"modules-utils-preconditions",
|
||||
],
|
||||
visibility: ["//packages/modules/Connectivity/remoteauth/tests:__subpackages__"],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Reports newly discovered remote devices.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public interface DeviceDiscoveryCallback {
|
||||
/** The device is no longer seen in the discovery process. */
|
||||
int STATE_LOST = 0;
|
||||
/** The device is seen in the discovery process */
|
||||
int STATE_SEEN = 1;
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({STATE_LOST, STATE_SEEN})
|
||||
@interface State {}
|
||||
|
||||
/**
|
||||
* Invoked for every change in remote device state.
|
||||
*
|
||||
* @param device remote device
|
||||
* @param state indicates if found or lost
|
||||
*/
|
||||
void onDeviceUpdate(@NonNull RemoteDevice device, @State int state);
|
||||
|
||||
/** Invoked when discovery is stopped due to timeout. */
|
||||
void onTimeout();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import android.remoteauth.RemoteDevice;
|
||||
|
||||
/**
|
||||
* Binder callback for DeviceDiscoveryCallback.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IDeviceDiscoveryListener {
|
||||
/** Reports a {@link RemoteDevice} being discovered. */
|
||||
void onDiscovered(in RemoteDevice remoteDevice);
|
||||
|
||||
/** Reports a {@link RemoteDevice} is no longer within range. */
|
||||
void onLost(in RemoteDevice remoteDevice);
|
||||
|
||||
/** Reports a timeout of {@link RemoteDevice} was reached. */
|
||||
void onTimeout();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import android.remoteauth.IDeviceDiscoveryListener;
|
||||
|
||||
/**
|
||||
* Interface for communicating with the RemoteAuthService.
|
||||
* These methods are all require MANAGE_REMOTE_AUTH signature permission.
|
||||
* @hide
|
||||
*/
|
||||
interface IRemoteAuthService {
|
||||
// This is protected by the MANAGE_REMOTE_AUTH signature permission.
|
||||
boolean isRemoteAuthSupported();
|
||||
|
||||
// This is protected by the MANAGE_REMOTE_AUTH signature permission.
|
||||
boolean registerDiscoveryListener(in IDeviceDiscoveryListener deviceDiscoveryListener,
|
||||
int userId,
|
||||
int timeoutMs,
|
||||
String packageName,
|
||||
@nullable String attributionTag);
|
||||
|
||||
// This is protected by the MANAGE_REMOTE_AUTH signature permission.
|
||||
void unregisterDiscoveryListener(in IDeviceDiscoveryListener deviceDiscoveryListener,
|
||||
int userId,
|
||||
String packageName,
|
||||
@nullable String attributionTag);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.SystemServiceRegistry;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Class for initializing RemoteAuth service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||
public final class RemoteAuthFrameworkInitializer {
|
||||
private RemoteAuthFrameworkInitializer() {}
|
||||
|
||||
/**
|
||||
* Called by {@link SystemServiceRegistry}'s static initializer and registers all Nearby
|
||||
* services to {@link Context}, so that {@link Context#getSystemService} can return them.
|
||||
*
|
||||
* @throws IllegalStateException if this is called from anywhere besides {@link
|
||||
* SystemServiceRegistry}
|
||||
*/
|
||||
public static void registerServiceWrappers() {
|
||||
// TODO(b/290092977): Change to Context.REMOTE_AUTH_SERVICE after aosp/2681375
|
||||
// is automerges from aosp-main to udc-mainline-prod
|
||||
SystemServiceRegistry.registerContextAwareService(
|
||||
RemoteAuthManager.REMOTE_AUTH_SERVICE,
|
||||
RemoteAuthManager.class,
|
||||
(context, serviceBinder) -> {
|
||||
IRemoteAuthService service = IRemoteAuthService.Stub.asInterface(serviceBinder);
|
||||
return new RemoteAuthManager(context, service);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
import static android.remoteauth.DeviceDiscoveryCallback.STATE_LOST;
|
||||
import static android.remoteauth.DeviceDiscoveryCallback.STATE_SEEN;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* A system service providing a way to perform remote authentication-related operations such as
|
||||
* discovering, registering and authenticating via remote authenticator.
|
||||
*
|
||||
* <p>To get a {@link RemoteAuthManager} instance, call the <code>
|
||||
* Context.getSystemService(Context.REMOTE_AUTH_SERVICE)</code>.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
// TODO(b/290092977): Change to Context.REMOTE_AUTH_SERVICE after aosp/2681375
|
||||
// is automerges from aosp-main to udc-mainline-prod
|
||||
@SystemService(RemoteAuthManager.REMOTE_AUTH_SERVICE)
|
||||
public class RemoteAuthManager {
|
||||
private static final String TAG = "RemoteAuthManager";
|
||||
|
||||
/** @hide */
|
||||
public static final String REMOTE_AUTH_SERVICE = "remote_auth";
|
||||
|
||||
private final Context mContext;
|
||||
private final IRemoteAuthService mService;
|
||||
|
||||
@GuardedBy("mDiscoveryListeners")
|
||||
private final WeakHashMap<
|
||||
DeviceDiscoveryCallback, WeakReference<DeviceDiscoveryListenerTransport>>
|
||||
mDiscoveryListeners = new WeakHashMap<>();
|
||||
|
||||
/** @hide */
|
||||
public RemoteAuthManager(@NonNull Context context, @NonNull IRemoteAuthService service) {
|
||||
Objects.requireNonNull(context);
|
||||
Objects.requireNonNull(service);
|
||||
mContext = context;
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this device can be enrolled in the feature.
|
||||
*
|
||||
* @return true if this device can be enrolled
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
// TODO(b/297301535): @RequiresPermission(MANAGE_REMOTE_AUTH)
|
||||
public boolean isRemoteAuthSupported() {
|
||||
try {
|
||||
return mService.isRemoteAuthSupported();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts remote authenticator discovery process with timeout. Devices that are capable to
|
||||
* operate as remote authenticators are reported via callback. The discovery stops by calling
|
||||
* stopDiscovery or after a timeout.
|
||||
*
|
||||
* @param timeoutMs the duration in milliseconds after which discovery will stop automatically
|
||||
* @param executor the callback will be executed in the executor thread
|
||||
* @param callback to be used by the caller to get notifications about remote devices
|
||||
* @return {@code true} if discovery began successfully, {@code false} otherwise
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
// TODO(b/297301535): @RequiresPermission(MANAGE_REMOTE_AUTH)
|
||||
public boolean startDiscovery(
|
||||
int timeoutMs,
|
||||
@CallbackExecutor @NonNull Executor executor,
|
||||
@NonNull DeviceDiscoveryCallback callback) {
|
||||
try {
|
||||
Preconditions.checkNotNull(callback, "invalid null callback");
|
||||
Preconditions.checkArgument(timeoutMs > 0, "invalid timeoutMs, must be > 0");
|
||||
Preconditions.checkNotNull(executor, "invalid null executor");
|
||||
DeviceDiscoveryListenerTransport transport;
|
||||
synchronized (mDiscoveryListeners) {
|
||||
WeakReference<DeviceDiscoveryListenerTransport> reference =
|
||||
mDiscoveryListeners.get(callback);
|
||||
transport = (reference != null) ? reference.get() : null;
|
||||
if (transport == null) {
|
||||
transport =
|
||||
new DeviceDiscoveryListenerTransport(
|
||||
callback, mContext.getUser().getIdentifier(), executor);
|
||||
}
|
||||
|
||||
boolean result =
|
||||
mService.registerDiscoveryListener(
|
||||
transport,
|
||||
mContext.getUser().getIdentifier(),
|
||||
timeoutMs,
|
||||
mContext.getPackageName(),
|
||||
mContext.getAttributionTag());
|
||||
if (result) {
|
||||
mDiscoveryListeners.put(callback, new WeakReference<>(transport));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this listener from device discovery notifications. The given callback is guaranteed
|
||||
* not to receive any invocations that happen after this method is invoked.
|
||||
*
|
||||
* @param callback the callback for the previously started discovery to be ended
|
||||
* @hide
|
||||
*/
|
||||
// Suppressed lint: Registration methods should have overload that accepts delivery Executor.
|
||||
// Already have executor in startDiscovery() method.
|
||||
@SuppressLint("ExecutorRegistration")
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
// TODO(b/297301535): @RequiresPermission(MANAGE_REMOTE_AUTH)
|
||||
public void stopDiscovery(@NonNull DeviceDiscoveryCallback callback) {
|
||||
Preconditions.checkNotNull(callback, "invalid null scanCallback");
|
||||
try {
|
||||
DeviceDiscoveryListenerTransport transport;
|
||||
synchronized (mDiscoveryListeners) {
|
||||
WeakReference<DeviceDiscoveryListenerTransport> reference =
|
||||
mDiscoveryListeners.remove(callback);
|
||||
transport = (reference != null) ? reference.get() : null;
|
||||
}
|
||||
if (transport != null) {
|
||||
mService.unregisterDiscoveryListener(
|
||||
transport,
|
||||
transport.getUserId(),
|
||||
mContext.getPackageName(),
|
||||
mContext.getAttributionTag());
|
||||
} else {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Cannot stop discovery with this callback "
|
||||
+ "because it is not registered.");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private class DeviceDiscoveryListenerTransport extends IDeviceDiscoveryListener.Stub {
|
||||
|
||||
private volatile @NonNull DeviceDiscoveryCallback mDeviceDiscoveryCallback;
|
||||
private Executor mExecutor;
|
||||
private @UserIdInt int mUserId;
|
||||
|
||||
DeviceDiscoveryListenerTransport(
|
||||
DeviceDiscoveryCallback deviceDiscoveryCallback,
|
||||
@UserIdInt int userId,
|
||||
@CallbackExecutor Executor executor) {
|
||||
Preconditions.checkNotNull(deviceDiscoveryCallback, "invalid null callback");
|
||||
mDeviceDiscoveryCallback = deviceDiscoveryCallback;
|
||||
mUserId = userId;
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
@UserIdInt
|
||||
int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDiscovered(RemoteDevice remoteDevice) throws RemoteException {
|
||||
if (remoteDevice == null) {
|
||||
Log.w(TAG, "onDiscovered is called with null device");
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "Notifying the caller about discovered: " + remoteDevice);
|
||||
mExecutor.execute(
|
||||
() -> {
|
||||
mDeviceDiscoveryCallback.onDeviceUpdate(remoteDevice, STATE_SEEN);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(RemoteDevice remoteDevice) throws RemoteException {
|
||||
if (remoteDevice == null) {
|
||||
Log.w(TAG, "onLost is called with null device");
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "Notifying the caller about lost: " + remoteDevice);
|
||||
mExecutor.execute(
|
||||
() -> {
|
||||
mDeviceDiscoveryCallback.onDeviceUpdate(remoteDevice, STATE_LOST);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout() {
|
||||
Log.i(TAG, "Notifying the caller about discovery timeout");
|
||||
mExecutor.execute(
|
||||
() -> {
|
||||
mDeviceDiscoveryCallback.onTimeout();
|
||||
});
|
||||
synchronized (mDiscoveryListeners) {
|
||||
mDiscoveryListeners.remove(mDeviceDiscoveryCallback);
|
||||
}
|
||||
mDeviceDiscoveryCallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
parcelable RemoteDevice;
|
||||
203
remoteauth/framework/java/android/remoteauth/RemoteDevice.java
Normal file
203
remoteauth/framework/java/android/remoteauth/RemoteDevice.java
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 android.remoteauth;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Remote device that can be registered as remote authenticator.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
// TODO(b/295407748) Change to use @DataClass
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public final class RemoteDevice implements Parcelable {
|
||||
/** The remote device is not registered as remote authenticator. */
|
||||
public static final int STATE_NOT_REGISTERED = 0;
|
||||
/** The remote device is registered as remote authenticator. */
|
||||
public static final int STATE_REGISTERED = 1;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({STATE_NOT_REGISTERED, STATE_REGISTERED})
|
||||
@interface RegistrationState {}
|
||||
|
||||
@NonNull private final String mName;
|
||||
private final @RegistrationState int mRegistrationState;
|
||||
private final int mConnectionId;
|
||||
|
||||
public static final @NonNull Creator<RemoteDevice> CREATOR =
|
||||
new Creator<>() {
|
||||
@Override
|
||||
public RemoteDevice createFromParcel(Parcel in) {
|
||||
RemoteDevice.Builder builder = new RemoteDevice.Builder();
|
||||
builder.setName(in.readString());
|
||||
builder.setRegistrationState(in.readInt());
|
||||
builder.setConnectionId(in.readInt());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteDevice[] newArray(int size) {
|
||||
return new RemoteDevice[size];
|
||||
}
|
||||
};
|
||||
|
||||
private RemoteDevice(
|
||||
@Nullable String name,
|
||||
@RegistrationState int registrationState,
|
||||
@NonNull int connectionId) {
|
||||
this.mName = name;
|
||||
this.mRegistrationState = registrationState;
|
||||
this.mConnectionId = connectionId;
|
||||
}
|
||||
|
||||
/** Gets the name of the {@link RemoteDevice} device. */
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/** Returns registration state of the {@link RemoteDevice}. */
|
||||
public @RegistrationState int getRegistrationState() {
|
||||
return mRegistrationState;
|
||||
}
|
||||
|
||||
/** Returns connection id of the {@link RemoteDevice}. */
|
||||
@NonNull
|
||||
public int getConnectionId() {
|
||||
return mConnectionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns a string representation of {@link RemoteDevice}. */
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("RemoteDevice [");
|
||||
sb.append("name=").append(mName).append(", ");
|
||||
sb.append("registered=").append(mRegistrationState).append(", ");
|
||||
sb.append("connectionId=").append(mConnectionId);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Returns true if this {@link RemoteDevice} object is equals to other. */
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof RemoteDevice) {
|
||||
RemoteDevice otherDevice = (RemoteDevice) other;
|
||||
return Objects.equals(this.mName, otherDevice.mName)
|
||||
&& this.getRegistrationState() == otherDevice.getRegistrationState()
|
||||
&& this.mConnectionId == otherDevice.mConnectionId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mName, mRegistrationState, mConnectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for writing {@link RemoteDevice} to a Parcel.
|
||||
*
|
||||
* @param dest The Parcel in which the object should be written.
|
||||
* @param flags Additional flags about how the object should be written.
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
String name = getName();
|
||||
dest.writeString(name);
|
||||
dest.writeInt(getRegistrationState());
|
||||
dest.writeInt(getConnectionId());
|
||||
}
|
||||
|
||||
/** Builder for {@link RemoteDevice} objects. */
|
||||
public static final class Builder {
|
||||
@Nullable private String mName;
|
||||
// represents if device is already registered
|
||||
private @RegistrationState int mRegistrationState;
|
||||
private int mConnectionId;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder(final int connectionId) {
|
||||
this.mConnectionId = connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the {@link RemoteDevice} device.
|
||||
*
|
||||
* @param name of the {@link RemoteDevice}. Can be {@code null} if there is no name.
|
||||
*/
|
||||
@NonNull
|
||||
public RemoteDevice.Builder setName(@Nullable String name) {
|
||||
this.mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the registration state of the {@link RemoteDevice} device.
|
||||
*
|
||||
* @param registrationState of the {@link RemoteDevice}.
|
||||
*/
|
||||
@NonNull
|
||||
public RemoteDevice.Builder setRegistrationState(@RegistrationState int registrationState) {
|
||||
this.mRegistrationState = registrationState;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connectionInfo of the {@link RemoteDevice} device.
|
||||
*
|
||||
* @param connectionId of the RemoteDevice.
|
||||
*/
|
||||
@NonNull
|
||||
public RemoteDevice.Builder setConnectionId(int connectionId) {
|
||||
this.mConnectionId = connectionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link RemoteDevice} instance.
|
||||
*
|
||||
* @return the configured {@link RemoteDevice} instance.
|
||||
*/
|
||||
@NonNull
|
||||
public RemoteDevice build() {
|
||||
return new RemoteDevice(mName, mRegistrationState, mConnectionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,24 @@ java_library {
|
||||
defaults: [
|
||||
"framework-system-server-module-defaults"
|
||||
],
|
||||
libs: [],
|
||||
static_libs: [],
|
||||
libs: [
|
||||
"androidx.annotation_annotation",
|
||||
"framework-bluetooth",
|
||||
"error_prone_annotations",
|
||||
"framework-configinfrastructure",
|
||||
"framework-connectivity-pre-jarjar",
|
||||
"framework-connectivity-t-pre-jarjar",
|
||||
"framework-statsd",
|
||||
],
|
||||
static_libs: [
|
||||
"libprotobuf-java-lite",
|
||||
"fast-pair-lite-protos",
|
||||
"modules-utils-build",
|
||||
"modules-utils-handlerexecutor",
|
||||
"modules-utils-preconditions",
|
||||
"modules-utils-backgroundthread",
|
||||
"presence-lite-protos",
|
||||
],
|
||||
sdk_version: "system_server_current",
|
||||
// This is included in service-connectivity which is 30+
|
||||
// TODO (b/293613362): allow APEXes to have service jars with higher min_sdk than the APEX
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.Context;
|
||||
import android.remoteauth.IDeviceDiscoveryListener;
|
||||
import android.remoteauth.IRemoteAuthService;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
/** Service implementing remoteauth functionality. */
|
||||
public class RemoteAuthService extends IRemoteAuthService.Stub {
|
||||
public static final String TAG = "RemoteAuthService";
|
||||
|
||||
public RemoteAuthService(Context context) {
|
||||
Preconditions.checkNotNull(context);
|
||||
// TODO(b/290280702): Create here RemoteConnectivityManager and RangingManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoteAuthSupported() {
|
||||
// TODO(b/297301535): checkPermission(mContext, MANAGE_REMOTE_AUTH);
|
||||
// TODO(b/290676192): integrate with RangingManager
|
||||
// (check if UWB is supported by this device)
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerDiscoveryListener(
|
||||
IDeviceDiscoveryListener deviceDiscoveryListener,
|
||||
@UserIdInt int userId,
|
||||
int timeoutMs,
|
||||
String packageName,
|
||||
@Nullable String attributionTag) {
|
||||
// TODO(b/297301535): checkPermission(mContext, MANAGE_REMOTE_AUTH);
|
||||
// TODO(b/290280702): implement register discovery logic
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDiscoveryListener(
|
||||
IDeviceDiscoveryListener deviceDiscoveryListener,
|
||||
@UserIdInt int userId,
|
||||
String packageName,
|
||||
@Nullable String attributionTag) {
|
||||
// TODO(b/297301535): checkPermission(mContext, MANAGE_REMOTE_AUTH);
|
||||
// TODO(b/290094221): implement unregister logic
|
||||
}
|
||||
|
||||
private static void checkPermission(Context context, String permission) {
|
||||
context.enforceCallingOrSelfPermission(permission,
|
||||
"Must have " + permission + " permission.");
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ android_test {
|
||||
"androidx.test.rules",
|
||||
"framework-remoteauth-static",
|
||||
"junit",
|
||||
"libprotobuf-java-lite",
|
||||
"platform-test-annotations",
|
||||
"service-remoteauth-pre-jarjar",
|
||||
"truth-prebuilt",
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.platform.test.annotations.Presubmit;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -31,6 +32,9 @@ import org.junit.runner.RunWith;
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class RemoteAuthManagerTest {
|
||||
@Before
|
||||
public void setUp() {}
|
||||
|
||||
@Test
|
||||
public void testStub() {
|
||||
assertTrue(true);
|
||||
|
||||
@@ -56,6 +56,7 @@ java_library {
|
||||
"service-connectivity-pre-jarjar",
|
||||
"service-nearby-pre-jarjar",
|
||||
"service-thread-pre-jarjar",
|
||||
"service-remoteauth-pre-jarjar",
|
||||
"ServiceConnectivityResources",
|
||||
"unsupportedappusage",
|
||||
],
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import android.content.Context;
|
||||
import android.remoteauth.RemoteAuthManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
@@ -25,6 +26,7 @@ import com.android.server.connectivity.ConnectivityNativeService;
|
||||
import com.android.server.ethernet.EthernetService;
|
||||
import com.android.server.ethernet.EthernetServiceImpl;
|
||||
import com.android.server.nearby.NearbyService;
|
||||
import com.android.server.remoteauth.RemoteAuthService;
|
||||
|
||||
/**
|
||||
* Connectivity service initializer for core networking. This is called by system server to create
|
||||
@@ -38,6 +40,7 @@ public final class ConnectivityServiceInitializer extends SystemService {
|
||||
private final NsdService mNsdService;
|
||||
private final NearbyService mNearbyService;
|
||||
private final EthernetServiceImpl mEthernetServiceImpl;
|
||||
private final RemoteAuthService mRemoteAuthService;
|
||||
|
||||
public ConnectivityServiceInitializer(Context context) {
|
||||
super(context);
|
||||
@@ -49,6 +52,7 @@ public final class ConnectivityServiceInitializer extends SystemService {
|
||||
mConnectivityNative = createConnectivityNativeService(context);
|
||||
mNsdService = createNsdService(context);
|
||||
mNearbyService = createNearbyService(context);
|
||||
mRemoteAuthService = createRemoteAuthService(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,6 +89,11 @@ public final class ConnectivityServiceInitializer extends SystemService {
|
||||
/* allowIsolated= */ false);
|
||||
}
|
||||
|
||||
if (mRemoteAuthService != null) {
|
||||
Log.i(TAG, "Registering " + RemoteAuthManager.REMOTE_AUTH_SERVICE);
|
||||
publishBinderService(RemoteAuthManager.REMOTE_AUTH_SERVICE, mRemoteAuthService,
|
||||
/* allowIsolated= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,6 +149,20 @@ public final class ConnectivityServiceInitializer extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/** Return RemoteAuth service instance */
|
||||
private RemoteAuthService createRemoteAuthService(final Context context) {
|
||||
if (!SdkLevel.isAtLeastV()) return null;
|
||||
try {
|
||||
return new RemoteAuthService(context);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// RemoteAuth is not yet supported in all branches
|
||||
// TODO: remove catch clause when it is available.
|
||||
Log.i(TAG, "Skipping unsupported service "
|
||||
+ RemoteAuthManager.REMOTE_AUTH_SERVICE);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EthernetServiceImpl instance or null if current SDK is lower than T or Ethernet
|
||||
* service isn't necessary.
|
||||
|
||||
Reference in New Issue
Block a user