Merge "Surface "neverForLocation" through public API." into sc-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index 5fcafc7..9775e08 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1581,6 +1581,7 @@
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
     field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
+    field public static final int usesPermissionFlags = 16844356; // 0x1010644
     field public static final int value = 16842788; // 0x1010024
     field public static final int valueFrom = 16843486; // 0x10102de
     field public static final int valueTo = 16843487; // 0x10102df
@@ -12171,6 +12172,7 @@
     field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1
     field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2
     field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+    field public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 65536; // 0x10000
     field public android.content.pm.ActivityInfo[] activities;
     field public android.content.pm.ApplicationInfo applicationInfo;
     field @Nullable public android.content.pm.Attribution[] attributions;
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index e8ef077..0462a4b 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -232,13 +232,23 @@
      *
      * @removed We do not support required permissions.
      */
-    public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0;
+    public static final int REQUESTED_PERMISSION_REQUIRED = 0x00000001;
 
     /**
      * Flag for {@link #requestedPermissionsFlags}: the requested permission
      * is currently granted to the application.
      */
-    public static final int REQUESTED_PERMISSION_GRANTED = 1<<1;
+    public static final int REQUESTED_PERMISSION_GRANTED = 0x00000002;
+
+    /**
+     * Flag for {@link #requestedPermissionsFlags}: the requested permission has
+     * declared {@code neverForLocation} in their manifest as a strong assertion
+     * by a developer that they will never use this permission to derive the
+     * physical location of the device, regardless of
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and/or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} being granted.
+     */
+    public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 0x00010000;
 
     /**
      * Array of all signatures read from the package file. This is only filled
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index fdd2c2a..e0052da 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -52,6 +52,7 @@
 import android.content.pm.parsing.component.ParsedPermissionGroup;
 import android.content.pm.parsing.component.ParsedProvider;
 import android.content.pm.parsing.component.ParsedService;
+import android.content.pm.parsing.component.ParsedUsesPermission;
 import android.os.Environment;
 import android.os.UserHandle;
 
@@ -61,6 +62,7 @@
 
 import java.io.File;
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 /** @hide **/
@@ -264,17 +266,26 @@
                             flags);
                 }
             }
-            size = pkg.getRequestedPermissions().size();
+            final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
+            size = usesPermissions.size();
             if (size > 0) {
                 pi.requestedPermissions = new String[size];
                 pi.requestedPermissionsFlags = new int[size];
                 for (int i = 0; i < size; i++) {
-                    final String perm = pkg.getRequestedPermissions().get(i);
-                    pi.requestedPermissions[i] = perm;
+                    final ParsedUsesPermission usesPermission = usesPermissions.get(i);
+                    pi.requestedPermissions[i] = usesPermission.name;
                     // The notion of required permissions is deprecated but for compatibility.
-                    pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
-                    if (grantedPermissions != null && grantedPermissions.contains(perm)) {
-                        pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+                    pi.requestedPermissionsFlags[i] |=
+                            PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+                    if (grantedPermissions != null
+                            && grantedPermissions.contains(usesPermission.name)) {
+                        pi.requestedPermissionsFlags[i] |=
+                                PackageInfo.REQUESTED_PERMISSION_GRANTED;
+                    }
+                    if ((usesPermission.usesPermissionFlags
+                            & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
+                        pi.requestedPermissionsFlags[i] |=
+                                PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
                     }
                 }
             }
diff --git a/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java b/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
index b9c2e36..adf8da0 100644
--- a/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
+++ b/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
@@ -20,6 +20,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.content.pm.PackageInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -44,7 +45,8 @@
      * to derive the physical location of the device, regardless of
      * ACCESS_FINE_LOCATION and/or ACCESS_COARSE_LOCATION being granted.
      */
-    public static final int FLAG_NEVER_FOR_LOCATION = 0x1;
+    public static final int FLAG_NEVER_FOR_LOCATION =
+            PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0318be7..140163e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2063,13 +2063,14 @@
         requested.  If it does support the feature, it will be as if the manifest didn't
         request it at all. -->
         <attr name="requiredNotFeature" format="string" />
-        <!-- Optional: set of flags that should apply to this permission request. -->
+        <!-- Optional: set of flags that should apply to this permission request. Note that
+             these flags start at 0x4 to match PackageInfo.requestedPermissionsFlags. -->
         <attr name="usesPermissionFlags">
             <!-- Strong assertion by a developer that they will never use this
                  permission to derive the physical location of the device, even
                  when the app has been granted the ACCESS_FINE_LOCATION and/or
                  ACCESS_COARSE_LOCATION permissions. -->
-            <flag name="neverForLocation" value="0x1" />
+            <flag name="neverForLocation" value="0x00010000" />
         </attr>
     </declare-styleable>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 33cc89d..3e5fad8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3091,6 +3091,7 @@
     <public name="isAccessibilityTool"/>
     <public name="attributionTags"/>
     <public name="suppressesSpellChecker" />
+    <public name="usesPermissionFlags" />
   </public-group>
 
   <public-group type="drawable" first-id="0x010800b5">
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index b089014..c295778 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1141,12 +1141,4 @@
      */
     public abstract boolean isPackageFrozen(
             @NonNull String packageName, int callingUid, int userId);
-
-    /**
-     * Returns true if the given {@code packageName} has declared the
-     * {@code neverForLocation} flag in the {@code uses-permission} manifest tag
-     * where they request the given {@code permissionName}.
-     */
-    public abstract boolean isPackageUsesPermissionNeverForLocation(@NonNull String packageName,
-            @NonNull String permissionName);
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ff042c2..43eeb2a5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27324,31 +27324,8 @@
             return PackageManagerService.this.getPackageStartability(
                     packageName, callingUid, userId) == PACKAGE_STARTABILITY_FROZEN;
         }
-
-        @Override
-        public boolean isPackageUsesPermissionNeverForLocation(@NonNull String packageName,
-                @NonNull String permissionName) {
-            Objects.requireNonNull(packageName);
-            Objects.requireNonNull(permissionName);
-            final AndroidPackage pkg;
-            synchronized (mLock) {
-                pkg = mPackages.get(packageName);
-            }
-            if (pkg == null) return false;
-            final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
-            final int size = usesPermissions.size();
-            for (int i = 0; i < size; i++) {
-                final ParsedUsesPermission usesPermission = usesPermissions.get(i);
-                if (Objects.equals(usesPermission.name, permissionName)) {
-                    return (usesPermission.usesPermissionFlags
-                            & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0;
-                }
-            }
-            return false;
-        }
     }
 
-
     @GuardedBy("mLock")
     private SparseArray<String> getAppsWithSharedUserIdsLocked() {
         final SparseArray<String> sharedUserIds = new SparseArray<>();