From da0acdf938f1d6e7a978e143d5d80d8dd5af52ad Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Wed, 15 Feb 2017 10:28:51 -0800 Subject: [PATCH] Auto-grant background execution and data access Companion apps can declare they want background access and background execution exceptions via dedicated permissions in their manifest. If such a permission is requested we auto-grant the corresponding exception after the user has chosen a device from the companion UI. These permissions are appop ones allowing us to use the app ops for gauging whether the user has made a change after we auto-granted the permission since we would like to revoke these special privileges when the app disassociates itself from the companion device if the user did not make an excplicit choice otherwise. While at this auto-grant fixed location permission to the companion device discovery service. Test: manual Change-Id: I46ee4291e5e5a8f7613f0dd75eb61d6b9341f306 --- Android.mk | 6 +- api/current.txt | 2 + api/system-current.txt | 2 + api/test-current.txt | 2 + core/java/android/app/AppOpsManager.java | 29 +++--- .../companion/CompanionDeviceManager.java | 36 ++++--- ... => ICompanionDeviceDiscoveryService.aidl} | 11 ++- ...panionDeviceDiscoveryServiceCallback.aidl} | 6 +- .../companion/ICompanionDeviceManager.aidl | 6 +- ...Callback.aidl => IFindDeviceCallback.aidl} | 2 +- core/res/AndroidManifest.xml | 18 +++- core/res/res/values/strings.xml | 10 ++ .../DeviceChooserActivity.java | 6 +- .../DeviceDiscoveryService.java | 37 ++++--- .../pm/DefaultPermissionGrantPolicy.java | 11 +++ .../print/CompanionDeviceManagerService.java | 98 +++++++++++-------- 16 files changed, 185 insertions(+), 97 deletions(-) rename core/java/android/companion/{ICompanionDeviceManagerService.aidl => ICompanionDeviceDiscoveryService.aidl} (71%) rename core/java/android/companion/{ICompanionDeviceManagerServiceCallback.aidl => ICompanionDeviceDiscoveryServiceCallback.aidl} (81%) rename core/java/android/companion/{IOnAssociateCallback.aidl => IFindDeviceCallback.aidl} (96%) diff --git a/Android.mk b/Android.mk index 28adbcaf88fc1..7a8b1b763b4c8 100644 --- a/Android.mk +++ b/Android.mk @@ -295,9 +295,9 @@ LOCAL_SRC_FILES += \ core/java/android/printservice/IPrintService.aidl \ core/java/android/printservice/IPrintServiceClient.aidl \ core/java/android/companion/ICompanionDeviceManager.aidl \ - core/java/android/companion/ICompanionDeviceManagerService.aidl \ - core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl \ - core/java/android/companion/IOnAssociateCallback.aidl \ + core/java/android/companion/ICompanionDeviceDiscoveryService.aidl \ + core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl \ + core/java/android/companion/IFindDeviceCallback.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \ diff --git a/api/current.txt b/api/current.txt index a03ef38035fbd..c5005080ab2b2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -121,6 +121,7 @@ package android { field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; + field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM"; @@ -139,6 +140,7 @@ package android { field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR"; field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT"; field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS"; + field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND"; field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; field public static final java.lang.String USE_SIP = "android.permission.USE_SIP"; field public static final java.lang.String VIBRATE = "android.permission.VIBRATE"; diff --git a/api/system-current.txt b/api/system-current.txt index 406d51c4f428c..54de0c6fe473e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -211,6 +211,7 @@ package android { field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; + field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND"; field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; @@ -248,6 +249,7 @@ package android { field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS"; field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK"; field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY"; + field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND"; field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; field public static final java.lang.String USE_SIP = "android.permission.USE_SIP"; field public static final java.lang.String VIBRATE = "android.permission.VIBRATE"; diff --git a/api/test-current.txt b/api/test-current.txt index 1be19ed328580..b9cf94d0d7e76 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -121,6 +121,7 @@ package android { field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; + field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM"; @@ -139,6 +140,7 @@ package android { field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR"; field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT"; field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS"; + field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND"; field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; field public static final java.lang.String USE_SIP = "android.permission.USE_SIP"; field public static final java.lang.String VIBRATE = "android.permission.VIBRATE"; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index fb927e96d1f5f..6dd31a8521721 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -357,7 +357,8 @@ public class AppOpsManager { public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground"; - private static final int[] RUNTIME_PERMISSIONS_OPS = { + private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = { + // RUNTIME PERMISSIONS // Contacts OP_READ_CONTACTS, OP_WRITE_CONTACTS, @@ -392,7 +393,13 @@ public class AppOpsManager { // Camera OP_CAMERA, // Body sensors - OP_BODY_SENSORS + OP_BODY_SENSORS, + + // APPOP PERMISSIONS + OP_ACCESS_NOTIFICATIONS, + OP_SYSTEM_ALERT_WINDOW, + OP_WRITE_SETTINGS, + OP_REQUEST_INSTALL_PACKAGES, }; /** @@ -926,9 +933,9 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // OP_RUN_IN_BACKGROUND AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ACCESSIBILITY_VOLUME AppOpsManager.MODE_ALLOWED, - AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES + AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES AppOpsManager.MODE_ALLOWED, // OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE - AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND + AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND }; /** @@ -1018,7 +1025,7 @@ public class AppOpsManager { /** * Mapping from a permission to the corresponding app op. */ - private static HashMap sRuntimePermToOp = new HashMap<>(); + private static HashMap sPermToOp = new HashMap<>(); static { if (sOpToSwitch.length != _NUM_OP) { @@ -1058,9 +1065,9 @@ public class AppOpsManager { sOpStrToOp.put(sOpToString[i], i); } } - for (int op : RUNTIME_PERMISSIONS_OPS) { + for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) { if (sOpPerms[op] != null) { - sRuntimePermToOp.put(sOpPerms[op], op); + sPermToOp.put(sOpPerms[op], op); } } } @@ -1112,12 +1119,12 @@ public class AppOpsManager { /** * Retrieve the app op code for a permission, or null if there is not one. - * This API is intended to be used for mapping runtime permissions to the - * corresponding app op. + * This API is intended to be used for mapping runtime or appop permissions + * to the corresponding app op. * @hide */ public static int permissionToOpCode(String permission) { - Integer boxedOpCode = sRuntimePermToOp.get(permission); + Integer boxedOpCode = sPermToOp.get(permission); return boxedOpCode != null ? boxedOpCode : OP_NONE; } @@ -1462,7 +1469,7 @@ public class AppOpsManager { * @return The app op associated with the permission or null. */ public static String permissionToOp(String permission) { - final Integer opCode = sRuntimePermToOp.get(permission); + final Integer opCode = sPermToOp.get(permission); if (opCode == null) { return null; } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index b379c7c57554f..c0c1a4dd198b5 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -29,12 +29,10 @@ import android.os.RemoteException; /** * System level service for managing companion devices * - * Usage: - * To obtain an instance call - * {@link Context#getSystemService}({@link Context#COMPANION_DEVICE_SERVICE}) - * - * Then, call {@link #associate} to initiate the flow of associating current package - * with a device selected by user + *

To obtain an instance call {@link Context#getSystemService}({@link + * Context#COMPANION_DEVICE_SERVICE}) Then, call {@link #associate(AssociationRequest, + * Callback, Handler)} to initiate the flow of associating current package with a + * device selected by user.

* * @see AssociationRequest */ @@ -46,6 +44,14 @@ public final class CompanionDeviceManager { */ public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE"; + /** + * The package name of the companion device discovery component. + * + * @hide + */ + public static final String COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME = + "com.android.companiondevicemanager"; + /** * A callback to receive once at least one suitable device is found, or the search failed * (e.g. timed out) @@ -81,13 +87,20 @@ public final class CompanionDeviceManager { /** * Associate this app with a companion device, selected by user * - * Once at least one appropriate device is found, {@code callback} will be called with a + *

Once at least one appropriate device is found, {@code callback} will be called with a * {@link PendingIntent} that can be used to show the list of available devices for the user * to select. * It should be started for result (i.e. using * {@link android.app.Activity#startIntentSenderForResult}), as the resulting * {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected - * device. (e.g. {@link android.bluetooth.BluetoothDevice}) + * device. (e.g. {@link android.bluetooth.BluetoothDevice})

+ * + *

If your app needs to be excluded from battery optimizations (run in the background) + * or to have unrestricted data access (use data in the background) you can declare that + * you use the {@link android.Manifest.permission#RUN_IN_BACKGROUND} and {@link + * android.Manifest.permission#USE_DATA_IN_BACKGROUND} respectively. Note that these + * special capabilities have a negative effect on the device's battery and user's data + * usage, therefore you should requested them when absolutely necessary.

* * @param request specific details about this request * @param callback will be called once there's at least one device found for user to choose from @@ -106,17 +119,16 @@ public final class CompanionDeviceManager { try { mService.associate( request, - new IOnAssociateCallback.Stub() { - + new IFindDeviceCallback.Stub() { @Override - public void onSuccess(PendingIntent launcher) throws RemoteException { + public void onSuccess(PendingIntent launcher) { finalHandler.post(() -> { callback.onDeviceFound(launcher.getIntentSender()); }); } @Override - public void onFailure(CharSequence reason) throws RemoteException { + public void onFailure(CharSequence reason) { finalHandler.post(() -> callback.onFailure(reason)); } }, diff --git a/core/java/android/companion/ICompanionDeviceManagerService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl similarity index 71% rename from core/java/android/companion/ICompanionDeviceManagerService.aidl rename to core/java/android/companion/ICompanionDeviceDiscoveryService.aidl index ff2a7eb957f0f..4d779639888ee 100644 --- a/core/java/android/companion/ICompanionDeviceManagerService.aidl +++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl @@ -17,13 +17,14 @@ package android.companion; import android.companion.AssociationRequest; -import android.companion.IOnAssociateCallback; - +import android.companion.ICompanionDeviceDiscoveryServiceCallback; +import android.companion.IFindDeviceCallback; /** @hide */ -interface ICompanionDeviceManagerService { +interface ICompanionDeviceDiscoveryService { void startDiscovery( in AssociationRequest request, - in IOnAssociateCallback callback, - in String callingPackage); + in String callingPackage, + in IFindDeviceCallback findCallback, + in ICompanionDeviceDiscoveryServiceCallback serviceCallback); } diff --git a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl similarity index 81% rename from core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl rename to core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl index c9dd345341b23..7af708e94d976 100644 --- a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl +++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl @@ -16,9 +16,7 @@ package android.companion; -import android.bluetooth.BluetoothDevice; - /** @hide */ -interface ICompanionDeviceManagerServiceCallback { - void onDeviceSelected(in BluetoothDevice device); +interface ICompanionDeviceDiscoveryServiceCallback { + void onDeviceSelected(String packageName, int userId); } diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index 065e31be9adf3..1d30ada25c62c 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -16,7 +16,7 @@ package android.companion; -import android.companion.IOnAssociateCallback; +import android.companion.IFindDeviceCallback; import android.companion.AssociationRequest; /** @@ -26,8 +26,8 @@ import android.companion.AssociationRequest; */ interface ICompanionDeviceManager { void associate(in AssociationRequest request, - in IOnAssociateCallback callback, - in String callingPackage); //TODO int userId? + in IFindDeviceCallback callback, + in String callingPackage); //TODO add these // boolean haveNotificationAccess(String packageName); diff --git a/core/java/android/companion/IOnAssociateCallback.aidl b/core/java/android/companion/IFindDeviceCallback.aidl similarity index 96% rename from core/java/android/companion/IOnAssociateCallback.aidl rename to core/java/android/companion/IFindDeviceCallback.aidl index 4867eadd25772..919e15198efaa 100644 --- a/core/java/android/companion/IOnAssociateCallback.aidl +++ b/core/java/android/companion/IFindDeviceCallback.aidl @@ -19,7 +19,7 @@ package android.companion; import android.app.PendingIntent; /** @hide */ -interface IOnAssociateCallback { +interface IFindDeviceCallback { void onSuccess(in PendingIntent launcher); void onFailure(in CharSequence reason); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cd02fbbedb7eb..97fbfa5a55b67 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1813,6 +1813,22 @@ android:description="@string/permdesc_systemAlertWindow" android:protectionLevel="signature|preinstalled|appop|pre23|development" /> + + + + + + @@ -2996,7 +3012,7 @@ any metadata and intents attached. @hide --> + android:protectionLevel="signature|privileged|appop" /> This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear. + + run in the background + + This app can run in the background. This may drain battery faster. + + + use data in the background + + This app can use data in the background. This may increase data usage. + make app always run diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java index 8a970da474e64..25127efad5020 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java @@ -33,7 +33,6 @@ import android.view.View; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; public class DeviceChooserActivity extends Activity { @@ -129,12 +128,9 @@ public class DeviceChooserActivity extends Activity { } protected void onPairTapped(BluetoothDevice selectedDevice) { + getService().onDeviceSelected(); setResult(RESULT_OK, new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice)); finish(); } - - private void toast(String msg) { - Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); - } } \ No newline at end of file diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index ccbee2ae196e6..11c722d7676c1 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -32,16 +32,15 @@ import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.companion.AssociationRequest; -import android.companion.BluetoothDeviceFilterUtils; import android.companion.BluetoothLEDeviceFilter; -import android.companion.ICompanionDeviceManagerService; -import android.companion.IOnAssociateCallback; +import android.companion.ICompanionDeviceDiscoveryService; +import android.companion.ICompanionDeviceDiscoveryServiceCallback; +import android.companion.IFindDeviceCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; -import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.IBinder; import android.os.RemoteException; @@ -70,21 +69,25 @@ public class DeviceDiscoveryService extends Service { List mDevicesFound; BluetoothDevice mSelectedDevice; DevicesAdapter mDevicesAdapter; - IOnAssociateCallback mCallback; + IFindDeviceCallback mFindCallback; + ICompanionDeviceDiscoveryServiceCallback mServiceCallback; String mCallingPackage; - private final ICompanionDeviceManagerService mBinder = - new ICompanionDeviceManagerService.Stub() { + private final ICompanionDeviceDiscoveryService mBinder = + new ICompanionDeviceDiscoveryService.Stub() { @Override public void startDiscovery(AssociationRequest request, - IOnAssociateCallback callback, - String callingPackage) throws RemoteException { + String callingPackage, + IFindDeviceCallback findCallback, + ICompanionDeviceDiscoveryServiceCallback serviceCallback) { if (DEBUG) { Log.i(LOG_TAG, - "startDiscovery() called with: filter = [" + request + "], callback = [" - + callback + "]"); + "startDiscovery() called with: filter = [" + request + + "], findCallback = [" + findCallback + "]" + + "], serviceCallback = [" + serviceCallback + "]"); } - mCallback = callback; + mFindCallback = findCallback; + mServiceCallback = serviceCallback; mCallingPackage = callingPackage; DeviceDiscoveryService.this.startDiscovery(request); } @@ -171,6 +174,14 @@ public class DeviceDiscoveryService extends Service { return super.onUnbind(intent); } + public void onDeviceSelected() { + try { + mServiceCallback.onDeviceSelected(mCallingPackage, getUserId()); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Error reporting selected device"); + } + } + private void stopScan() { if (DEBUG) Log.i(LOG_TAG, "stopScan() called"); mBluetoothAdapter.cancelDiscovery(); @@ -205,7 +216,7 @@ public class DeviceDiscoveryService extends Service { //TODO also, on timeout -> call onFailure private void onReadyToShowUI() { try { - mCallback.onSuccess(PendingIntent.getActivity( + mFindCallback.onSuccess(PendingIntent.getActivity( this, 0, new Intent(this, DeviceChooserActivity.class), PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 9da94b3007eeb..06b6f66203aa4 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -20,6 +20,7 @@ import android.Manifest; import android.annotation.NonNull; import android.app.DownloadManager; import android.app.admin.DevicePolicyManager; +import android.companion.CompanionDeviceManager; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -673,6 +674,16 @@ final class DefaultPermissionGrantPolicy { && doesPackageSupportRuntimePermissions(storageManagerPckg)) { grantRuntimePermissionsLPw(storageManagerPckg, STORAGE_PERMISSIONS, true, userId); } + + // Companion devices + PackageParser.Package companionDeviceDiscoveryPackage = getSystemPackageLPr( + CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME); + if (companionDeviceDiscoveryPackage != null + && doesPackageSupportRuntimePermissions(companionDeviceDiscoveryPackage)) { + grantRuntimePermissionsLPw(companionDeviceDiscoveryPackage, + LOCATION_PERMISSIONS, true, userId); + } + mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId); } } diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java index 9824c1d126130..9ac8295e816da 100644 --- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java +++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java @@ -19,20 +19,28 @@ package com.android.server.print; import static com.android.internal.util.Preconditions.checkNotNull; -import android.app.PendingIntent; +import android.Manifest; import android.companion.AssociationRequest; +import android.companion.CompanionDeviceManager; +import android.companion.ICompanionDeviceDiscoveryService; +import android.companion.ICompanionDeviceDiscoveryServiceCallback; import android.companion.ICompanionDeviceManager; -import android.companion.ICompanionDeviceManagerService; -import android.companion.IOnAssociateCallback; +import android.companion.IFindDeviceCallback; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.NetworkPolicyManager; import android.os.Binder; import android.os.IBinder; +import android.os.IDeviceIdleController; import android.os.RemoteException; -import android.util.Log; +import android.os.ServiceManager; +import android.util.Slog; +import com.android.internal.util.ArrayUtils; import com.android.server.SystemService; //TODO move to own package! @@ -40,7 +48,8 @@ import com.android.server.SystemService; public class CompanionDeviceManagerService extends SystemService { private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative( - "com.android.companiondevicemanager", ".DeviceDiscoveryService"); + CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, + ".DeviceDiscoveryService"); private static final boolean DEBUG = false; private static final String LOG_TAG = "CompanionDeviceManagerService"; @@ -58,14 +67,13 @@ public class CompanionDeviceManagerService extends SystemService { } class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub { - @Override public void associate( AssociationRequest request, - IOnAssociateCallback callback, - String callingPackage) throws RemoteException { + IFindDeviceCallback callback, + String callingPackage) { if (DEBUG) { - Log.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback + Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback + ", callingPackage = " + callingPackage + ")"); } checkNotNull(request); @@ -85,23 +93,24 @@ public class CompanionDeviceManagerService extends SystemService { private ServiceConnection getServiceConnection( final AssociationRequest request, - final IOnAssociateCallback callback, + final IFindDeviceCallback findDeviceCallback, final String callingPackage) { return new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) { - Log.i(LOG_TAG, + Slog.i(LOG_TAG, "onServiceConnected(name = " + name + ", service = " + service + ")"); } try { - ICompanionDeviceManagerService.Stub + ICompanionDeviceDiscoveryService.Stub .asInterface(service) .startDiscovery( request, - getCallback(callingPackage, callback), - callingPackage); + callingPackage, + findDeviceCallback, + getServiceCallback()); } catch (RemoteException e) { throw new RuntimeException(e); } @@ -109,39 +118,50 @@ public class CompanionDeviceManagerService extends SystemService { @Override public void onServiceDisconnected(ComponentName name) { - if (DEBUG) Log.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")"); + if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")"); } }; } - private IOnAssociateCallback.Stub getCallback( - String callingPackage, - IOnAssociateCallback propagateTo) { - return new IOnAssociateCallback.Stub() { - + private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() { + return new ICompanionDeviceDiscoveryServiceCallback.Stub() { @Override - public void onSuccess(PendingIntent launcher) - throws RemoteException { - if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")"); - recordSpecialPriviledgesForPackage(callingPackage); - propagateTo.onSuccess(launcher); - } - - @Override - public void onFailure(CharSequence reason) throws RemoteException { - if (DEBUG) Log.i(LOG_TAG, "onFailure()"); - propagateTo.onFailure(reason); + public void onDeviceSelected(String packageName, int userId) { + grantSpecialAccessPermissionsIfNeeded(packageName, userId); } }; } - void recordSpecialPriviledgesForPackage(String priviledgedPackage) { - //TODO Show dialog before recording notification access -// final SettingStringHelper setting = -// new SettingStringHelper( -// getContext().getContentResolver(), -// Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, -// Binder.getCallingUid()); -// setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage)); + private void grantSpecialAccessPermissionsIfNeeded(String packageName, int userId) { + final long identity = Binder.clearCallingIdentity(); + final PackageInfo packageInfo; + try { + packageInfo = getContext().getPackageManager().getPackageInfoAsUser( + packageName, PackageManager.GET_PERMISSIONS, userId); + } catch (PackageManager.NameNotFoundException e) { + Slog.e(LOG_TAG, "Error granting special access permissions to package:" + + packageName, e); + return; + } + try { + if (ArrayUtils.contains(packageInfo.requestedPermissions, + Manifest.permission.RUN_IN_BACKGROUND)) { + IDeviceIdleController idleController = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); + try { + idleController.addPowerSaveWhitelistApp(packageName); + } catch (RemoteException e) { + /* ignore - local call */ + } + } + if (ArrayUtils.contains(packageInfo.requestedPermissions, + Manifest.permission.USE_DATA_IN_BACKGROUND)) { + NetworkPolicyManager.from(getContext()).addUidPolicy( + packageInfo.applicationInfo.uid, + NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); + } + } finally { + Binder.restoreCallingIdentity(identity); + } } }