Use compat framework for API behavior
Check compat API behavior using new compat APIs, also use ActivityManager APIs to properly support user paramters on APIs. Bug: 145742912 Test: none Change-Id: Ic86052b59764ad79404b78ba148aaf3220b3c1e5
This commit is contained in:
@@ -33,6 +33,9 @@ import android.annotation.SystemService;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.compat.Compatibility;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledAfter;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -50,7 +53,6 @@ import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
@@ -81,6 +83,36 @@ public class LocationManager {
|
||||
|
||||
private static final String TAG = "LocationManager";
|
||||
|
||||
/**
|
||||
* For apps targeting Android K and above, supplied {@link PendingIntent}s must be targeted to a
|
||||
* specific package.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public static final long TARGETED_PENDING_INTENT = 148963590L;
|
||||
|
||||
/**
|
||||
* For apps targeting Android K and above, incomplete locations may not be passed to
|
||||
* {@link #setTestProviderLocation}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
|
||||
private static final long INCOMPLETE_LOCATION = 148964793L;
|
||||
|
||||
/**
|
||||
* For apps targeting Android S and above, all {@link GpsStatus} API usage must be replaced with
|
||||
* {@link GnssStatus} APIs.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
|
||||
private static final long GPS_STATUS_USAGE = 144027538L;
|
||||
|
||||
/**
|
||||
* Name of the network location provider.
|
||||
*
|
||||
@@ -771,7 +803,6 @@ public class LocationManager {
|
||||
public void requestSingleUpdate(@NonNull String provider,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(provider != null, "invalid null provider");
|
||||
checkPendingIntent(pendingIntent);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
|
||||
provider, 0, 0, true);
|
||||
@@ -800,7 +831,6 @@ public class LocationManager {
|
||||
public void requestSingleUpdate(@NonNull Criteria criteria,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(criteria != null, "invalid null criteria");
|
||||
checkPendingIntent(pendingIntent);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
|
||||
criteria, 0, 0, true);
|
||||
@@ -1021,7 +1051,6 @@ public class LocationManager {
|
||||
public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(provider != null, "invalid null provider");
|
||||
checkPendingIntent(pendingIntent);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
|
||||
provider, minTimeMs, minDistanceM, false);
|
||||
@@ -1048,7 +1077,6 @@ public class LocationManager {
|
||||
public void requestLocationUpdates(long minTimeMs, float minDistanceM,
|
||||
@NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(criteria != null, "invalid null criteria");
|
||||
checkPendingIntent(pendingIntent);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
|
||||
criteria, minTimeMs, minDistanceM, false);
|
||||
@@ -1164,9 +1192,9 @@ public class LocationManager {
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(locationRequest != null, "invalid null location request");
|
||||
Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
|
||||
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) {
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(pendingIntent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to package");
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1198,15 +1226,9 @@ public class LocationManager {
|
||||
*/
|
||||
@RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION})
|
||||
public boolean injectLocation(@NonNull Location location) {
|
||||
if (location == null) {
|
||||
IllegalArgumentException e = new IllegalArgumentException("invalid null location");
|
||||
if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
|
||||
throw e;
|
||||
} else {
|
||||
Log.w(TAG, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Preconditions.checkArgument(location != null, "invalid null location");
|
||||
Preconditions.checkArgument(location.isComplete(),
|
||||
"incomplete location object, missing timestamp or accuracy?");
|
||||
|
||||
try {
|
||||
return mService.injectLocation(location);
|
||||
@@ -1487,15 +1509,11 @@ public class LocationManager {
|
||||
Preconditions.checkArgument(provider != null, "invalid null provider");
|
||||
Preconditions.checkArgument(location != null, "invalid null location");
|
||||
|
||||
if (!location.isComplete()) {
|
||||
IllegalArgumentException e = new IllegalArgumentException(
|
||||
"Incomplete location object, missing timestamp or accuracy? " + location);
|
||||
if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
Log.w(TAG, e);
|
||||
location.makeComplete();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
if (Compatibility.isChangeEnabled(INCOMPLETE_LOCATION)) {
|
||||
Preconditions.checkArgument(location.isComplete(),
|
||||
"incomplete location object, missing timestamp or accuracy?");
|
||||
} else {
|
||||
location.makeComplete();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1629,7 +1647,11 @@ public class LocationManager {
|
||||
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
|
||||
public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
|
||||
@NonNull PendingIntent intent) {
|
||||
checkPendingIntent(intent);
|
||||
Preconditions.checkArgument(intent != null, "invalid null pending intent");
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(intent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
if (expiration < 0) expiration = Long.MAX_VALUE;
|
||||
|
||||
Geofence fence = Geofence.createCircle(latitude, longitude, radius);
|
||||
@@ -1659,7 +1681,11 @@ public class LocationManager {
|
||||
* permission is not present
|
||||
*/
|
||||
public void removeProximityAlert(@NonNull PendingIntent intent) {
|
||||
checkPendingIntent(intent);
|
||||
Preconditions.checkArgument(intent != null, "invalid null pending intent");
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(intent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.removeGeofence(null, intent, mContext.getPackageName());
|
||||
@@ -1709,8 +1735,13 @@ public class LocationManager {
|
||||
@NonNull LocationRequest request,
|
||||
@NonNull Geofence fence,
|
||||
@NonNull PendingIntent intent) {
|
||||
checkPendingIntent(intent);
|
||||
Preconditions.checkArgument(request != null, "invalid null location request");
|
||||
Preconditions.checkArgument(fence != null, "invalid null geofence");
|
||||
Preconditions.checkArgument(intent != null, "invalid null pending intent");
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(intent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
|
||||
@@ -1737,8 +1768,12 @@ public class LocationManager {
|
||||
* @hide
|
||||
*/
|
||||
public void removeGeofence(@NonNull Geofence fence, @NonNull PendingIntent intent) {
|
||||
checkPendingIntent(intent);
|
||||
Preconditions.checkArgument(fence != null, "invalid null geofence");
|
||||
Preconditions.checkArgument(intent != null, "invalid null pending intent");
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(intent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.removeGeofence(fence, intent, mContext.getPackageName());
|
||||
@@ -1759,7 +1794,11 @@ public class LocationManager {
|
||||
* @hide
|
||||
*/
|
||||
public void removeAllGeofences(@NonNull PendingIntent intent) {
|
||||
checkPendingIntent(intent);
|
||||
Preconditions.checkArgument(intent != null, "invalid null pending intent");
|
||||
if (Compatibility.isChangeEnabled(TARGETED_PENDING_INTENT)) {
|
||||
Preconditions.checkArgument(intent.isTargetedToPackage(),
|
||||
"pending intent must be targeted to a package");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.removeGeofence(null, intent, mContext.getPackageName());
|
||||
@@ -1833,14 +1872,15 @@ public class LocationManager {
|
||||
* @param status object containing GPS status details, or null.
|
||||
* @return status object containing updated GPS status.
|
||||
*
|
||||
* @deprecated GpsStatus APIs are deprecated, use {@link GnssStatus} APIs instead.
|
||||
* @deprecated GpsStatus APIs are deprecated, use {@link GnssStatus} APIs instead. No longer
|
||||
* supported in apps targeting S and above.
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiresPermission(ACCESS_FINE_LOCATION)
|
||||
public @Nullable GpsStatus getGpsStatus(@Nullable GpsStatus status) {
|
||||
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.R) {
|
||||
if (Compatibility.isChangeEnabled(GPS_STATUS_USAGE)) {
|
||||
throw new UnsupportedOperationException(
|
||||
"GpsStatus APIs not supported in S and above, use GnssStatus APIs instead");
|
||||
"GpsStatus APIs not supported, please use GnssStatus APIs instead");
|
||||
}
|
||||
|
||||
GnssStatus gnssStatus = mGnssStatusListenerManager.getGnssStatus();
|
||||
@@ -1863,17 +1903,14 @@ public class LocationManager {
|
||||
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
|
||||
*
|
||||
* @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead. No longer
|
||||
* supported in apps targeting R and above.
|
||||
* supported in apps targeting S and above.
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiresPermission(ACCESS_FINE_LOCATION)
|
||||
public boolean addGpsStatusListener(GpsStatus.Listener listener) {
|
||||
UnsupportedOperationException ex = new UnsupportedOperationException(
|
||||
"GpsStatus APIs not supported in S and above, use GnssStatus APIs instead");
|
||||
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.R) {
|
||||
throw ex;
|
||||
} else {
|
||||
Log.w(TAG, ex);
|
||||
if (Compatibility.isChangeEnabled(GPS_STATUS_USAGE)) {
|
||||
throw new UnsupportedOperationException(
|
||||
"GpsStatus APIs not supported, please use GnssStatus APIs instead");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1889,16 +1926,13 @@ public class LocationManager {
|
||||
* @param listener GPS status listener object to remove
|
||||
*
|
||||
* @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead. No longer
|
||||
* supported in apps targeting R and above.
|
||||
* supported in apps targeting S and above.
|
||||
*/
|
||||
@Deprecated
|
||||
public void removeGpsStatusListener(GpsStatus.Listener listener) {
|
||||
UnsupportedOperationException ex = new UnsupportedOperationException(
|
||||
"GpsStatus APIs not supported in S and above, use GnssStatus APIs instead");
|
||||
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.R) {
|
||||
throw ex;
|
||||
} else {
|
||||
Log.w(TAG, ex);
|
||||
if (Compatibility.isChangeEnabled(GPS_STATUS_USAGE)) {
|
||||
throw new UnsupportedOperationException(
|
||||
"GpsStatus APIs not supported, please use GnssStatus APIs instead");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -2397,19 +2431,6 @@ public class LocationManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPendingIntent(PendingIntent pendingIntent) {
|
||||
Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
|
||||
if (!pendingIntent.isTargetedToPackage()) {
|
||||
IllegalArgumentException e = new IllegalArgumentException(
|
||||
"invalid pending intent - must be targeted to package");
|
||||
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) {
|
||||
throw e;
|
||||
} else {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GetCurrentLocationTransport extends ILocationListener.Stub implements
|
||||
AlarmManager.OnAlarmListener {
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import static android.os.PowerManager.locationPowerSaveModeToString;
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -2170,10 +2171,10 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
@Override
|
||||
public boolean injectLocation(Location location) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to inject location");
|
||||
mContext.enforceCallingPermission(ACCESS_FINE_LOCATION,
|
||||
"Access Fine Location permission not granted to inject Location");
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null);
|
||||
mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null);
|
||||
|
||||
Preconditions.checkArgument(location.isComplete());
|
||||
|
||||
synchronized (mLock) {
|
||||
LocationProviderManager manager = getLocationProviderManager(location.getProvider());
|
||||
@@ -2419,20 +2420,15 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
@Override
|
||||
public boolean isLocationEnabledForUser(int userId) {
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
|
||||
null);
|
||||
}
|
||||
|
||||
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
|
||||
userId, false, false, "isLocationEnabledForUser", null);
|
||||
return mSettingsHelper.isLocationEnabled(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProviderEnabledForUser(String providerName, int userId) {
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
|
||||
null);
|
||||
}
|
||||
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
|
||||
userId, false, false, "isProviderEnabledForUser", null);
|
||||
|
||||
// Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
|
||||
// so we discourage its use
|
||||
@@ -2741,6 +2737,9 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
@Override
|
||||
public void setTestProviderLocation(String provider, Location location, String packageName) {
|
||||
Preconditions.checkArgument(location.isComplete(),
|
||||
"incomplete location object, missing timestamp or accuracy?");
|
||||
|
||||
if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user