diff options
author | Xin Li <delphij@google.com> | 2020-08-31 21:21:38 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2020-08-31 21:21:38 -0700 |
commit | 628590d7ec80e10a3fc24b1c18a1afb55cca10a8 (patch) | |
tree | 4b1c3f52d86d7fb53afbe9e9438468588fa489f8 /services/companion | |
parent | b11b8ec3aec8bb42f2c07e1c5ac7942da293baa8 (diff) | |
parent | d2d3a20624d968199353ccf6ddbae6f3ac39c9af (diff) |
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507
Merged-In: I3d92a6de21a938f6b352ec26dc23420c0fe02b27
Change-Id: Ifdb80563ef042738778ebb8a7581a97c4e3d96e2
Diffstat (limited to 'services/companion')
-rw-r--r-- | services/companion/Android.bp | 1 | ||||
-rw-r--r-- | services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java | 276 |
2 files changed, 142 insertions, 135 deletions
diff --git a/services/companion/Android.bp b/services/companion/Android.bp index 9677a7d83bfb..e25104227b71 100644 --- a/services/companion/Android.bp +++ b/services/companion/Android.bp @@ -7,6 +7,7 @@ filegroup { java_library_static { name: "services.companion", + defaults: ["services_defaults"], srcs: [":services.companion-sources"], libs: ["services.core"], } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index a4347333685b..a704c58a9b70 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -18,24 +18,29 @@ 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; +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable; +import static java.util.concurrent.TimeUnit.MINUTES; + import android.annotation.CheckResult; import android.annotation.Nullable; +import android.app.AppOpsManager; 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.SharedPreferences; import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; @@ -55,6 +60,7 @@ import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; import android.os.UserHandle; +import android.os.UserManagerInternal; import android.provider.Settings; import android.provider.SettingsStringUtil.ComponentNameSet; import android.text.BidiFormatter; @@ -67,7 +73,11 @@ 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.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.function.pooled.PooledLambda; @@ -109,6 +119,9 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private static final boolean DEBUG = false; private static final String LOG_TAG = "CompanionDeviceManagerService"; + private static final String PREF_FILE_NAME = "companion_device_preferences.xml"; + private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done"; + private static final String XML_TAG_ASSOCIATIONS = "associations"; private static final String XML_TAG_ASSOCIATION = "association"; private static final String XML_ATTR_PACKAGE = "package"; @@ -118,12 +131,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 +148,18 @@ 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(); } @@ -178,6 +204,39 @@ public class CompanionDeviceManagerService extends SystemService implements Bind if (atmInternal != null) { atmInternal.setCompanionAppPackages(userHandle, companionAppPackages); } + + BackgroundThread.getHandler().sendMessageDelayed( + obtainMessage(CompanionDeviceManagerService::maybeGrantAutoRevokeExemptions, this), + MINUTES.toMillis(10)); + } + + void maybeGrantAutoRevokeExemptions() { + PackageManager pm = getContext().getPackageManager(); + for (int userId : LocalServices.getService(UserManagerInternal.class).getUserIds()) { + SharedPreferences pref = getContext().getSharedPreferences( + new File(Environment.getUserSystemDirectory(userId), PREF_FILE_NAME), + Context.MODE_PRIVATE); + if (pref.getBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, false)) { + continue; + } + + try { + Set<Association> associations = readAllAssociations(userId); + if (associations == null) { + continue; + } + for (Association a : associations) { + try { + int uid = pm.getPackageUidAsUser(a.companionAppPackage, userId); + exemptFromAutoRevoke(a.companionAppPackage, uid); + } catch (PackageManager.NameNotFoundException e) { + Log.w(LOG_TAG, "Unknown companion package: " + a.companionAppPackage, e); + } + } + } finally { + pref.edit().putBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, true).apply(); + } + } } @Override @@ -187,7 +246,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 +269,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 +296,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); } @@ -269,8 +336,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public List<String> getAssociations(String callingPackage, int userId) throws RemoteException { - checkCallerIsSystemOr(callingPackage, userId); - checkUsesFeature(callingPackage, getCallingUserId()); + if (!callerCanManageCompanionDevices()) { + checkCallerIsSystemOr(callingPackage, userId); + checkUsesFeature(callingPackage, getCallingUserId()); + } return new ArrayList<>(CollectionUtils.map( readAllAssociations(userId, callingPackage), a -> a.deviceAddress)); @@ -286,6 +355,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind removeAssociation(getCallingUserId(), callingPackage, deviceMacAddress); } + private boolean callerCanManageCompanionDevices() { + return getContext().checkCallingOrSelfPermission( + android.Manifest.permission.MANAGE_COMPANION_DEVICES) + == PackageManager.PERMISSION_GRANTED; + } + private void checkCallerIsSystemOr(String pkg) throws RemoteException { checkCallerIsSystemOr(pkg, getCallingUserId()); } @@ -337,6 +412,24 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return new ComponentNameSet(setting).contains(component); } + @Override + public boolean isDeviceAssociatedForWifiConnection(String packageName, String macAddress, + int userId) { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_COMPANION_DEVICES, "isDeviceAssociated"); + + boolean bypassMacPermission = getContext().getPackageManager().checkPermission( + android.Manifest.permission.COMPANION_APPROVE_WIFI_CONNECTIONS, packageName) + == PackageManager.PERMISSION_GRANTED; + if (bypassMacPermission) { + return true; + } + + return CollectionUtils.any( + readAllAssociations(userId, packageName), + a -> Objects.equals(a.deviceAddress, macAddress)); + } + private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { checkCallerIsSystemOr(callingPackage); int userId = getCallingUserId(); @@ -378,82 +471,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) { @@ -496,6 +521,21 @@ public class CompanionDeviceManagerService extends SystemService implements Bind packageInfo.applicationInfo.uid, NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); } + + exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid); + } + + private void exemptFromAutoRevoke(String packageName, int uid) { + try { + mAppOpsManager.setMode( + AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, + uid, + packageName, + AppOpsManager.MODE_IGNORED); + } catch (RemoteException e) { + Log.w(LOG_TAG, + "Error while granting auto revoke exemption for " + packageName, e); + } } private static <T> boolean containsEither(T[] array, T a, T b) { @@ -517,14 +557,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) { @@ -621,41 +662,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" |