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 c8e84c36b3a3b..15d6995925e04 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 fd84e838564b2..05fc04019ff87 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 752986ce91d41..ac4f3e38caa98 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); + } } }