diff options
-rw-r--r-- | core/java/android/companion/Association.aidl (renamed from core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl) | 13 | ||||
-rw-r--r-- | core/java/android/companion/Association.java | 179 | ||||
-rw-r--r-- | core/java/android/companion/ICompanionDeviceDiscoveryService.aidl | 5 | ||||
-rw-r--r-- | core/java/com/android/internal/infra/AndroidFuture.aidl | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/infra/PerUser.java | 59 | ||||
-rw-r--r-- | core/java/com/android/internal/util/FunctionalUtils.java | 33 | ||||
-rw-r--r-- | packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java | 22 | ||||
-rw-r--r-- | services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java | 189 |
8 files changed, 340 insertions, 162 deletions
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/Association.aidl index c9dc019bd2f2..2a28f1f094ad 100644 --- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl +++ b/core/java/android/companion/Association.aidl @@ -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; diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java new file mode 100644 index 000000000000..3fa6a3e76634 --- /dev/null +++ b/core/java/android/companion/Association.java @@ -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 + +} diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl index 5398c3cea68d..5e3d46caae91 100644 --- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl +++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl @@ -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); } diff --git a/core/java/com/android/internal/infra/AndroidFuture.aidl b/core/java/com/android/internal/infra/AndroidFuture.aidl index b19aab8ab0d5..5f623b183168 100644 --- a/core/java/com/android/internal/infra/AndroidFuture.aidl +++ b/core/java/com/android/internal/infra/AndroidFuture.aidl @@ -17,4 +17,4 @@ package com.android.internal.infra; /** @hide */ -parcelable AndroidFuture; +parcelable AndroidFuture<T>; diff --git a/core/java/com/android/internal/infra/PerUser.java b/core/java/com/android/internal/infra/PerUser.java new file mode 100644 index 000000000000..560ca8cff8df --- /dev/null +++ b/core/java/com/android/internal/infra/PerUser.java @@ -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; + } + } +} diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java index b955f672fe93..3c9791791a68 100644 --- a/core/java/com/android/internal/util/FunctionalUtils.java +++ b/core/java/com/android/internal/util/FunctionalUtils.java @@ -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; @@ -54,6 +55,13 @@ public class FunctionalUtils { /** * @see #uncheckExceptions(ThrowingConsumer) */ + public static <A, B> BiConsumer<A, B> uncheckExceptions(ThrowingBiConsumer<A, B> action) { + return action; + } + + /** + * @see #uncheckExceptions(ThrowingConsumer) + */ public static <T> Supplier<T> uncheckExceptions(ThrowingSupplier<T> action) { return action; } @@ -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); + } + } + } } diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index d11b5c573ca9..7aa997e39307 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -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> { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 8f1e1568ead6..e976811a3094 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -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) { + addAssociation(new Association(userId, deviceAddress, packageName)); } - void addAssociation(int userId, String packageName, String deviceAddress) { - updateSpecialAccessPermissionForAssociatedPackage(packageName, userId); - recordAssociation(packageName, deviceAddress); + 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" |