diff --git a/core/api/current.txt b/core/api/current.txt index d9753ab5e4a0..c3b5b943477f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -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); diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index cb1cff9cda22..859fd804dea5 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -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); } } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index a0a0f3276b99..6ba0279313b1 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -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); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 5ed6c86bdc18..39c21a2ede48 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -152,6 +152,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUid; int callerPid; + boolean renounceFineLocationAccess; + boolean renounceCoarseLocationAccess; Set 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 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 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 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) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a2efc962ed9c..4c7e4e1d24b9 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -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. + * + *

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: + *

    + *
  1. The app must hold the {@code android.permission.NETWORK_SCAN} permission.
  2. + *
  3. The app must not supply any specific bands or channels to scan.
  4. + *
  5. The app must only specify MCC/MNC pairs that are + * associated to a SIM in the device.
  6. + *
  7. Returned results will have no meaningful info other than signal strength + * and MCC/MNC info.
  8. + *
+ * + * @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 { *

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. + * + *

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. + * + *

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. + *

+ * 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. + *

+ * + * 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 must + * 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."); diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java index 9572154ec773..122662d3d7c8 100644 --- a/telephony/java/android/telephony/TelephonyScanManager.java +++ b/telephony/java/android/telephony/TelephonyScanManager.java @@ -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"); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2df5f53147bc..03010f6b27b6 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -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.