Merge "Add RemoteAuthService" into main

This commit is contained in:
Igor Zaslavsky
2023-08-24 20:02:42 +00:00
committed by Gerrit Code Review
19 changed files with 817 additions and 8 deletions

View File

@@ -203,6 +203,8 @@ bootclasspath_fragment {
// result in a build failure due to inconsistent flags. // result in a build failure due to inconsistent flags.
package_prefixes: [ package_prefixes: [
"android.nearby.aidl", "android.nearby.aidl",
"android.remoteauth.aidl",
"android.remoteauth",
"android.net.apf", "android.net.apf",
"android.net.connectivity", "android.net.connectivity",
"android.net.http.apihelpers", "android.net.http.apihelpers",

View File

@@ -43,6 +43,7 @@ java_defaults {
":framework-connectivity-tiramisu-updatable-sources", ":framework-connectivity-tiramisu-updatable-sources",
":framework-nearby-java-sources", ":framework-nearby-java-sources",
":framework-thread-sources", ":framework-thread-sources",
":framework-remoteauth-java-sources",
], ],
libs: [ libs: [
"unsupportedappusage", "unsupportedappusage",
@@ -130,8 +131,10 @@ java_sdk_library {
"android.net", "android.net",
"android.net.nsd", "android.net.nsd",
"android.nearby", "android.nearby",
"android.remoteauth",
"com.android.connectivity", "com.android.connectivity",
"com.android.nearby", "com.android.nearby",
"com.android.remoteauth",
], ],
hidden_api: { hidden_api: {
@@ -153,6 +156,7 @@ java_sdk_library {
"//packages/modules/Connectivity/service", // For R8 only "//packages/modules/Connectivity/service", // For R8 only
"//packages/modules/Connectivity/service-t", "//packages/modules/Connectivity/service-t",
"//packages/modules/Connectivity/nearby:__subpackages__", "//packages/modules/Connectivity/nearby:__subpackages__",
"//packages/modules/Connectivity/remoteauth:__subpackages__",
"//frameworks/base", "//frameworks/base",
// Tests using hidden APIs // Tests using hidden APIs

View File

@@ -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);
}
}

View File

@@ -62,7 +62,6 @@ java_defaults {
":framework-connectivity-sources", ":framework-connectivity-sources",
":net-utils-framework-common-srcs", ":net-utils-framework-common-srcs",
":framework-connectivity-api-shared-srcs", ":framework-connectivity-api-shared-srcs",
":framework-remoteauth-java-sources",
], ],
aidl: { aidl: {
generate_get_transaction_name: true, generate_get_transaction_name: true,
@@ -153,7 +152,6 @@ java_sdk_library {
"//packages/modules/Connectivity/framework-t", "//packages/modules/Connectivity/framework-t",
"//packages/modules/Connectivity/service", "//packages/modules/Connectivity/service",
"//packages/modules/Connectivity/service-t", "//packages/modules/Connectivity/service-t",
"//packages/modules/Connectivity/remoteauth:__subpackages__",
"//frameworks/base/packages/Connectivity/service", "//frameworks/base/packages/Connectivity/service",
"//frameworks/base", "//frameworks/base",

View File

@@ -7,7 +7,7 @@
// TODO(b/193602229): uncomment once it's supported. // TODO(b/193602229): uncomment once it's supported.
//"mainline-presubmit": [ //"mainline-presubmit": [
// { // {
// "name": "RemoteAuthUnitTests[com.google.android.tethering.apex]" // "name": "RemoteAuthUnitTests[com.google.android.remoteauth.apex]"
// } // }
//] //]
} }

View File

@@ -25,7 +25,7 @@ filegroup {
], ],
path: "java", path: "java",
visibility: [ visibility: [
"//packages/modules/Connectivity/framework:__subpackages__", "//packages/modules/Connectivity/framework-t:__subpackages__",
], ],
} }
@@ -43,7 +43,13 @@ java_library {
name: "framework-remoteauth-static", name: "framework-remoteauth-static",
srcs: [":framework-remoteauth-java-sources"], srcs: [":framework-remoteauth-java-sources"],
sdk_version: "module_current", sdk_version: "module_current",
libs: [], libs: [
static_libs: [], "androidx.annotation_annotation",
"framework-annotations-lib",
"framework-bluetooth",
],
static_libs: [
"modules-utils-preconditions",
],
visibility: ["//packages/modules/Connectivity/remoteauth/tests:__subpackages__"], visibility: ["//packages/modules/Connectivity/remoteauth/tests:__subpackages__"],
} }

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
});
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;

