Merge "Auto-grant background execution and data access"

This commit is contained in:
TreeHugger Robot
2017-02-16 06:51:04 +00:00
committed by Android (Google) Code Review
16 changed files with 185 additions and 97 deletions

View File

@@ -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 \

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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
*/
@@ -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
* <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));
}
},

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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

View File

@@ -815,6 +815,16 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<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. -->

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}