Allow renounce location permission

Allow renounce location permission

Bug: 198533763
Test: CTS
Merged-In: I10872f34603441da2cf80f1f2976f3f3ca0ff6c2
Change-Id: I10872f34603441da2cf80f1f2976f3f3ca0ff6c2
This commit is contained in:
Sooraj Sasindran 2021-11-10 16:27:50 -08:00
parent 6a8b9f3964
commit 5d02dbb7bf
7 changed files with 219 additions and 36 deletions

View File

@ -42841,6 +42841,7 @@ package android.telephony {
method public int getPhoneType();
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState(boolean, boolean);
method @Nullable public android.telephony.SignalStrength getSignalStrength();
method public int getSimCarrierId();
method @Nullable public CharSequence getSimCarrierIdName();
@ -42893,8 +42894,10 @@ package android.telephony {
method public boolean isWorldPhone();
method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
method public void registerTelephonyCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback);
method public void registerTelephonyCallback(boolean, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method @Nullable @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(boolean, @NonNull android.telephony.NetworkScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
method public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);

View File

@ -247,8 +247,8 @@ public class TelephonyRegistryManager {
} else if (listener.mSubId != null) {
subId = listener.mSubId;
}
sRegistry.listenWithEventList(
subId, pkg, featureId, listener.callback, eventsList, notifyNow);
sRegistry.listenWithEventList(false, false, subId, pkg, featureId,
listener.callback, eventsList, notifyNow);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@ -263,11 +263,13 @@ public class TelephonyRegistryManager {
* @param events List events
* @param notifyNow Whether to notify instantly
*/
private void listenFromCallback(int subId, @NonNull String pkg, @NonNull String featureId,
private void listenFromCallback(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess, int subId,
@NonNull String pkg, @NonNull String featureId,
@NonNull TelephonyCallback telephonyCallback, @NonNull int[] events,
boolean notifyNow) {
try {
sRegistry.listenWithEventList(
sRegistry.listenWithEventList(renounceFineLocationAccess, renounceCoarseLocationAccess,
subId, pkg, featureId, telephonyCallback.callback, events, notifyNow);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@ -1161,14 +1163,17 @@ public class TelephonyRegistryManager {
*
* @param callback The {@link TelephonyCallback} object to register.
*/
public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor,
public void registerTelephonyCallback(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess,
@NonNull @CallbackExecutor Executor executor,
int subId, String pkgName, String attributionTag, @NonNull TelephonyCallback callback,
boolean notifyNow) {
if (callback == null) {
throw new IllegalStateException("telephony service is null.");
}
callback.init(executor);
listenFromCallback(subId, pkgName, attributionTag, callback,
listenFromCallback(renounceFineLocationAccess, renounceCoarseLocationAccess, subId,
pkgName, attributionTag, callback,
getEventsFromCallback(callback).stream().mapToInt(i -> i).toArray(), notifyNow);
}
@ -1179,6 +1184,7 @@ public class TelephonyRegistryManager {
*/
public void unregisterTelephonyCallback(int subId, String pkgName, String attributionTag,
@NonNull TelephonyCallback callback, boolean notifyNow) {
listenFromCallback(subId, pkgName, attributionTag, callback, new int[0], notifyNow);
listenFromCallback(false, false, subId,
pkgName, attributionTag, callback, new int[0], notifyNow);
}
}

View File

@ -43,7 +43,8 @@ interface ITelephonyRegistry {
void removeOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
void listenWithEventList(in int subId, String pkg, String featureId,
void listenWithEventList(in boolean renounceFineLocationAccess,
in boolean renounceCoarseLocationAccess, in int subId, String pkg, String featureId,
IPhoneStateListener callback, in int[] events, boolean notifyNow);
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
void notifyCallStateForAllSubs(int state, String incomingNumber);

View File

@ -152,6 +152,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int callerUid;
int callerPid;
boolean renounceFineLocationAccess;
boolean renounceCoarseLocationAccess;
Set<Integer> eventList;
@ -995,14 +997,25 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
@Override
public void listenWithEventList(int subId, String callingPackage, String callingFeatureId,
IPhoneStateListener callback, int[] events, boolean notifyNow) {
public void listenWithEventList(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess, int subId, String callingPackage,
String callingFeatureId, IPhoneStateListener callback,
int[] events, boolean notifyNow) {
Set<Integer> eventList = Arrays.stream(events).boxed().collect(Collectors.toSet());
listen(callingPackage, callingFeatureId, callback, eventList, notifyNow, subId);
listen(renounceFineLocationAccess, renounceFineLocationAccess, callingPackage,
callingFeatureId, callback, eventList, notifyNow, subId);
}
private void listen(String callingPackage, @Nullable String callingFeatureId,
IPhoneStateListener callback, Set<Integer> events, boolean notifyNow, int subId) {
listen(false, false, callingPackage,
callingFeatureId, callback, events, notifyNow, subId);
}
private void listen(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess, String callingPackage,
@Nullable String callingFeatureId, IPhoneStateListener callback,
Set<Integer> events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid()
@ -1047,6 +1060,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
r.callback = callback;
r.callingPackage = callingPackage;
r.callingFeatureId = callingFeatureId;
r.renounceCoarseLocationAccess = renounceCoarseLocationAccess;
r.renounceFineLocationAccess = renounceFineLocationAccess;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
@ -3198,6 +3213,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
* If you don't need app compat logic, use {@link #checkFineLocationAccess(Record)}.
*/
private boolean checkFineLocationAccess(Record r, int minSdk) {
if (r.renounceFineLocationAccess) {
return false;
}
LocationAccessPolicy.LocationPermissionQuery query =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
.setCallingPackage(r.callingPackage)
@ -3224,6 +3242,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
* If you don't need app compat logic, use {@link #checkCoarseLocationAccess(Record)}.
*/
private boolean checkCoarseLocationAccess(Record r, int minSdk) {
if (r.renounceCoarseLocationAccess) {
return false;
}
LocationAccessPolicy.LocationPermissionQuery query =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
.setCallingPackage(r.callingPackage)

View File

@ -8320,12 +8320,58 @@ public class TelephonyManager {
public NetworkScan requestNetworkScan(
NetworkScanRequest request, Executor executor,
TelephonyScanManager.NetworkScanCallback callback) {
synchronized (this) {
return requestNetworkScan(false, request, executor, callback);
}
/**
* Request a network scan.
*
* This method is asynchronous, so the network scan results will be returned by callback.
* The returned NetworkScan will contain a callback method which can be used to stop the scan.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges})
* and {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If the system-wide location switch is off, apps may still call this API, with the
* following constraints:
* <ol>
* <li>The app must hold the {@code android.permission.NETWORK_SCAN} permission.</li>
* <li>The app must not supply any specific bands or channels to scan.</li>
* <li>The app must only specify MCC/MNC pairs that are
* associated to a SIM in the device.</li>
* <li>Returned results will have no meaningful info other than signal strength
* and MCC/MNC info.</li>
* </ol>
*
* @param renounceFineLocationAccess Set this to true if the caller would not like to receive
* location related information which will be sent if the caller already possess
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param executor The executor through which the callback should be invoked. Since the scan
* request may trigger multiple callbacks and they must be invoked in the same order as
* they are received by the platform, the user should provide an executor which executes
* tasks one at a time in serial order. For example AsyncTask.SERIAL_EXECUTOR.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
android.Manifest.permission.MODIFY_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION
})
public @Nullable NetworkScan requestNetworkScan(
boolean renounceFineLocationAccess, @NonNull NetworkScanRequest request,
@NonNull Executor executor,
@NonNull TelephonyScanManager.NetworkScanCallback callback) {
synchronized (sCacheLock) {
if (mTelephonyScanManager == null) {
mTelephonyScanManager = new TelephonyScanManager();
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
return mTelephonyScanManager.requestNetworkScan(getSubId(), renounceFineLocationAccess,
request, executor, callback,
getOpPackageName(), getAttributionTag());
}
@ -11384,7 +11430,6 @@ public class TelephonyManager {
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
* and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
*
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
*/
@ -11394,7 +11439,72 @@ public class TelephonyManager {
Manifest.permission.ACCESS_COARSE_LOCATION
})
public @Nullable ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
return getServiceState(false, false);
}
/**
* Returns the current {@link ServiceState} information.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* If you want continuous updates of service state info, register a {@link PhoneStateListener}
* via {@link #listen} with the {@link PhoneStateListener#LISTEN_SERVICE_STATE} event.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
* and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
* @param renounceFineLocationAccess Set this to true if the caller would not like to receive
* location related information which will be sent if the caller already possess
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission
* @param renounceCoarseLocationAccess Set this to true if the caller would not like to
* receive location related information which will be sent if the caller already possess
* {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions.
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
})
public @Nullable ServiceState getServiceState(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess) {
return getServiceStateForSubscriber(getSubId(), renounceFineLocationAccess,
renounceCoarseLocationAccess);
}
/**
* Returns the service state information on specified subscription. Callers require
* either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
*
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
* @param renounceFineLocationAccess Set this to true if the caller would not like to receive
* location related information which will be sent if the caller already possess
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission
* @param renounceCoarseLocationAccess Set this to true if the caller would not like to
* receive location related information which will be sent if the caller already possess
* {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions.
*/
private ServiceState getServiceStateForSubscriber(int subId,
boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess) {
try {
ITelephony service = getITelephony();
if (service != null) {
return service.getServiceStateForSubscriber(subId, renounceFineLocationAccess,
renounceCoarseLocationAccess,
getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
} catch (NullPointerException e) {
AnomalyReporter.reportAnomaly(
UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
"getServiceStateForSubscriber " + subId + " NPE");
}
return null;
}
/**
@ -11407,20 +11517,7 @@ public class TelephonyManager {
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public ServiceState getServiceStateForSubscriber(int subId) {
try {
ITelephony service = getITelephony();
if (service != null) {
return service.getServiceStateForSubscriber(subId, getOpPackageName(),
getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
} catch (NullPointerException e) {
AnomalyReporter.reportAnomaly(
UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
"getServiceStateForSubscriber " + subId + " NPE");
}
return null;
return getServiceStateForSubscriber(getSubId(), false, false);
}
/**
@ -15270,7 +15367,49 @@ public class TelephonyManager {
*/
public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull TelephonyCallback callback) {
registerTelephonyCallback(false, false, executor, callback);
}
/**
* Registers a callback object to receive notification of changes in specified telephony states.
* <p>
* To register a callback, pass a {@link TelephonyCallback} which implements
* interfaces of events. For example,
* FakeServiceStateCallback extends {@link TelephonyCallback} implements
* {@link TelephonyCallback.ServiceStateListener}.
*
* At registration, and when a specified telephony state changes, the telephony manager invokes
* the appropriate callback method on the callback object and passes the current (updated)
* values.
* <p>
*
* If this TelephonyManager object has been created with {@link #createForSubscriptionId},
* applies to the given subId. Otherwise, applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}. To register events for multiple
* subIds, pass a separate callback object to each TelephonyManager object created with
* {@link #createForSubscriptionId}.
*
* Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
* call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
* {@link SecurityException} will be thrown otherwise.
*
* This API should be used sparingly -- large numbers of callbacks will cause system
* instability. If a process has registered too many callbacks without unregistering them, it
* may encounter an {@link IllegalStateException} when trying to register more callbacks.
*
* @param renounceFineLocationAccess Set this to true if the caller would not like to receive
* location related information which will be sent if the caller already possess
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permissions.
* @param renounceCoarseLocationAccess Set this to true if the caller would not like to
* receive location related information which will be sent if the caller already possess
* {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions.
* @param executor The executor of where the callback will execute.
* @param callback The {@link TelephonyCallback} object to register.
*/
public void registerTelephonyCallback(boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess,
@NonNull @CallbackExecutor Executor executor,
@NonNull TelephonyCallback callback) {
if (mContext == null) {
throw new IllegalStateException("telephony service is null.");
}
@ -15281,7 +15420,8 @@ public class TelephonyManager {
mTelephonyRegistryMgr = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (mTelephonyRegistryMgr != null) {
mTelephonyRegistryMgr.registerTelephonyCallback(executor, mSubId, getOpPackageName(),
mTelephonyRegistryMgr.registerTelephonyCallback(renounceFineLocationAccess,
renounceCoarseLocationAccess, executor, mSubId, getOpPackageName(),
getAttributionTag(), callback, getITelephony() != null);
} else {
throw new IllegalStateException("telephony service is null.");

View File

@ -228,7 +228,9 @@ public final class TelephonyScanManager {
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param renounceFineLocationAccess Set this to true if the caller would not like to receive
* location related information which will be sent if the caller already possess
* {@link android.Manifest.permission.ACCESS_FINE_LOCATION} and do not renounce the permission
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param callback Returns network scan results or errors.
* @param callingPackage The package name of the caller
@ -237,6 +239,7 @@ public final class TelephonyScanManager {
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
boolean renounceFineLocationAccess,
NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
String callingPackage, @Nullable String callingFeatureId) {
try {
@ -252,7 +255,8 @@ public final class TelephonyScanManager {
// the record to the ScanInfo cache.
synchronized (mScanInfo) {
int scanId = telephony.requestNetworkScan(
subId, request, mMessenger, new Binder(), callingPackage,
subId, renounceFineLocationAccess, request, mMessenger,
new Binder(), callingPackage,
callingFeatureId);
if (scanId == INVALID_SCAN_ID) {
Rlog.e(TAG, "Failed to initiate network scan");

View File

@ -900,6 +900,8 @@ interface ITelephony {
* Perform a radio network scan and return the id of this scan.
*
* @param subId the id of the subscription.
* @param renounceFineLocationAccess Set this to true if the caller would not like to
* receive fine location related information
* @param request Defines all the configs for network scan.
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
@ -907,8 +909,9 @@ interface ITelephony {
* @param callingFeatureId The feature in the package
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
in IBinder binder, in String callingPackage, String callingFeatureId);
int requestNetworkScan(int subId, in boolean renounceFineLocationAccess,
in NetworkScanRequest request, in Messenger messenger, in IBinder binder,
in String callingPackage, String callingFeatureId);
/**
* Stop an existing radio network scan.
@ -1387,12 +1390,17 @@ interface ITelephony {
/**
* Get the service state on specified subscription
* @param subId Subscription id
* @param renounceFineLocationAccess Set this to true if the caller would not like to
* receive fine location related information
* @param renounceCoarseLocationAccess Set this to true if the caller would not like to
* receive coarse location related information
* @param callingPackage The package making the call
* @param callingFeatureId The feature in the package
* @return Service state on specified subscription.
*/
ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
String callingFeatureId);
ServiceState getServiceStateForSubscriber(int subId, boolean renounceFineLocationAccess,
boolean renounceCoarseLocationAccess,
String callingPackage, String callingFeatureId);
/**
* Returns the URI for the per-account voicemail ringtone set in Phone settings.