View 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);
}
}
}

View File

@@ -29,8 +29,24 @@ java_library {
defaults: [ defaults: [
"framework-system-server-module-defaults" "framework-system-server-module-defaults"
], ],
libs: [], libs: [
static_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", sdk_version: "system_server_current",
// This is included in service-connectivity which is 30+ // 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 // TODO (b/293613362): allow APEXes to have service jars with higher min_sdk than the APEX

View File

@@ -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.");
}
}

View File

@@ -37,6 +37,7 @@ android_test {
"androidx.test.rules", "androidx.test.rules",
"framework-remoteauth-static", "framework-remoteauth-static",
"junit", "junit",
"libprotobuf-java-lite",
"platform-test-annotations", "platform-test-annotations",
"service-remoteauth-pre-jarjar", "service-remoteauth-pre-jarjar",
"truth-prebuilt", "truth-prebuilt",

View File

@@ -23,6 +23,7 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -31,6 +32,9 @@ import org.junit.runner.RunWith;
@SmallTest @SmallTest
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class RemoteAuthManagerTest { public class RemoteAuthManagerTest {
@Before
public void setUp() {}
@Test @Test
public void testStub() { public void testStub() {
assertTrue(true); assertTrue(true);

View File

@@ -56,6 +56,7 @@ java_library {
"service-connectivity-pre-jarjar", "service-connectivity-pre-jarjar",
"service-nearby-pre-jarjar", "service-nearby-pre-jarjar",
"service-thread-pre-jarjar", "service-thread-pre-jarjar",
"service-remoteauth-pre-jarjar",
"ServiceConnectivityResources", "ServiceConnectivityResources",
"unsupportedappusage", "unsupportedappusage",
], ],

View File

@@ -17,6 +17,7 @@
package com.android.server; package com.android.server;
import android.content.Context; import android.content.Context;
import android.remoteauth.RemoteAuthManager;
import android.util.Log; import android.util.Log;
import com.android.modules.utils.build.SdkLevel; 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.EthernetService;
import com.android.server.ethernet.EthernetServiceImpl; import com.android.server.ethernet.EthernetServiceImpl;
import com.android.server.nearby.NearbyService; 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 * 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 NsdService mNsdService;
private final NearbyService mNearbyService; private final NearbyService mNearbyService;
private final EthernetServiceImpl mEthernetServiceImpl; private final EthernetServiceImpl mEthernetServiceImpl;
private final RemoteAuthService mRemoteAuthService;
public ConnectivityServiceInitializer(Context context) { public ConnectivityServiceInitializer(Context context) {
super(context); super(context);
@@ -49,6 +52,7 @@ public final class ConnectivityServiceInitializer extends SystemService {
mConnectivityNative = createConnectivityNativeService(context); mConnectivityNative = createConnectivityNativeService(context);
mNsdService = createNsdService(context); mNsdService = createNsdService(context);
mNearbyService = createNearbyService(context); mNearbyService = createNearbyService(context);
mRemoteAuthService = createRemoteAuthService(context);
} }
@Override @Override
@@ -85,6 +89,11 @@ public final class ConnectivityServiceInitializer extends SystemService {
/* allowIsolated= */ false); /* allowIsolated= */ false);
} }
if (mRemoteAuthService != null) {
Log.i(TAG, "Registering " + RemoteAuthManager.REMOTE_AUTH_SERVICE);
publishBinderService(RemoteAuthManager.REMOTE_AUTH_SERVICE, mRemoteAuthService,
/* allowIsolated= */ false);
}
} }
@Override @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 * Return EthernetServiceImpl instance or null if current SDK is lower than T or Ethernet
* service isn't necessary. * service isn't necessary.