DO NOT MERGE Add listener ids for location listening operations

Bug: 153257294
Test: presubmits
Change-Id: I12654a3afac5362383caba3cea1c5e0a2b8ce1d9
This commit is contained in:
Soonil Nagarkar
2020-04-07 17:48:48 -07:00
parent bd745f763a
commit 45e623c63a
5 changed files with 62 additions and 19 deletions

View File

@@ -47,10 +47,10 @@ interface ILocationManager
Location getLastLocation(in LocationRequest request, String packageName, String featureId);
boolean getCurrentLocation(in LocationRequest request,
in ICancellationSignal cancellationSignal, in ILocationListener listener,
String packageName, String featureId);
String packageName, String featureId, String listenerId);
void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
in PendingIntent intent, String packageName, String featureId);
in PendingIntent intent, String packageName, String featureId, String listenerId);
void removeUpdates(in ILocationListener listener, in PendingIntent intent);
void requestGeofence(in LocationRequest request, in Geofence geofence,

View File

@@ -718,7 +718,7 @@ public class LocationManager {
currentLocationRequest.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
}
GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor,
GetCurrentLocationTransport transport = new GetCurrentLocationTransport(executor,
consumer);
if (cancellationSignal != null) {
@@ -729,14 +729,15 @@ public class LocationManager {
try {
if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
listenerTransport, mContext.getPackageName(), mContext.getAttributionTag())) {
listenerTransport.register(mContext.getSystemService(AlarmManager.class),
transport, mContext.getPackageName(), mContext.getAttributionTag(),
transport.getListenerId())) {
transport.register(mContext.getSystemService(AlarmManager.class),
remoteCancellationSignal);
if (cancellationSignal != null) {
cancellationSignal.setOnCancelListener(listenerTransport::cancel);
cancellationSignal.setOnCancelListener(transport::cancel);
}
} else {
listenerTransport.fail();
transport.fail();
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1175,7 +1176,8 @@ public class LocationManager {
boolean registered = false;
try {
mService.requestLocationUpdates(locationRequest, transport, null,
mContext.getPackageName(), mContext.getAttributionTag());
mContext.getPackageName(), mContext.getAttributionTag(),
transport.getListenerId());
registered = true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1220,7 +1222,7 @@ public class LocationManager {
try {
mService.requestLocationUpdates(locationRequest, null, pendingIntent,
mContext.getPackageName(), mContext.getAttributionTag());
mContext.getPackageName(), mContext.getAttributionTag(), null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2558,6 +2560,10 @@ public class LocationManager {
mRemoteCancellationSignal = null;
}
public String getListenerId() {
return mConsumer.getClass().getName() + "@" + System.identityHashCode(mConsumer);
}
public synchronized void register(AlarmManager alarmManager,
ICancellationSignal remoteCancellationSignal) {
if (mConsumer == null) {
@@ -2683,6 +2689,10 @@ public class LocationManager {
return mListener;
}
public String getListenerId() {
return mListener.getClass().getName() + "@" + System.identityHashCode(mListener);
}
public void register(@NonNull Executor executor) {
Preconditions.checkArgument(executor != null, "invalid null executor");
mExecutor = executor;

View File

@@ -1836,12 +1836,13 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
PendingIntent intent, String packageName, String featureId) {
PendingIntent intent, String packageName, String featureId, String listenerId) {
if (request == null) {
request = DEFAULT_LOCATION_REQUEST;
}
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId,
listenerId);
identity.enforceLocationPermission();
WorkSource workSource = request.getWorkSource();
@@ -2027,7 +2028,7 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean getCurrentLocation(LocationRequest locationRequest,
ICancellationSignal remoteCancellationSignal, ILocationListener listener,
String packageName, String featureId) {
String packageName, String featureId, String listenerId) {
// side effect of validating locationRequest and packageName
Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
if (lastLocation != null) {
@@ -2052,7 +2053,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
requestLocationUpdates(locationRequest, listener, null, packageName, featureId);
requestLocationUpdates(locationRequest, listener, null, packageName, featureId, listenerId);
CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
remoteCancellationSignal);
if (cancellationSignal != null) {

View File

@@ -191,7 +191,7 @@ public class AppOpsHelper {
callerIdentity.uid,
callerIdentity.packageName,
callerIdentity.featureId,
null) == AppOpsManager.MODE_ALLOWED;
callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -210,7 +210,7 @@ public class AppOpsHelper {
callerIdentity.packageName,
false,
callerIdentity.featureId,
null) == AppOpsManager.MODE_ALLOWED;
callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -245,7 +245,7 @@ public class AppOpsHelper {
callerIdentity.uid,
callerIdentity.packageName,
callerIdentity.featureId,
null) == AppOpsManager.MODE_ALLOWED;
callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
} finally {
Binder.restoreCallingIdentity(identity);
}

View File

@@ -83,12 +83,22 @@ public final class CallerIdentity {
*/
public static CallerIdentity fromBinder(Context context, String packageName,
@Nullable String featureId) {
return fromBinder(context, packageName, featureId, null);
}
/**
* Creates a CallerIdentity from the current binder identity, using the given package, feature
* id, and listener id. The package will be checked to enforce it belongs to the calling uid,
* and a security exception will be thrown if it is invalid.
*/
public static CallerIdentity fromBinder(Context context, String packageName,
@Nullable String featureId, @Nullable String listenerId) {
int uid = Binder.getCallingUid();
if (!ArrayUtils.contains(context.getPackageManager().getPackagesForUid(uid), packageName)) {
throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
}
return fromBinderUnsafe(context, packageName, featureId);
return fromBinderUnsafe(context, packageName, featureId, listenerId);
}
/**
@@ -99,8 +109,19 @@ public final class CallerIdentity {
*/
public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
@Nullable String featureId) {
return fromBinderUnsafe(context, packageName, featureId, null);
}
/**
* Creates a CallerIdentity from the current binder identity, using the given package, feature
* id, and listener id. The package will not be checked to enforce that it belongs to the
* calling uid - this method should only be used if the package will be validated by some other
* means, such as an appops call.
*/
public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
@Nullable String featureId, @Nullable String listenerId) {
return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(),
UserHandle.getCallingUserId(), packageName, featureId,
UserHandle.getCallingUserId(), packageName, featureId, listenerId,
getBinderPermissionLevel(context));
}
@@ -157,6 +178,9 @@ public final class CallerIdentity {
/** The calling feature id. */
public final @Nullable String featureId;
/** The calling listener id. */
public final @Nullable String listenerId;
/**
* The calling location permission level. This field should only be used for validating
* permissions for API access. It should not be used for validating permissions for location
@@ -167,11 +191,18 @@ public final class CallerIdentity {
@VisibleForTesting
public CallerIdentity(int uid, int pid, int userId, String packageName,
@Nullable String featureId, @PermissionLevel int permissionLevel) {
this(uid, pid, userId, packageName, featureId, null, permissionLevel);
}
private CallerIdentity(int uid, int pid, int userId, String packageName,
@Nullable String featureId, @Nullable String listenerId,
@PermissionLevel int permissionLevel) {
this.uid = uid;
this.pid = pid;
this.userId = userId;
this.packageName = Objects.requireNonNull(packageName);
this.featureId = featureId;
this.listenerId = listenerId;
this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE,
PERMISSION_FINE, "permissionLevel");
}
@@ -216,7 +247,8 @@ public final class CallerIdentity {
return uid == that.uid
&& pid == that.pid
&& packageName.equals(that.packageName)
&& Objects.equals(featureId, that.featureId);
&& Objects.equals(featureId, that.featureId)
&& Objects.equals(listenerId, that.listenerId);
}
@Override