[BACKPORT] Improve location checks in TelephonyRegistry

Improve location checking for apps targeting SDK28
or earlier.

Bug: 158484422
Test: (cts) atest TelephonyLocationTests; atest PhoneStateListenerTest
Merged-In: I8caa3ea409836ce8469d8d8210b481a0284594f2
Change-Id: I8caa3ea409836ce8469d8d8210b481a0284594f2
(cherry picked from commit 4e0c7d16fd76bd7743a7f46ba63c75e8c65d63be)
(cherry picked from commit cc584e777db03316f98298a18a1844e51592ebef)
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 23bf955..c4f1c80 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -310,11 +310,10 @@
     private List<Map<Integer, PreciseDataConnectionState>> mPreciseDataConnectionStates =
             new ArrayList<Map<Integer, PreciseDataConnectionState>>();
 
-    static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_REGISTRATION_FAILURE
-                    | PhoneStateListener.LISTEN_BARRING_INFO;
-
-    static final int ENFORCE_FINE_LOCATION_PERMISSION_MASK =
+    // Starting in Q, almost all cellular location requires FINE location enforcement.
+    // Prior to Q, cellular was available with COARSE location enforcement. Bits in this
+    // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later.
+    static final int ENFORCE_LOCATION_PERMISSION_MASK =
             PhoneStateListener.LISTEN_CELL_LOCATION
                     | PhoneStateListener.LISTEN_CELL_INFO
                     | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
@@ -371,7 +370,7 @@
                                 + " newDefaultPhoneId=" + newDefaultPhoneId);
                     }
 
-                    //Due to possible risk condition,(notify call back using the new
+                    //Due to possible race condition,(notify call back using the new
                     //defaultSubId comes before new defaultSubId update) we need to recall all
                     //possible missed notify callback
                     synchronized (mRecords) {
@@ -904,7 +903,8 @@
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
                         try {
                             if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
-                            if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 // null will be translated to empty CellLocation object in client.
                                 r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
                             }
@@ -959,7 +959,8 @@
                         try {
                             if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
                                     + mCellInfo.get(phoneId));
-                            if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
                             }
                         } catch (RemoteException ex) {
@@ -1513,7 +1514,8 @@
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
                             idMatch(r.subId, subId, phoneId) &&
-                            checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellInfoForSubscriber: mCellInfo=" + cellInfo
@@ -1845,7 +1847,8 @@
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
                             idMatch(r.subId, subId, phoneId) &&
-                            checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellLocation: cellLocation=" + cellLocation
@@ -2624,19 +2627,13 @@
                 .setCallingPid(Binder.getCallingPid())
                 .setCallingUid(Binder.getCallingUid());
 
-        boolean shouldCheckLocationPermissions = false;
-        if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
-            locationQueryBuilder.setMinSdkVersionForCoarse(0);
-            shouldCheckLocationPermissions = true;
-        }
-
-        if ((events & ENFORCE_FINE_LOCATION_PERMISSION_MASK) != 0) {
+        if ((events & ENFORCE_LOCATION_PERMISSION_MASK) != 0) {
             // Everything that requires fine location started in Q. So far...
             locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q);
-            shouldCheckLocationPermissions = true;
-        }
+            // If we're enforcing fine starting in Q, we also want to enforce coarse even for
+            // older SDK versions.
+            locationQueryBuilder.setMinSdkVersionForCoarse(0);
 
-        if (shouldCheckLocationPermissions) {
             LocationAccessPolicy.LocationPermissionResult result =
                     LocationAccessPolicy.checkLocationPermission(
                             mContext, locationQueryBuilder.build());
@@ -2803,8 +2800,16 @@
             try {
                 if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
                         mServiceState[phoneId]);
-                r.callback.onServiceStateChanged(
-                        new ServiceState(mServiceState[phoneId]));
+                ServiceState ss = new ServiceState(mServiceState[phoneId]);
+                if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                    r.callback.onServiceStateChanged(ss);
+                } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+                    r.callback.onServiceStateChanged(
+                            ss.createLocationInfoSanitizedCopy(false));
+                } else {
+                    r.callback.onServiceStateChanged(
+                            ss.createLocationInfoSanitizedCopy(true));
+                }
             } catch (RemoteException ex) {
                 mRemoveList.add(r.binder);
             }
@@ -2849,7 +2854,8 @@
                     log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
                             + mCellInfo.get(phoneId));
                 }
-                if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                        && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                     r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
                 }
             } catch (RemoteException ex) {
@@ -2915,7 +2921,8 @@
                     log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
                             + mCellIdentity[phoneId]);
                 }
-                if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                        && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                     // null will be translated to empty CellLocation object in client.
                     r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
                 }