1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.compatibility.common.deviceinfo; 18 19 import android.util.Log; 20 21 import androidx.annotation.NonNull; 22 23 import com.android.compatibility.common.util.DeviceInfoStore; 24 import com.android.compatibility.common.util.SystemUtil; 25 import com.android.modules.utils.build.SdkLevel; 26 27 import java.io.IOException; 28 29 /** 30 * PermissionDeviceInfo collector. 31 * <p> 32 * Information about permissions in the system, independent of per-package information which is 33 * collected in {@link PackageDeviceInfo}. 34 */ 35 public class PermissionDeviceInfo extends DeviceInfo { 36 37 private static final String LOG_TAG = "PermissionDeviceInfo"; 38 39 private static final String NAME = "name"; 40 private static final String PACKAGES = "packages"; 41 private static final String PARTITION = "partition"; 42 private static final String PERMISSIONS = "permissions"; 43 private static final String SIGNATURE_PERMISSION_ALLOWLIST_ENABLED = 44 "signature_permission_allowlist_enabled"; 45 private static final String SIGNATURE_PERMISSION_ALLOWLISTS = "signature_permission_allowlists"; 46 47 @Override collectDeviceInfo(@onNull DeviceInfoStore store)48 protected void collectDeviceInfo(@NonNull DeviceInfoStore store) throws Exception { 49 if (SdkLevel.isAtLeastV()) { 50 collectSignaturePermissionAllowlists(store); 51 collectSignaturePermissionAllowlistEnabled(store); 52 } 53 } 54 collectSignaturePermissionAllowlists(@onNull DeviceInfoStore store)55 private static void collectSignaturePermissionAllowlists(@NonNull DeviceInfoStore store) 56 throws IOException { 57 store.startArray(SIGNATURE_PERMISSION_ALLOWLISTS); 58 collectSignaturePermissionAllowlist(store, "system"); 59 collectSignaturePermissionAllowlist(store, "vendor"); 60 collectSignaturePermissionAllowlist(store, "product"); 61 collectSignaturePermissionAllowlist(store, "system-ext"); 62 collectSignaturePermissionAllowlist(store, "apex"); 63 store.endArray(); // "signature_permission_allowlists" 64 } 65 collectSignaturePermissionAllowlist(@onNull DeviceInfoStore store, @NonNull String partition)66 private static void collectSignaturePermissionAllowlist(@NonNull DeviceInfoStore store, 67 @NonNull String partition) throws IOException { 68 final String output = SystemUtil.runShellCommandOrThrow( 69 "pm get-signature-permission-allowlist " + partition).trim(); 70 store.startGroup(); 71 store.addResult(PARTITION, partition); 72 store.startArray(PACKAGES); 73 boolean isFirstPackage = true; 74 for (String line : output.split("\n")) { 75 line = line.trim(); 76 if (line.startsWith("Package: ")) { 77 if (isFirstPackage) { 78 isFirstPackage = false; 79 } else { 80 store.endArray(); // "permissions" 81 store.endGroup(); 82 } 83 String packageName = line.substring("Package: ".length()); 84 store.startGroup(); 85 store.addResult(NAME, packageName); 86 store.startArray(PERMISSIONS); 87 } else if (line.startsWith("Permission: ")) { 88 String permissionName = line.substring("Permission: ".length()); 89 store.startGroup(); 90 store.addResult(NAME, permissionName); 91 store.endGroup(); 92 } else if (line.isEmpty()) { 93 // Ignored. 94 } else { 95 throw new IllegalArgumentException("Unknown line: " + line); 96 } 97 } 98 if (!isFirstPackage) { 99 store.endArray(); // "permissions" 100 store.endGroup(); 101 } 102 store.endArray(); // "packages" 103 store.endGroup(); 104 } 105 collectSignaturePermissionAllowlistEnabled(@onNull DeviceInfoStore store)106 private static void collectSignaturePermissionAllowlistEnabled(@NonNull DeviceInfoStore store) 107 throws IOException { 108 Boolean enabled = FeatureFlagUtils.isFeatureFlagEnabled( 109 "permissions/android.permission.flags.signature_permission_allowlist_enabled", 110 "system"); 111 if (enabled == null) { 112 Log.e(LOG_TAG, "Failed to check whether signature permission allowlist is enabled"); 113 return; 114 } 115 store.addResult(SIGNATURE_PERMISSION_ALLOWLIST_ENABLED, enabled); 116 } 117 } 118