Merge "Activity recognition source app op tracking" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
64b26b5c49
@@ -69,6 +69,7 @@ package android {
|
||||
field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
|
||||
field public static final String BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS";
|
||||
field @Deprecated public static final String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
|
||||
field public static final String BYPASS_ROLE_QUALIFICATION = "android.permission.BYPASS_ROLE_QUALIFICATION";
|
||||
field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED";
|
||||
field public static final String CAMERA_OPEN_CLOSE_LISTENER = "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
|
||||
field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD";
|
||||
|
||||
@@ -233,6 +233,8 @@ package android.app {
|
||||
field public static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
|
||||
field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
|
||||
field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
|
||||
field public static final String OPSTR_ACTIVITY_RECOGNITION = "android:activity_recognition";
|
||||
field public static final String OPSTR_ACTIVITY_RECOGNITION_SOURCE = "android:activity_recognition_source";
|
||||
field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
|
||||
field public static final String OPSTR_PHONE_CALL_CAMERA = "android:phone_call_camera";
|
||||
field public static final String OPSTR_PHONE_CALL_MICROPHONE = "android:phone_call_microphone";
|
||||
|
||||
@@ -1225,9 +1225,19 @@ public class AppOpsManager {
|
||||
/** @hide */
|
||||
public static final int OP_UWB_RANGING = AppProtoEnums.APP_OP_UWB_RANGING;
|
||||
|
||||
/**
|
||||
* Activity recognition being accessed by an activity recognition source, which
|
||||
* is a component that already has access since it is the one that detects
|
||||
* activity recognition.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int OP_ACTIVITY_RECOGNITION_SOURCE =
|
||||
AppProtoEnums.APP_OP_ACTIVITY_RECOGNITION_SOURCE;
|
||||
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public static final int _NUM_OP = 113;
|
||||
public static final int _NUM_OP = 114;
|
||||
|
||||
/** Access to coarse location information. */
|
||||
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
|
||||
@@ -1478,6 +1488,7 @@ public class AppOpsManager {
|
||||
public static final String OPSTR_USE_BIOMETRIC = "android:use_biometric";
|
||||
|
||||
/** @hide Recognize physical activity. */
|
||||
@TestApi
|
||||
public static final String OPSTR_ACTIVITY_RECOGNITION = "android:activity_recognition";
|
||||
|
||||
/** @hide Financial app read sms. */
|
||||
@@ -1643,6 +1654,17 @@ public class AppOpsManager {
|
||||
/** @hide */
|
||||
public static final String OPSTR_UWB_RANGING = "android:uwb_ranging";
|
||||
|
||||
/**
|
||||
* Activity recognition being accessed by an activity recognition source, which
|
||||
* is a component that already has access since it is the one that detects
|
||||
* activity recognition.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public static final String OPSTR_ACTIVITY_RECOGNITION_SOURCE =
|
||||
"android:activity_recognition_source";
|
||||
|
||||
/** {@link #sAppOpsToNote} not initialized yet for this op */
|
||||
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
|
||||
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
|
||||
@@ -1853,6 +1875,7 @@ public class AppOpsManager {
|
||||
OP_MANAGE_MEDIA, // MANAGE_MEDIA
|
||||
OP_BLUETOOTH_CONNECT, // OP_BLUETOOTH_CONNECT
|
||||
OP_UWB_RANGING, // OP_UWB_RANGING
|
||||
OP_ACTIVITY_RECOGNITION_SOURCE // OP_ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1972,6 +1995,7 @@ public class AppOpsManager {
|
||||
OPSTR_MANAGE_MEDIA,
|
||||
OPSTR_BLUETOOTH_CONNECT,
|
||||
OPSTR_UWB_RANGING,
|
||||
OPSTR_ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2091,7 +2115,8 @@ public class AppOpsManager {
|
||||
"COARSE_LOCATION_SOURCE",
|
||||
"MANAGE_MEDIA",
|
||||
"BLUETOOTH_CONNECT",
|
||||
"UWB_RANGING"
|
||||
"UWB_RANGING",
|
||||
"ACTIVITY_RECOGNITION_SOURCE"
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2213,6 +2238,7 @@ public class AppOpsManager {
|
||||
Manifest.permission.MANAGE_MEDIA,
|
||||
Manifest.permission.BLUETOOTH_CONNECT,
|
||||
Manifest.permission.UWB_RANGING,
|
||||
null, // no permission for OP_ACTIVITY_RECOGNITION_SOURCE,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2334,6 +2360,7 @@ public class AppOpsManager {
|
||||
null, // MANAGE_MEDIA
|
||||
null, // BLUETOOTH_CONNECT
|
||||
null, // UWB_RANGING
|
||||
null, // ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2454,6 +2481,7 @@ public class AppOpsManager {
|
||||
null, // MANAGE_MEDIA
|
||||
null, // BLUETOOTH_CONNECT
|
||||
null, // UWB_RANGING
|
||||
null // ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2573,6 +2601,7 @@ public class AppOpsManager {
|
||||
AppOpsManager.MODE_DEFAULT, // MANAGE_MEDIA
|
||||
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_CONNECT
|
||||
AppOpsManager.MODE_ALLOWED, // UWB_RANGING
|
||||
AppOpsManager.MODE_ALLOWED, // ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2696,6 +2725,7 @@ public class AppOpsManager {
|
||||
false, // MANAGE_MEDIA
|
||||
false, // BLUETOOTH_CONNECT
|
||||
false, // UWB_RANGING
|
||||
false, // ACTIVITY_RECOGNITION_SOURCE
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -4240,6 +4240,15 @@
|
||||
<permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
|
||||
android:protectionLevel="signature|installer" />
|
||||
|
||||
<!-- @SystemApi Allows an application to bypass role qualification. This allows switching role
|
||||
holders to otherwise non eligible holders. Only the shell is allowed to do this, the
|
||||
qualification for the shell role itself cannot be bypassed, and each role needs to
|
||||
explicitly allow bypassing qualification in its definition. The bypass state will not be
|
||||
persisted across reboot.
|
||||
@hide -->
|
||||
<permission android:name="android.permission.BYPASS_ROLE_QUALIFICATION"
|
||||
android:protectionLevel="internal|role" />
|
||||
|
||||
<!-- @SystemApi Allows an application to observe role holder changes.
|
||||
@hide -->
|
||||
<permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"
|
||||
|
||||
@@ -1932,11 +1932,13 @@
|
||||
<!-- The name of the package that will hold the speech recognizer role by default. -->
|
||||
<string name="config_systemSpeechRecognizer" translatable="false"></string>
|
||||
<!-- The name of the package that will hold the system Wi-Fi coex manager role. -->
|
||||
<string name="config_systemWifiCoexManager" translateable="false"></string>
|
||||
<string name="config_systemWifiCoexManager" translatable="false"></string>
|
||||
<!-- The name of the package that will hold the wellbeing role. -->
|
||||
<string name="config_systemWellbeing" translatable="false"></string>
|
||||
<!-- The name of the package that will hold the television notification handler role -->
|
||||
<string name="config_systemTelevisionNotificationHandler" translatable="false"></string>
|
||||
<!-- The name of the package that will hold the system activity recognizer role. -->
|
||||
<string name="config_systemActivityRecognizer" translatable="false"></string>
|
||||
|
||||
<!-- The name of the package that will be allowed to change its components' label/icon. -->
|
||||
<string name="config_overrideComponentUiPackage" translatable="false"></string>
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
<uses-permission android:name="android.permission.SET_TIME_ZONE" />
|
||||
<uses-permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
|
||||
<uses-permission android:name="android.permission.BYPASS_ROLE_QUALIFICATION" />
|
||||
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
||||
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
|
||||
<uses-permission android:name="android.permission.STATUS_BAR" />
|
||||
|
||||
@@ -21,11 +21,22 @@ import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.AppOpsManagerInternal;
|
||||
import android.app.SyncNotedAppOp;
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.AttributionSource;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManagerInternal;
|
||||
import android.net.Uri;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.function.HeptFunction;
|
||||
@@ -35,6 +46,8 @@ import com.android.internal.util.function.QuadFunction;
|
||||
import com.android.internal.util.function.TriFunction;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -42,9 +55,21 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* This class defines policy for special behaviors around app ops.
|
||||
*/
|
||||
public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegate {
|
||||
private static final String LOG_TAG = AppOpsPolicy.class.getName();
|
||||
|
||||
private static final String ACTIVITY_RECOGNITION_TAGS =
|
||||
"android:activity_recognition_allow_listed_tags";
|
||||
private static final String ACTIVITY_RECOGNITION_TAGS_SEPARATOR = ";";
|
||||
|
||||
@NonNull
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@NonNull
|
||||
private final Context mContext;
|
||||
|
||||
@NonNull
|
||||
private final RoleManager mRoleManager;
|
||||
|
||||
/**
|
||||
* The locking policy around the location tags is a bit special. Since we want to
|
||||
* avoid grabbing the lock on every op note we are taking the approach where the
|
||||
@@ -60,48 +85,57 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
public AppOpsPolicy() {
|
||||
@GuardedBy("mLock - writes only - see above")
|
||||
@NonNull
|
||||
private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>>
|
||||
mActivityRecognitionTags = new ConcurrentHashMap<>();
|
||||
|
||||
public AppOpsPolicy(@NonNull Context context) {
|
||||
mContext = context;
|
||||
mRoleManager = mContext.getSystemService(RoleManager.class);
|
||||
|
||||
final LocationManagerInternal locationManagerInternal = LocalServices.getService(
|
||||
LocationManagerInternal.class);
|
||||
locationManagerInternal.setOnProviderLocationTagsChangeListener((providerTagInfo) -> {
|
||||
synchronized (mLock) {
|
||||
final int uid = providerTagInfo.getUid();
|
||||
// We make a copy of the per UID state to limit our mutation to one
|
||||
// operation in the underlying concurrent data structure.
|
||||
ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
|
||||
if (uidTags != null) {
|
||||
uidTags = new ArrayMap<>(uidTags);
|
||||
}
|
||||
|
||||
final String packageName = providerTagInfo.getPackageName();
|
||||
ArraySet<String> packageTags = (uidTags != null) ? uidTags.get(packageName) : null;
|
||||
if (packageTags != null) {
|
||||
packageTags = new ArraySet<>(packageTags);
|
||||
}
|
||||
|
||||
final Set<String> providerTags = providerTagInfo.getTags();
|
||||
if (providerTags != null && !providerTags.isEmpty()) {
|
||||
if (packageTags != null) {
|
||||
packageTags.clear();
|
||||
packageTags.addAll(providerTags);
|
||||
} else {
|
||||
packageTags = new ArraySet<>(providerTags);
|
||||
}
|
||||
if (uidTags == null) {
|
||||
uidTags = new ArrayMap<>();
|
||||
}
|
||||
uidTags.put(packageName, packageTags);
|
||||
mLocationTags.put(uid, uidTags);
|
||||
} else if (uidTags != null) {
|
||||
uidTags.remove(packageName);
|
||||
if (!uidTags.isEmpty()) {
|
||||
mLocationTags.put(uid, uidTags);
|
||||
} else {
|
||||
mLocationTags.remove(uid);
|
||||
}
|
||||
}
|
||||
updateAllowListedTagsForPackageLocked(providerTagInfo.getUid(),
|
||||
providerTagInfo.getPackageName(), providerTagInfo.getTags(),
|
||||
mLocationTags);
|
||||
}
|
||||
});
|
||||
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
intentFilter.addDataScheme("package");
|
||||
|
||||
context.registerReceiverAsUser(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final Uri uri = intent.getData();
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
final String packageName = uri.getSchemeSpecificPart();
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return;
|
||||
}
|
||||
final List<String> activityRecognizers = mRoleManager.getRoleHolders(
|
||||
RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER);
|
||||
if (activityRecognizers.contains(packageName)) {
|
||||
updateActivityRecognizerTags(packageName);
|
||||
}
|
||||
}
|
||||
}, UserHandle.SYSTEM, intentFilter, null, null);
|
||||
|
||||
mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(),
|
||||
(String roleName, UserHandle user) -> {
|
||||
if (RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER.equals(roleName)) {
|
||||
initializeActivityRecognizersTags();
|
||||
}
|
||||
}, UserHandle.SYSTEM);
|
||||
|
||||
initializeActivityRecognizersTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,7 +155,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
@Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable
|
||||
String message, boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer,
|
||||
String, String, Boolean, String, Boolean, SyncNotedAppOp> superImpl) {
|
||||
return superImpl.apply(resolveOpCode(code, uid, packageName, attributionTag), uid,
|
||||
return superImpl.apply(resolveDatasourceOp(code, uid, packageName, attributionTag), uid,
|
||||
packageName, attributionTag, shouldCollectAsyncNotedOp,
|
||||
message, shouldCollectMessage);
|
||||
}
|
||||
@@ -132,7 +166,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
boolean shouldCollectMessage, boolean skipProxyOperation, @NonNull HexFunction<Integer,
|
||||
AttributionSource, Boolean, String, Boolean, Boolean,
|
||||
SyncNotedAppOp> superImpl) {
|
||||
return superImpl.apply(resolveOpCode(code, attributionSource.getUid(),
|
||||
return superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(),
|
||||
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
|
||||
attributionSource, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
|
||||
skipProxyOperation);
|
||||
@@ -144,7 +178,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
|
||||
boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource,
|
||||
Boolean, Boolean, String, Boolean, Boolean, SyncNotedAppOp> superImpl) {
|
||||
return superImpl.apply(token, resolveOpCode(code, attributionSource.getUid(),
|
||||
return superImpl.apply(token, resolveDatasourceOp(code, attributionSource.getUid(),
|
||||
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
|
||||
attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
|
||||
shouldCollectMessage, skipProxyOperation);
|
||||
@@ -154,36 +188,129 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
public void finishProxyOperation(IBinder clientId, int code,
|
||||
@NonNull AttributionSource attributionSource,
|
||||
@NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
|
||||
superImpl.apply(clientId, resolveOpCode(code, attributionSource.getUid(),
|
||||
superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(),
|
||||
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
|
||||
attributionSource);
|
||||
}
|
||||
|
||||
private int resolveOpCode(int code, int uid, @NonNull String packageName,
|
||||
private int resolveDatasourceOp(int code, int uid, @NonNull String packageName,
|
||||
@Nullable String attributionTag) {
|
||||
if (isHandledOp(code) && attributionTag != null) {
|
||||
// Only a single lookup from the underlying concurrent data structure
|
||||
final ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
|
||||
if (uidTags != null) {
|
||||
final ArraySet<String> packageTags = uidTags.get(packageName);
|
||||
if (packageTags != null && packageTags.contains(attributionTag)) {
|
||||
return resolveHandledOp(code);
|
||||
if (attributionTag == null) {
|
||||
return code;
|
||||
}
|
||||
int resolvedCode = resolveLocationOp(code);
|
||||
if (resolvedCode != code) {
|
||||
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
|
||||
mLocationTags)) {
|
||||
return resolvedCode;
|
||||
}
|
||||
} else {
|
||||
resolvedCode = resolveArOp(code);
|
||||
if (resolvedCode != code) {
|
||||
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
|
||||
mActivityRecognitionTags)) {
|
||||
return resolvedCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private static boolean isHandledOp(int code) {
|
||||
switch (code) {
|
||||
case AppOpsManager.OP_FINE_LOCATION:
|
||||
case AppOpsManager.OP_COARSE_LOCATION:
|
||||
private void initializeActivityRecognizersTags() {
|
||||
final List<String> activityRecognizers = mRoleManager.getRoleHolders(
|
||||
RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER);
|
||||
final int recognizerCount = activityRecognizers.size();
|
||||
if (recognizerCount > 0) {
|
||||
for (int i = 0; i < recognizerCount; i++) {
|
||||
final String activityRecognizer = activityRecognizers.get(i);
|
||||
updateActivityRecognizerTags(activityRecognizer);
|
||||
}
|
||||
} else {
|
||||
clearActivityRecognitionTags();
|
||||
}
|
||||
}
|
||||
|
||||
private void clearActivityRecognitionTags() {
|
||||
synchronized (mLock) {
|
||||
mActivityRecognitionTags.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateActivityRecognizerTags(@NonNull String activityRecognizer) {
|
||||
try {
|
||||
final ApplicationInfo recognizerAppInfo = mContext.getPackageManager()
|
||||
.getApplicationInfoAsUser(activityRecognizer, PackageManager.GET_META_DATA,
|
||||
UserHandle.USER_SYSTEM);
|
||||
if (recognizerAppInfo.metaData == null) {
|
||||
return;
|
||||
}
|
||||
final String tagsList = recognizerAppInfo.metaData.getString(ACTIVITY_RECOGNITION_TAGS);
|
||||
if (tagsList != null) {
|
||||
final String[] tags = tagsList.split(ACTIVITY_RECOGNITION_TAGS_SEPARATOR);
|
||||
synchronized (mLock) {
|
||||
updateAllowListedTagsForPackageLocked(recognizerAppInfo.uid,
|
||||
recognizerAppInfo.packageName, new ArraySet<>(tags),
|
||||
mActivityRecognitionTags);
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.wtf(LOG_TAG, "Missing " + RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER
|
||||
+ " role holder package " + activityRecognizer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateAllowListedTagsForPackageLocked(int uid, String packageName,
|
||||
Set<String> allowListedTags, ConcurrentHashMap<Integer, ArrayMap<String,
|
||||
ArraySet<String>>> datastore) {
|
||||
// We make a copy of the per UID state to limit our mutation to one
|
||||
// operation in the underlying concurrent data structure.
|
||||
ArrayMap<String, ArraySet<String>> uidTags = datastore.get(uid);
|
||||
if (uidTags != null) {
|
||||
uidTags = new ArrayMap<>(uidTags);
|
||||
}
|
||||
|
||||
ArraySet<String> packageTags = (uidTags != null) ? uidTags.get(packageName) : null;
|
||||
if (packageTags != null) {
|
||||
packageTags = new ArraySet<>(packageTags);
|
||||
}
|
||||
|
||||
if (allowListedTags != null && !allowListedTags.isEmpty()) {
|
||||
if (packageTags != null) {
|
||||
packageTags.clear();
|
||||
packageTags.addAll(allowListedTags);
|
||||
} else {
|
||||
packageTags = new ArraySet<>(allowListedTags);
|
||||
}
|
||||
if (uidTags == null) {
|
||||
uidTags = new ArrayMap<>();
|
||||
}
|
||||
uidTags.put(packageName, packageTags);
|
||||
datastore.put(uid, uidTags);
|
||||
} else if (uidTags != null) {
|
||||
uidTags.remove(packageName);
|
||||
if (!uidTags.isEmpty()) {
|
||||
datastore.put(uid, uidTags);
|
||||
} else {
|
||||
datastore.remove(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDatasourceAttributionTag(int uid, @NonNull String packageName,
|
||||
@NonNull String attributionTag, @NonNull Map<Integer, ArrayMap<String,
|
||||
ArraySet<String>>> mappedOps) {
|
||||
// Only a single lookup from the underlying concurrent data structure
|
||||
final ArrayMap<String, ArraySet<String>> uidTags = mappedOps.get(uid);
|
||||
if (uidTags != null) {
|
||||
final ArraySet<String> packageTags = uidTags.get(packageName);
|
||||
if (packageTags != null && packageTags.contains(attributionTag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int resolveHandledOp(int code) {
|
||||
private static int resolveLocationOp(int code) {
|
||||
switch (code) {
|
||||
case AppOpsManager.OP_FINE_LOCATION:
|
||||
return AppOpsManager.OP_FINE_LOCATION_SOURCE;
|
||||
@@ -192,4 +319,11 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private static int resolveArOp(int code) {
|
||||
if (code == AppOpsManager.OP_ACTIVITY_RECOGNITION) {
|
||||
return AppOpsManager.OP_ACTIVITY_RECOGNITION_SOURCE;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2678,7 +2678,7 @@ public final class SystemServer implements Dumpable {
|
||||
|
||||
t.traceBegin("RegisterAppOpsPolicy");
|
||||
try {
|
||||
mActivityManagerService.setAppOpsPolicy(new AppOpsPolicy());
|
||||
mActivityManagerService.setAppOpsPolicy(new AppOpsPolicy(mSystemContext));
|
||||
} catch (Throwable e) {
|
||||
reportWtf("registering app ops policy", e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user