No blame for location usage if no location sensitive field is queried

ServiceStateProvide calls LocationAccessPolicy#checkLocationPermission
to check if the calling app has location permission. But this
API blames a location usage when the app has location granted.

To avoid caller get blamed if no location protected filed is queried,
ServiceStateProvide will perform location permission check only
app explicitly queries loction protected fields.

Bug: 179730843
Test: atest ServiceStateProvideTest
Change-Id: Idcb04cf3b981db8e704c485993225e366dbc8db4
diff --git a/src/com/android/phone/ServiceStateProvider.java b/src/com/android/phone/ServiceStateProvider.java
index 50f90b1..3fa1e58 100644
--- a/src/com/android/phone/ServiceStateProvider.java
+++ b/src/com/android/phone/ServiceStateProvider.java
@@ -426,30 +426,44 @@
                 ss = unredactedServiceState;
             } else {
                 availableColumns = ALL_COLUMNS;
-
-                final boolean hasLocationPermission = hasLocationPermission();
-                if (!enforceLocationPermission || hasLocationPermission) {
-                    // No matter the targetSdkVersion, return unredacted ServiceState if caller does
-                    // have location permission or location permission enforcement is not introduced
+                if (!enforceLocationPermission) {
+                    // No matter the targetSdkVersion, return unredacted ServiceState if location
+                    // permission enforcement is not introduced
                     ss = unredactedServiceState;
                 } else {
-                    // The caller has targetSdkVersion S+ but no location permission. It explicitly
-                    // requires location protected columns. Throw SecurityException to fail loudly.
-                    if (targetingAtLeastS && projection != null) {
+                    boolean implicitlyQueryLocation = projection == null;
+                    boolean explicitlyQueryLocation = false;
+                    if (projection != null) {
                         for (String requiredColumn : projection) {
                             if (LOCATION_PROTECTED_COLUMNS_SET.contains(requiredColumn)) {
-                                throw new SecurityException("Column " + requiredColumn
-                                        + "requires location permissions to access.");
+                                explicitlyQueryLocation = true;
+                                break;
                             }
                         }
                     }
 
-                    // In all other cases, return the redacted ServiceState.
-                    // The caller has no location permission but only requires columns without
-                    // location sensitive info or "all" columns, return result that scrub out all
-                    // sensitive info. In later case, we will not know which columns will be fetched
-                    // from the returned cursor until the result has been returned.
-                    ss = getLocationRedactedServiceState(unredactedServiceState);
+                    // Check location permission only when location sensitive info are queried
+                    // (either explicitly or implicitly) to avoid caller get blamed with location
+                    // permission when query non sensitive info.
+                    if (implicitlyQueryLocation || explicitlyQueryLocation) {
+                        if (hasLocationPermission()) {
+                            ss = unredactedServiceState;
+                        } else {
+                            if (targetingAtLeastS) {
+                                // Throw SecurityException to fail loudly if caller is targetSDK S+
+                                throw new SecurityException(
+                                        "Querying location sensitive info requires location "
+                                                + "permissions");
+                            } else {
+                                // For backward compatibility, return redacted value for old SDK
+                                ss = getLocationRedactedServiceState(unredactedServiceState);
+                            }
+                        }
+                    } else {
+                        // The caller is not interested in location sensitive info, return result
+                        // that scrub out all sensitive info. And no permission check is needed.
+                        ss = getLocationRedactedServiceState(unredactedServiceState);
+                    }
                 }
             }