diff options
| author | 2017-02-15 10:28:51 -0800 | |
|---|---|---|
| committer | 2017-02-15 20:32:41 -0800 | |
| commit | da0acdf938f1d6e7a978e143d5d80d8dd5af52ad (patch) | |
| tree | a87f84a6afb69607c20513adb4730af5daf7ff92 | |
| parent | 3d52f79be4dba94f046709fabc1bfb911a670709 (diff) | |
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
16 files changed, 185 insertions, 97 deletions
diff --git a/Android.mk b/Android.mk index 28adbcaf88fc..7a8b1b763b4c 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 a03ef38035fb..c5005080ab2b 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 406d51c4f428..54de0c6fe473 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 1be19ed32858..b9cf94d0d7e7 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 fb927e96d1f5..6dd31a852172 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<String, Integer> sRuntimePermToOp = new HashMap<>(); + private static HashMap<String, Integer> 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 b379c7c57554..c0c1a4dd198b 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 + * <p>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.</p> * * @see AssociationRequest */ @@ -47,6 +45,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 + * <p>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})</p> + * + * <p>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.</p> * * @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 index ff2a7eb957f0..4d779639888e 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 index c9dd345341b2..7af708e94d97 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 065e31be9adf..1d30ada25c62 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 index 4867eadd2577..919e15198efa 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 cd02fbbedb7e..97fbfa5a55b6 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" /> + <!-- Allows an app to run in the background. + <p>Protection level: signature + --> + <permission android:name="android.permission.RUN_IN_BACKGROUND" + android:label="@string/permlab_runInBackground" + android:description="@string/permdesc_runInBackground" + android:protectionLevel="signature" /> + + <!-- Allows an app to use data in the background. + <p>Protection level: signature + --> + <permission android:name="android.permission.USE_DATA_IN_BACKGROUND" + android:label="@string/permlab_useDataInBackground" + android:description="@string/permdesc_useDataInBackground" + android:protectionLevel="signature" /> + <!-- ================================== --> <!-- Permissions affecting the system wallpaper --> <!-- ================================== --> @@ -2996,7 +3012,7 @@ any metadata and intents attached. @hide --> <permission android:name="android.permission.ACCESS_NOTIFICATIONS" - android:protectionLevel="signature|privileged" /> + android:protectionLevel="signature|privileged|appop" /> <!-- Marker permission for applications that wish to access notification policy. <p>Protection level: normal diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 23098668c082..8faa76cda808 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -816,6 +816,16 @@ <string name="permdesc_systemAlertWindow">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.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_runInBackground">run in the background</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_runInBackground">This app can run in the background. This may drain battery faster.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_useDataInBackground">use data in the background</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_useDataInBackground">This app can use data in the background. This may increase data usage.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_persistentActivity">make app always run</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_persistentActivity" product="tablet">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the tablet.</string> diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java index 8a970da474e6..25127efad502 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 ccbee2ae196e..11c722d7676c 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<BluetoothDevice> 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 9da94b3007ee..06b6f66203aa 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 9824c1d12613..9ac8295e816d 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() { - - @Override - public void onSuccess(PendingIntent launcher) - throws RemoteException { - if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")"); - recordSpecialPriviledgesForPackage(callingPackage); - propagateTo.onSuccess(launcher); - } - + private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() { + return new ICompanionDeviceDiscoveryServiceCallback.Stub() { @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); + } } } |