Merge "Add flags to <uses-permission> manifest tags." into sc-dev
This commit is contained in:
@@ -34,6 +34,7 @@ import android.content.pm.parsing.component.ParsedPermissionGroup;
|
||||
import android.content.pm.parsing.component.ParsedProcess;
|
||||
import android.content.pm.parsing.component.ParsedProvider;
|
||||
import android.content.pm.parsing.component.ParsedService;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -89,7 +90,7 @@ public interface ParsingPackage extends ParsingPackageRead {
|
||||
|
||||
ParsingPackage addReqFeature(FeatureInfo reqFeature);
|
||||
|
||||
ParsingPackage addRequestedPermission(String permission);
|
||||
ParsingPackage addUsesPermission(ParsedUsesPermission parsedUsesPermission);
|
||||
|
||||
ParsingPackage addService(ParsedService parsedService);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ import android.content.pm.parsing.component.ParsedPermissionGroup;
|
||||
import android.content.pm.parsing.component.ParsedProcess;
|
||||
import android.content.pm.parsing.component.ParsedProvider;
|
||||
import android.content.pm.parsing.component.ParsedService;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -71,6 +72,7 @@ import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringValueMap;
|
||||
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -227,8 +229,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
protected List<String> adoptPermissions = emptyList();
|
||||
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
private List<String> requestedPermissions = emptyList();
|
||||
private List<ParsedUsesPermission> usesPermissions = emptyList();
|
||||
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedStringList.class)
|
||||
private List<String> implicitPermissions = emptyList();
|
||||
@@ -691,9 +693,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsingPackageImpl addRequestedPermission(String permission) {
|
||||
this.requestedPermissions = CollectionUtils.add(this.requestedPermissions,
|
||||
TextUtils.safeIntern(permission));
|
||||
public ParsingPackageImpl addUsesPermission(ParsedUsesPermission permission) {
|
||||
this.usesPermissions = CollectionUtils.add(this.usesPermissions, permission);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1134,7 +1135,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
dest.writeByteArray(this.restrictUpdateHash);
|
||||
dest.writeStringList(this.originalPackages);
|
||||
sForInternedStringList.parcel(this.adoptPermissions, dest, flags);
|
||||
sForInternedStringList.parcel(this.requestedPermissions, dest, flags);
|
||||
dest.writeTypedList(this.usesPermissions);
|
||||
sForInternedStringList.parcel(this.implicitPermissions, dest, flags);
|
||||
sForStringSet.parcel(this.upgradeKeySets, dest, flags);
|
||||
dest.writeMap(this.keySetMapping);
|
||||
@@ -1255,7 +1256,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
this.restrictUpdateHash = in.createByteArray();
|
||||
this.originalPackages = in.createStringArrayList();
|
||||
this.adoptPermissions = sForInternedStringList.unparcel(in);
|
||||
this.requestedPermissions = sForInternedStringList.unparcel(in);
|
||||
this.usesPermissions = in.createTypedArrayList(ParsedUsesPermission.CREATOR);
|
||||
this.implicitPermissions = sForInternedStringList.unparcel(in);
|
||||
this.upgradeKeySets = sForStringSet.unparcel(in);
|
||||
this.keySetMapping = in.readHashMap(boot);
|
||||
@@ -1551,9 +1552,21 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getRequestedPermissions() {
|
||||
final List<ParsedUsesPermission> usesPermissions = getUsesPermissions();
|
||||
final int size = usesPermissions.size();
|
||||
final List<String> requestedPermissions = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
requestedPermissions.add(usesPermissions.get(i).name);
|
||||
}
|
||||
return requestedPermissions;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<ParsedUsesPermission> getUsesPermissions() {
|
||||
return usesPermissions;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getImplicitPermissions() {
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.pm.parsing.component.ParsedPermissionGroup;
|
||||
import android.content.pm.parsing.component.ParsedProcess;
|
||||
import android.content.pm.parsing.component.ParsedProvider;
|
||||
import android.content.pm.parsing.component.ParsedService;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
@@ -45,6 +46,7 @@ import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -192,6 +194,14 @@ public interface ParsingPackageRead extends Parcelable {
|
||||
@NonNull
|
||||
List<FeatureInfo> getReqFeatures();
|
||||
|
||||
/**
|
||||
* @deprecated consider migrating to {@link #getUsesPermissions} which has
|
||||
* more parsed details, such as flags
|
||||
*/
|
||||
@NonNull
|
||||
@Deprecated
|
||||
List<String> getRequestedPermissions();
|
||||
|
||||
/**
|
||||
* All the permissions declared. This is an effective set, and may include permissions
|
||||
* transformed from split/migrated permissions from previous versions, so may not be exactly
|
||||
@@ -200,7 +210,7 @@ public interface ParsingPackageRead extends Parcelable {
|
||||
* @see R.styleable#AndroidManifestUsesPermission
|
||||
*/
|
||||
@NonNull
|
||||
List<String> getRequestedPermissions();
|
||||
List<ParsedUsesPermission> getUsesPermissions();
|
||||
|
||||
/**
|
||||
* Returns the properties set on the application
|
||||
|
||||
@@ -67,6 +67,7 @@ import android.content.pm.parsing.component.ParsedProvider;
|
||||
import android.content.pm.parsing.component.ParsedProviderUtils;
|
||||
import android.content.pm.parsing.component.ParsedService;
|
||||
import android.content.pm.parsing.component.ParsedServiceUtils;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.content.pm.parsing.result.ParseInput;
|
||||
import android.content.pm.parsing.result.ParseInput.DeferredError;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
@@ -119,6 +120,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@@ -1206,6 +1208,10 @@ public class ParsingPackageUtils {
|
||||
requiredNotFeatures.add(feature);
|
||||
}
|
||||
|
||||
final int usesPermissionFlags = sa.getInt(
|
||||
com.android.internal.R.styleable.AndroidManifestUsesPermission_usesPermissionFlags,
|
||||
0);
|
||||
|
||||
final int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
@@ -1270,14 +1276,31 @@ public class ParsingPackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkg.getRequestedPermissions().contains(name)) {
|
||||
pkg.addRequestedPermission(name.intern());
|
||||
} else {
|
||||
Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
|
||||
+ name + " in package: " + pkg.getPackageName() + " at: "
|
||||
+ parser.getPositionDescription());
|
||||
// Quietly ignore duplicate permission requests, but fail loudly if
|
||||
// the two requests have conflicting flags
|
||||
boolean found = 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, name)) {
|
||||
if (usesPermission.usesPermissionFlags != usesPermissionFlags) {
|
||||
return input.error("Conflicting uses-permissions flags: "
|
||||
+ name + " in package: " + pkg.getPackageName() + " at: "
|
||||
+ parser.getPositionDescription());
|
||||
} else {
|
||||
Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
|
||||
+ name + " in package: " + pkg.getPackageName() + " at: "
|
||||
+ parser.getPositionDescription());
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
pkg.addUsesPermission(new ParsedUsesPermission(name, usesPermissionFlags));
|
||||
}
|
||||
return success;
|
||||
} finally {
|
||||
sa.recycle();
|
||||
@@ -2755,7 +2778,7 @@ public class ParsingPackageUtils {
|
||||
newPermsMsg.append(' ');
|
||||
}
|
||||
newPermsMsg.append(npi.name);
|
||||
pkg.addRequestedPermission(npi.name)
|
||||
pkg.addUsesPermission(new ParsedUsesPermission(npi.name, 0))
|
||||
.addImplicitPermission(npi.name);
|
||||
}
|
||||
}
|
||||
@@ -2777,7 +2800,7 @@ public class ParsingPackageUtils {
|
||||
for (int in = 0; in < newPerms.size(); in++) {
|
||||
final String perm = newPerms.get(in);
|
||||
if (!requestedPermissions.contains(perm)) {
|
||||
pkg.addRequestedPermission(perm)
|
||||
pkg.addUsesPermission(new ParsedUsesPermission(perm, 0))
|
||||
.addImplicitPermission(perm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.content.pm.parsing.component;
|
||||
|
||||
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A {@link android.R.styleable#AndroidManifestUsesPermission
|
||||
* <uses-permission>} tag parsed from the manifest.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ParsedUsesPermission implements Parcelable {
|
||||
/** Name of the permission requested */
|
||||
public @NonNull String name;
|
||||
|
||||
/** Set of flags that should apply to this permission request. */
|
||||
public @UsesPermissionFlags int usesPermissionFlags;
|
||||
|
||||
/**
|
||||
* Strong assertion by a developer that they will never use this permission
|
||||
* 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;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
|
||||
FLAG_NEVER_FOR_LOCATION
|
||||
})
|
||||
public @interface UsesPermissionFlags {}
|
||||
|
||||
public ParsedUsesPermission(@NonNull String name,
|
||||
@UsesPermissionFlags int usesPermissionFlags) {
|
||||
this.name = name.intern();
|
||||
this.usesPermissionFlags = usesPermissionFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
sForInternedString.parcel(this.name, dest, flags);
|
||||
dest.writeInt(usesPermissionFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected ParsedUsesPermission(@NonNull Parcel in) {
|
||||
this.name = sForInternedString.unparcel(in);
|
||||
this.usesPermissionFlags = in.readInt();
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<ParsedUsesPermission> CREATOR
|
||||
= new Parcelable.Creator<ParsedUsesPermission>() {
|
||||
@Override
|
||||
public ParsedUsesPermission[] newArray(int size) {
|
||||
return new ParsedUsesPermission[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsedUsesPermission createFromParcel(@NonNull Parcel in) {
|
||||
return new ParsedUsesPermission(in);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2063,6 +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. -->
|
||||
<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" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- <code>required-feature</code> and <code>required-not-feature</code> elements inside
|
||||
|
||||
@@ -1141,4 +1141,12 @@ public abstract class PackageManagerInternal {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -252,6 +252,7 @@ import android.content.pm.parsing.component.ParsedPermissionGroup;
|
||||
import android.content.pm.parsing.component.ParsedProcess;
|
||||
import android.content.pm.parsing.component.ParsedProvider;
|
||||
import android.content.pm.parsing.component.ParsedService;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
import android.content.pm.parsing.result.ParseTypeImpl;
|
||||
import android.content.res.Resources;
|
||||
@@ -27322,6 +27323,28 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.content.pm.parsing.component.ParsedPermission;
|
||||
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.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -854,7 +855,7 @@ public class PackageParserTest {
|
||||
.addProvider(new ParsedProvider())
|
||||
.addService(new ParsedService())
|
||||
.addInstrumentation(new ParsedInstrumentation())
|
||||
.addRequestedPermission("foo7")
|
||||
.addUsesPermission(new ParsedUsesPermission("foo7", 0))
|
||||
.addImplicitPermission("foo25")
|
||||
.addProtectedBroadcast("foo8")
|
||||
.setStaticSharedLibName("foo23")
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.SharedLibraryInfo;
|
||||
import android.content.pm.parsing.ParsingPackage;
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Environment;
|
||||
import android.os.UserHandle;
|
||||
@@ -429,7 +430,7 @@ public class ScanTests {
|
||||
@Test
|
||||
public void factoryTestFlagSet() throws Exception {
|
||||
final ParsingPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME)
|
||||
.addRequestedPermission(Manifest.permission.FACTORY_TEST);
|
||||
.addUsesPermission(new ParsedUsesPermission(Manifest.permission.FACTORY_TEST, 0));
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = PackageManagerService.scanPackageOnlyLI(
|
||||
createBasicScanRequestBuilder(basicPackage).build(),
|
||||
|
||||
Reference in New Issue
Block a user