Merge "Use ServiceConnector and @DataClass in companion service"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fb3ddfc41d
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* Copyright (C) 2019 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.
|
||||
@@ -10,16 +10,9 @@
|
||||
* 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 per missions and
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.companion;
|
||||
|
||||
/** @hide */
|
||||
interface ICompanionDeviceDiscoveryServiceCallback {
|
||||
@UnsupportedAppUsage
|
||||
oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
|
||||
@UnsupportedAppUsage
|
||||
oneway void onDeviceSelectionCancel();
|
||||
}
|
||||
parcelable Association;
|
||||
179
core/java/android/companion/Association.java
Normal file
179
core/java/android/companion/Association.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.companion;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.DataClass;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A record indicating that a device with a given address was confirmed by the user to be
|
||||
* associated to a given companion app
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@DataClass(genEqualsHashCode = true, genToString = true)
|
||||
public class Association implements Parcelable {
|
||||
|
||||
public final int userId;
|
||||
public final @NonNull String deviceAddress;
|
||||
public final @NonNull String companionAppPackage;
|
||||
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.13.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/companion/Association.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
//@formatter:off
|
||||
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public Association(
|
||||
int userId,
|
||||
@NonNull String deviceAddress,
|
||||
@NonNull String companionAppPackage) {
|
||||
this.userId = userId;
|
||||
this.deviceAddress = deviceAddress;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, deviceAddress);
|
||||
this.companionAppPackage = companionAppPackage;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, companionAppPackage);
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public String toString() {
|
||||
// You can override field toString logic by defining methods like:
|
||||
// String fieldNameToString() { ... }
|
||||
|
||||
return "Association { " +
|
||||
"userId = " + userId + ", " +
|
||||
"deviceAddress = " + deviceAddress + ", " +
|
||||
"companionAppPackage = " + companionAppPackage +
|
||||
" }";
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public boolean equals(@Nullable Object o) {
|
||||
// You can override field equality logic by defining either of the methods like:
|
||||
// boolean fieldNameEquals(Association other) { ... }
|
||||
// boolean fieldNameEquals(FieldType otherValue) { ... }
|
||||
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@SuppressWarnings("unchecked")
|
||||
Association that = (Association) o;
|
||||
//noinspection PointlessBooleanExpression
|
||||
return true
|
||||
&& userId == that.userId
|
||||
&& Objects.equals(deviceAddress, that.deviceAddress)
|
||||
&& Objects.equals(companionAppPackage, that.companionAppPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int hashCode() {
|
||||
// You can override field hashCode logic by defining methods like:
|
||||
// int fieldNameHashCode() { ... }
|
||||
|
||||
int _hash = 1;
|
||||
_hash = 31 * _hash + userId;
|
||||
_hash = 31 * _hash + Objects.hashCode(deviceAddress);
|
||||
_hash = 31 * _hash + Objects.hashCode(companionAppPackage);
|
||||
return _hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
// You can override field parcelling by defining methods like:
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
dest.writeInt(userId);
|
||||
dest.writeString(deviceAddress);
|
||||
dest.writeString(companionAppPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int describeContents() { return 0; }
|
||||
|
||||
/** @hide */
|
||||
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||
@DataClass.Generated.Member
|
||||
protected Association(@NonNull Parcel in) {
|
||||
// You can override field unparcelling by defining methods like:
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
|
||||
int _userId = in.readInt();
|
||||
String _deviceAddress = in.readString();
|
||||
String _companionAppPackage = in.readString();
|
||||
|
||||
this.userId = _userId;
|
||||
this.deviceAddress = _deviceAddress;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, deviceAddress);
|
||||
this.companionAppPackage = _companionAppPackage;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, companionAppPackage);
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public static final @NonNull Parcelable.Creator<Association> CREATOR
|
||||
= new Parcelable.Creator<Association>() {
|
||||
@Override
|
||||
public Association[] newArray(int size) {
|
||||
return new Association[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association createFromParcel(@NonNull Parcel in) {
|
||||
return new Association(in);
|
||||
}
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1573767103332L,
|
||||
codegenVersion = "1.0.13",
|
||||
sourceFile = "frameworks/base/core/java/android/companion/Association.java",
|
||||
inputSignatures = "public final int userId\npublic final @android.annotation.NonNull java.lang.String deviceAddress\npublic final @android.annotation.NonNull java.lang.String companionAppPackage\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
//@formatter:on
|
||||
// End of generated code
|
||||
|
||||
}
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
package android.companion;
|
||||
|
||||
import android.companion.Association;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
|
||||
import android.companion.IFindDeviceCallback;
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
|
||||
|
||||
/** @hide */
|
||||
@@ -27,5 +28,5 @@ interface ICompanionDeviceDiscoveryService {
|
||||
in AssociationRequest request,
|
||||
in String callingPackage,
|
||||
in IFindDeviceCallback findCallback,
|
||||
in ICompanionDeviceDiscoveryServiceCallback serviceCallback);
|
||||
in AndroidFuture<Association> serviceCallback);
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
package com.android.internal.infra;
|
||||
|
||||
/** @hide */
|
||||
parcelable AndroidFuture;
|
||||
parcelable AndroidFuture<T>;
|
||||
|
||||
59
core/java/com/android/internal/infra/PerUser.java
Normal file
59
core/java/com/android/internal/infra/PerUser.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.internal.infra;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A {@link SparseArray} customized for a common use-case of storing state per-user.
|
||||
*
|
||||
* Unlike a normal {@link SparseArray} this will always create a value on {@link #get} if one is
|
||||
* not present instead of returning null.
|
||||
*
|
||||
* @param <T> user state type
|
||||
*/
|
||||
public abstract class PerUser<T> extends SparseArray<T> {
|
||||
|
||||
/**
|
||||
* Initialize state for the given user
|
||||
*/
|
||||
protected abstract @NonNull T create(int userId);
|
||||
|
||||
/**
|
||||
* Same as {@link #get(int)}, renamed for readability.
|
||||
*
|
||||
* This will never return null, deferring to {@link #create} instead
|
||||
* when called for the first time.
|
||||
*/
|
||||
public @NonNull T forUser(int userId) {
|
||||
return get(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull T get(int userId) {
|
||||
T userState = super.get(userId);
|
||||
if (userState != null) {
|
||||
return userState;
|
||||
} else {
|
||||
userState = Preconditions.checkNotNull(create(userId));
|
||||
put(userId, userState);
|
||||
return userState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package com.android.internal.util;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ExceptionUtils;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
@@ -51,6 +52,13 @@ public class FunctionalUtils {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #uncheckExceptions(ThrowingConsumer)
|
||||
*/
|
||||
public static <A, B> BiConsumer<A, B> uncheckExceptions(ThrowingBiConsumer<A, B> action) {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #uncheckExceptions(ThrowingConsumer)
|
||||
*/
|
||||
@@ -185,4 +193,29 @@ public class FunctionalUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BiConsumer} that allows throwing checked exceptions from its single abstract method.
|
||||
*
|
||||
* Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression
|
||||
* that throws a checked exception into a regular {@link Function}
|
||||
*
|
||||
* @param <A> see {@link BiConsumer}
|
||||
* @param <B> see {@link BiConsumer}
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@SuppressWarnings("FunctionalInterfaceMethodChanged")
|
||||
public interface ThrowingBiConsumer<A, B> extends BiConsumer<A, B> {
|
||||
/** @see ThrowingFunction */
|
||||
void acceptOrThrow(A a, B b) throws Exception;
|
||||
|
||||
@Override
|
||||
default void accept(A a, B b) {
|
||||
try {
|
||||
acceptOrThrow(a, b);
|
||||
} catch (Exception ex) {
|
||||
throw ExceptionUtils.propagate(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,12 @@ import android.bluetooth.le.ScanCallback;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.companion.Association;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.BluetoothDeviceFilter;
|
||||
import android.companion.BluetoothLeDeviceFilter;
|
||||
import android.companion.DeviceFilter;
|
||||
import android.companion.ICompanionDeviceDiscoveryService;
|
||||
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
|
||||
import android.companion.IFindDeviceCallback;
|
||||
import android.companion.WifiDeviceFilter;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -63,6 +63,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
@@ -97,7 +98,7 @@ public class DeviceDiscoveryService extends Service {
|
||||
DevicesAdapter mDevicesAdapter;
|
||||
IFindDeviceCallback mFindCallback;
|
||||
|
||||
ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
|
||||
AndroidFuture<Association> mServiceCallback;
|
||||
boolean mIsScanning = false;
|
||||
@Nullable DeviceChooserActivity mActivity = null;
|
||||
|
||||
@@ -107,7 +108,7 @@ public class DeviceDiscoveryService extends Service {
|
||||
public void startDiscovery(AssociationRequest request,
|
||||
String callingPackage,
|
||||
IFindDeviceCallback findCallback,
|
||||
ICompanionDeviceDiscoveryServiceCallback serviceCallback) {
|
||||
AndroidFuture serviceCallback) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG,
|
||||
"startDiscovery() called with: filter = [" + request
|
||||
@@ -303,23 +304,12 @@ public class DeviceDiscoveryService extends Service {
|
||||
}
|
||||
|
||||
void onDeviceSelected(String callingPackage, String deviceAddress) {
|
||||
try {
|
||||
mServiceCallback.onDeviceSelected(
|
||||
//TODO is this the right userId?
|
||||
callingPackage, getUserId(), deviceAddress);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(LOG_TAG, "Failed to record association: "
|
||||
+ callingPackage + " <-> " + deviceAddress);
|
||||
}
|
||||
mServiceCallback.complete(new Association(getUserId(), deviceAddress, callingPackage));
|
||||
}
|
||||
|
||||
void onCancel() {
|
||||
if (DEBUG) Log.i(LOG_TAG, "onCancel()");
|
||||
try {
|
||||
mServiceCallback.onDeviceSelectionCancel();
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
mServiceCallback.cancel(true);
|
||||
}
|
||||
|
||||
class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package com.android.server.companion;
|
||||
|
||||
import static com.android.internal.util.CollectionUtils.size;
|
||||
import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
|
||||
import static com.android.internal.util.Preconditions.checkArgument;
|
||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||
import static com.android.internal.util.Preconditions.checkState;
|
||||
@@ -26,16 +27,15 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainRunna
|
||||
import android.annotation.CheckResult;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.PendingIntent;
|
||||
import android.companion.Association;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.companion.ICompanionDeviceDiscoveryService;
|
||||
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
|
||||
import android.companion.ICompanionDeviceManager;
|
||||
import android.companion.IFindDeviceCallback;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.FeatureInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
@@ -67,6 +67,9 @@ import android.util.Xml;
|
||||
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
import com.android.internal.infra.PerUser;
|
||||
import com.android.internal.infra.ServiceConnector;
|
||||
import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
@@ -118,12 +121,13 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
private final CompanionDeviceManagerImpl mImpl;
|
||||
private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>();
|
||||
private IDeviceIdleController mIdleController;
|
||||
private ServiceConnection mServiceConnection;
|
||||
private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
|
||||
private IAppOpsService mAppOpsManager;
|
||||
|
||||
private IFindDeviceCallback mFindDeviceCallback;
|
||||
private AssociationRequest mRequest;
|
||||
private String mCallingPackage;
|
||||
private AndroidFuture<Association> mOngoingDeviceDiscovery;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@@ -134,6 +138,19 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
|
||||
mAppOpsManager = IAppOpsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.APP_OPS_SERVICE));
|
||||
|
||||
Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
|
||||
mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
|
||||
@Override
|
||||
protected ServiceConnector<ICompanionDeviceDiscoveryService> create(int userId) {
|
||||
return new ServiceConnector.Impl<>(
|
||||
getContext(),
|
||||
serviceIntent, 0/* bindingFlags */, userId,
|
||||
ICompanionDeviceDiscoveryService.Stub::asInterface);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
registerPackageMonitor();
|
||||
}
|
||||
|
||||
@@ -187,7 +204,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
|
||||
private void cleanup() {
|
||||
synchronized (mLock) {
|
||||
mServiceConnection = unbind(mServiceConnection);
|
||||
AndroidFuture<Association> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
|
||||
if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
|
||||
ongoingDeviceDiscovery.cancel(true);
|
||||
}
|
||||
mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
|
||||
mRequest = null;
|
||||
mCallingPackage = null;
|
||||
@@ -207,15 +227,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@CheckResult
|
||||
private ServiceConnection unbind(@Nullable ServiceConnection conn) {
|
||||
if (conn != null) {
|
||||
getContext().unbindService(conn);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
|
||||
|
||||
@Override
|
||||
@@ -243,13 +254,27 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
checkCallerIsSystemOr(callingPackage);
|
||||
int userId = getCallingUserId();
|
||||
checkUsesFeature(callingPackage, userId);
|
||||
|
||||
mFindDeviceCallback = callback;
|
||||
mRequest = request;
|
||||
mCallingPackage = callingPackage;
|
||||
callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
|
||||
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
getContext().bindServiceAsUser(
|
||||
new Intent().setComponent(SERVICE_TO_BIND_TO),
|
||||
createServiceConnection(request, callback, callingPackage),
|
||||
Context.BIND_AUTO_CREATE,
|
||||
UserHandle.of(userId));
|
||||
mOngoingDeviceDiscovery = mServiceConnectors.forUser(userId).postAsync(service -> {
|
||||
AndroidFuture<Association> future = new AndroidFuture<>();
|
||||
service.startDiscovery(request, callingPackage, callback, future);
|
||||
return future;
|
||||
}).whenComplete(uncheckExceptions((association, err) -> {
|
||||
if (err == null) {
|
||||
addAssociation(association);
|
||||
} else {
|
||||
Log.e(LOG_TAG, "Failed to discover device(s)", err);
|
||||
callback.onFailure("No devices found: " + err.getMessage());
|
||||
}
|
||||
cleanup();
|
||||
}));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingIdentity);
|
||||
}
|
||||
@@ -386,82 +411,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
return Binder.getCallingUid() == Process.SYSTEM_UID;
|
||||
}
|
||||
|
||||
private ServiceConnection createServiceConnection(
|
||||
final AssociationRequest request,
|
||||
final IFindDeviceCallback findDeviceCallback,
|
||||
final String callingPackage) {
|
||||
mServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG,
|
||||
"onServiceConnected(name = " + name + ", service = "
|
||||
+ service + ")");
|
||||
}
|
||||
|
||||
mFindDeviceCallback = findDeviceCallback;
|
||||
mRequest = request;
|
||||
mCallingPackage = callingPackage;
|
||||
|
||||
try {
|
||||
mFindDeviceCallback.asBinder().linkToDeath(
|
||||
CompanionDeviceManagerService.this, 0);
|
||||
} catch (RemoteException e) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ICompanionDeviceDiscoveryService.Stub
|
||||
.asInterface(service)
|
||||
.startDiscovery(
|
||||
request,
|
||||
callingPackage,
|
||||
findDeviceCallback,
|
||||
getServiceCallback());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(LOG_TAG, "Error while initiating device discovery", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
|
||||
}
|
||||
};
|
||||
return mServiceConnection;
|
||||
}
|
||||
|
||||
private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
|
||||
return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
|
||||
|
||||
@Override
|
||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
||||
throws RemoteException {
|
||||
try {
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(LOG_TAG, "Error during IPC", e);
|
||||
throw ExceptionUtils.propagate(e, RemoteException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
|
||||
addAssociation(userId, packageName, deviceAddress);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelectionCancel() {
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void addAssociation(int userId, String packageName, String deviceAddress) {
|
||||
updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
|
||||
recordAssociation(packageName, deviceAddress);
|
||||
addAssociation(new Association(userId, deviceAddress, packageName));
|
||||
}
|
||||
|
||||
void addAssociation(Association association) {
|
||||
updateSpecialAccessPermissionForAssociatedPackage(
|
||||
association.companionAppPackage, association.userId);
|
||||
recordAssociation(association);
|
||||
}
|
||||
|
||||
void removeAssociation(int userId, String pkg, String deviceMacAddress) {
|
||||
@@ -525,14 +482,15 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
}, getContext(), packageName, userId).recycleOnUse());
|
||||
}
|
||||
|
||||
private void recordAssociation(String priviledgedPackage, String deviceAddress) {
|
||||
private void recordAssociation(Association association) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
|
||||
+ ", deviceAddress = " + deviceAddress + ")");
|
||||
Log.i(LOG_TAG, "recordAssociation(" + association + ")");
|
||||
}
|
||||
int userId = getCallingUserId();
|
||||
updateAssociations(associations -> CollectionUtils.add(associations,
|
||||
new Association(userId, deviceAddress, priviledgedPackage)));
|
||||
updateAssociations(associations -> CollectionUtils.add(associations, association));
|
||||
}
|
||||
|
||||
private void recordAssociation(String privilegedPackage, String deviceAddress) {
|
||||
recordAssociation(new Association(getCallingUserId(), deviceAddress, privilegedPackage));
|
||||
}
|
||||
|
||||
private void updateAssociations(Function<Set<Association>, Set<Association>> update) {
|
||||
@@ -629,41 +587,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class Association {
|
||||
public final int uid;
|
||||
public final String deviceAddress;
|
||||
public final String companionAppPackage;
|
||||
|
||||
private Association(int uid, String deviceAddress, String companionAppPackage) {
|
||||
this.uid = uid;
|
||||
this.deviceAddress = checkNotNull(deviceAddress);
|
||||
this.companionAppPackage = checkNotNull(companionAppPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Association that = (Association) o;
|
||||
|
||||
if (uid != that.uid) return false;
|
||||
if (!deviceAddress.equals(that.deviceAddress)) return false;
|
||||
return companionAppPackage.equals(that.companionAppPackage);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = uid;
|
||||
result = 31 * result + deviceAddress.hashCode();
|
||||
result = 31 * result + companionAppPackage.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private class ShellCmd extends ShellCommand {
|
||||
public static final String USAGE = "help\n"
|
||||
+ "list USER_ID\n"
|
||||
|
||||
Reference in New Issue
Block a user