This introduces a new configurable XML file
(/etc/sysconfig/enhanced-confirmation.xml) for ECM (Enhanced
Confirmation Mode). This file enables OEMs to declare a list of
"trusted packages" and/or "trusted installer" packages. A "trusted
package" will be exempt from ECM restrictions. A "trusted installer",
and all packages that it installs, will be exempt from ECM restrictions.
The file may contain zero or more XML elements of the form:
<enhanced-confirmation-trusted-package
package="com.example.app"
sha256-cert-digest="E9:7A:BC:2C:D1:..."/>
...and/or...
<enhanced-confirmation-trusted-installer
package="com.example.app"
sha256-cert-digest="E9:7A:BC:2C:D1:..."/>
(Where the 'package' attribute is a package name, and
'sha256-cert-digest' is a hex-encoded SHA-256 digest of a signing
certificate. Both fields are required for each XML element.)
This file is parsed by the SystemConfig class, where the collection of
all XML elements are deserialized into (SignedPackage) objects which
are cached within SystemConfig.
These objects are accessible by calling either the following SystemAPI
methods:
SystemConfigManager::getEnhancedConfirmationTrustedPackages
SystemConfigManager::getEnhancedConfirmationTrustedInstallers
...which in turn call the (respective) binder methods:
SystemConfigService::getEnhancedConfirmationTrustedPackages
SystemConfigService::getEnhancedConfirmationTrustedInstallers
...which read the data directly from SystemConfig.
The only intended caller of this API is ECM
(EnhancedConfirmationManager/EnhancedConfirmationService), which runs in
SystemServer.
The reason this needs to be SystemApi(MODULE_LIBRARIES) is that the ECM
source code lives within the packages/modules/Permission mainline
module.
Bug: 310654834
Test: atest FrameworksServicesTests:com.android.server.systemconfig.SystemConfigTest
Change-Id: I50e524e5782cea4e66232acef493edbe62aa1f61
156 lines
6.7 KiB
Java
156 lines
6.7 KiB
Java
/*
|
|
* Copyright (C) 2020 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 com.android.server;
|
|
|
|
import static java.util.stream.Collectors.toList;
|
|
import static java.util.stream.Collectors.toMap;
|
|
|
|
import android.Manifest;
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.content.pm.PackageManagerInternal;
|
|
import android.content.pm.SignedPackage;
|
|
import android.content.pm.SignedPackageParcel;
|
|
import android.os.Binder;
|
|
import android.os.ISystemConfig;
|
|
import android.util.ArrayMap;
|
|
import android.util.ArraySet;
|
|
import android.util.SparseArray;
|
|
|
|
import com.android.internal.util.ArrayUtils;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Service class that runs inside the system_server process to handle queries to
|
|
* {@link com.android.server.SystemConfig}.
|
|
* @hide
|
|
*/
|
|
public class SystemConfigService extends SystemService {
|
|
private final Context mContext;
|
|
|
|
private final ISystemConfig.Stub mInterface = new ISystemConfig.Stub() {
|
|
@Override
|
|
public List<String> getDisabledUntilUsedPreinstalledCarrierApps() {
|
|
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,
|
|
"getDisabledUntilUsedPreInstalledCarrierApps requires READ_CARRIER_APP_INFO");
|
|
return new ArrayList<>(
|
|
SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps());
|
|
}
|
|
|
|
@Override
|
|
public Map getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
|
|
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,
|
|
"getDisabledUntilUsedPreInstalledCarrierAssociatedApps requires"
|
|
+ " READ_CARRIER_APP_INFO");
|
|
return SystemConfig.getInstance()
|
|
.getDisabledUntilUsedPreinstalledCarrierAssociatedApps().entrySet().stream()
|
|
.collect(toMap(
|
|
Map.Entry::getKey,
|
|
e -> e.getValue().stream().map(app -> app.packageName)
|
|
.collect(toList())));
|
|
}
|
|
|
|
@Override
|
|
public Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries() {
|
|
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,
|
|
"getDisabledUntilUsedPreInstalledCarrierAssociatedAppEntries requires"
|
|
+ " READ_CARRIER_APP_INFO");
|
|
return SystemConfig.getInstance()
|
|
.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
|
|
}
|
|
|
|
@Override
|
|
public int[] getSystemPermissionUids(String permissionName) {
|
|
mContext.enforceCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS,
|
|
"getSystemPermissionUids requires GET_RUNTIME_PERMISSIONS");
|
|
final List<Integer> uids = new ArrayList<>();
|
|
final SparseArray<ArraySet<String>> systemPermissions =
|
|
SystemConfig.getInstance().getSystemPermissions();
|
|
for (int i = 0; i < systemPermissions.size(); i++) {
|
|
final ArraySet<String> permissions = systemPermissions.valueAt(i);
|
|
if (permissions != null && permissions.contains(permissionName)) {
|
|
uids.add(systemPermissions.keyAt(i));
|
|
}
|
|
}
|
|
return ArrayUtils.convertToIntArray(uids);
|
|
}
|
|
|
|
@Override
|
|
public List<ComponentName> getEnabledComponentOverrides(String packageName) {
|
|
ArrayMap<String, Boolean> systemComponents = SystemConfig.getInstance()
|
|
.getComponentsEnabledStates(packageName);
|
|
List<ComponentName> enabledComponent = new ArrayList<>();
|
|
if (systemComponents != null) {
|
|
for (Map.Entry<String, Boolean> entry : systemComponents.entrySet()) {
|
|
if (Boolean.TRUE.equals(entry.getValue())) {
|
|
enabledComponent.add(new ComponentName(packageName, entry.getKey()));
|
|
}
|
|
}
|
|
}
|
|
return enabledComponent;
|
|
}
|
|
|
|
@Override
|
|
public List<ComponentName> getDefaultVrComponents() {
|
|
getContext().enforceCallingOrSelfPermission(Manifest.permission.QUERY_ALL_PACKAGES,
|
|
"Caller must hold " + Manifest.permission.QUERY_ALL_PACKAGES);
|
|
return new ArrayList<>(SystemConfig.getInstance().getDefaultVrComponents());
|
|
}
|
|
|
|
@Override
|
|
public List<String> getPreventUserDisablePackages() {
|
|
PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
|
|
return SystemConfig.getInstance().getPreventUserDisablePackages().stream()
|
|
.filter(preventUserDisablePackage ->
|
|
pmi.canQueryPackage(Binder.getCallingUid(), preventUserDisablePackage))
|
|
.collect(toList());
|
|
}
|
|
|
|
@Override
|
|
public List<SignedPackageParcel> getEnhancedConfirmationTrustedPackages() {
|
|
getContext().enforceCallingOrSelfPermission(
|
|
Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES,
|
|
"Caller must hold " + Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES);
|
|
|
|
return SystemConfig.getInstance().getEnhancedConfirmationTrustedPackages().stream()
|
|
.map(SignedPackage::getData).toList();
|
|
}
|
|
|
|
@Override
|
|
public List<SignedPackageParcel> getEnhancedConfirmationTrustedInstallers() {
|
|
getContext().enforceCallingOrSelfPermission(
|
|
Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES,
|
|
"Caller must hold " + Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES);
|
|
|
|
return SystemConfig.getInstance().getEnhancedConfirmationTrustedInstallers().stream()
|
|
.map(SignedPackage::getData).toList();
|
|
}
|
|
};
|
|
|
|
public SystemConfigService(Context context) {
|
|
super(context);
|
|
mContext = context;
|
|
}
|
|
|
|
@Override
|
|
public void onStart() {
|
|
publishBinderService(Context.SYSTEM_CONFIG_SERVICE, mInterface);
|
|
}
|
|
}
|