Merge "Revert "OMS: integrate OverlayManagerService into framework""
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := idmap.cpp create.cpp inspect.cpp
|
||||
LOCAL_SRC_FILES := idmap.cpp create.cpp scan.cpp inspect.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := liblog libutils libandroidfw
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ SYNOPSIS \n\
|
||||
idmap --help \n\
|
||||
idmap --fd target overlay fd \n\
|
||||
idmap --path target overlay idmap \n\
|
||||
idmap --scan target-package-name-to-look-for path-to-target-apk dir-to-hold-idmaps \\\
|
||||
dir-to-scan [additional-dir-to-scan [additional-dir-to-scan [...]]]\n\
|
||||
idmap --inspect idmap \n\
|
||||
\n\
|
||||
DESCRIPTION \n\
|
||||
@@ -46,6 +48,11 @@ OPTIONS \n\
|
||||
\n\
|
||||
--path: create idmap for target package 'target' (path to apk) and overlay package \n\
|
||||
'overlay' (path to apk); write results to 'idmap' (path). \n\
|
||||
\n\
|
||||
--scan: non-recursively search directory 'dir-to-scan' (path) for overlay packages with \n\
|
||||
target package 'target-package-name-to-look-for' (package name) present at\n\
|
||||
'path-to-target-apk' (path to apk). For each overlay package found, create an\n\
|
||||
idmap file in 'dir-to-hold-idmaps' (path). \n\
|
||||
\n\
|
||||
--inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\
|
||||
debug-friendly format. \n\
|
||||
@@ -90,6 +97,16 @@ EXAMPLES \n\
|
||||
NOTES \n\
|
||||
This tool and its expected invocation from installd is modelled on dexopt.";
|
||||
|
||||
bool verify_directory_readable(const char *path)
|
||||
{
|
||||
return access(path, R_OK | X_OK) == 0;
|
||||
}
|
||||
|
||||
bool verify_directory_writable(const char *path)
|
||||
{
|
||||
return access(path, W_OK) == 0;
|
||||
}
|
||||
|
||||
bool verify_file_readable(const char *path)
|
||||
{
|
||||
return access(path, R_OK) == 0;
|
||||
@@ -150,6 +167,36 @@ NOTES \n\
|
||||
return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
|
||||
}
|
||||
|
||||
int maybe_scan(const char *target_package_name, const char *target_apk_path,
|
||||
const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
|
||||
{
|
||||
if (!verify_root_or_system()) {
|
||||
fprintf(stderr, "error: permission denied: not user root or user system\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!verify_file_readable(target_apk_path)) {
|
||||
ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!verify_directory_writable(idmap_dir)) {
|
||||
ALOGD("error: no write access to %s: %s\n", idmap_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t N = overlay_dirs->size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
const char *dir = overlay_dirs->itemAt(i);
|
||||
if (!verify_directory_readable(dir)) {
|
||||
ALOGD("error: no read access to %s: %s\n", dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return idmap_scan(target_package_name, target_apk_path, idmap_dir, overlay_dirs);
|
||||
}
|
||||
|
||||
int maybe_inspect(const char *idmap_path)
|
||||
{
|
||||
// anyone (not just root or system) may do --inspect
|
||||
@@ -188,6 +235,14 @@ int main(int argc, char **argv)
|
||||
return maybe_create_path(argv[2], argv[3], argv[4]);
|
||||
}
|
||||
|
||||
if (argc >= 6 && !strcmp(argv[1], "--scan")) {
|
||||
android::Vector<const char *> v;
|
||||
for (int i = 5; i < argc; i++) {
|
||||
v.push(argv[i]);
|
||||
}
|
||||
return maybe_scan(argv[2], argv[3], argv[4], &v);
|
||||
}
|
||||
|
||||
if (argc == 3 && !strcmp(argv[1], "--inspect")) {
|
||||
return maybe_inspect(argv[2]);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,12 @@ int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
|
||||
|
||||
int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
|
||||
|
||||
// Regarding target_package_name: the idmap_scan implementation should
|
||||
// be able to extract this from the manifest in target_apk_path,
|
||||
// simplifying the external API.
|
||||
int idmap_scan(const char *target_package_name, const char *target_apk_path,
|
||||
const char *idmap_dir, const android::Vector<const char *> *overlay_dirs);
|
||||
|
||||
int idmap_inspect(const char *idmap_path);
|
||||
|
||||
#endif // _IDMAP_H_
|
||||
|
||||
239
cmds/idmap/scan.cpp
Normal file
239
cmds/idmap/scan.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "idmap.h"
|
||||
|
||||
#include <memory>
|
||||
#include <androidfw/ResourceTypes.h>
|
||||
#include <androidfw/StreamingZipInflater.h>
|
||||
#include <androidfw/ZipFileRO.h>
|
||||
#include <private/android_filesystem_config.h> // for AID_SYSTEM
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/String16.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#define NO_OVERLAY_TAG (-1000)
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace {
|
||||
struct Overlay {
|
||||
Overlay() {}
|
||||
Overlay(const String8& a, const String8& i, int p) :
|
||||
apk_path(a), idmap_path(i), priority(p) {}
|
||||
|
||||
bool operator<(Overlay const& rhs) const
|
||||
{
|
||||
return rhs.priority > priority;
|
||||
}
|
||||
|
||||
String8 apk_path;
|
||||
String8 idmap_path;
|
||||
int priority;
|
||||
};
|
||||
|
||||
bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
|
||||
{
|
||||
// the file is opened for appending so that it doesn't get truncated
|
||||
// before we can guarantee mutual exclusion via the flock
|
||||
FILE* fout = fopen(filename, "a");
|
||||
if (fout == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) {
|
||||
fclose(fout);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) {
|
||||
TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
|
||||
fclose(fout);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < overlayVector.size(); ++i) {
|
||||
const Overlay& overlay = overlayVector[i];
|
||||
fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
|
||||
}
|
||||
|
||||
TEMP_FAILURE_RETRY(fflush(fout));
|
||||
TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
|
||||
fclose(fout);
|
||||
|
||||
// Make file world readable since Zygote (running as root) will read
|
||||
// it when creating the initial AssetManger object
|
||||
const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
|
||||
if (chmod(filename, mode) == -1) {
|
||||
unlink(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String8 flatten_path(const char *path)
|
||||
{
|
||||
String16 tmp(path);
|
||||
tmp.replaceAll('/', '@');
|
||||
return String8(tmp);
|
||||
}
|
||||
|
||||
int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name)
|
||||
{
|
||||
const size_t N = parser.getAttributeCount();
|
||||
String16 target;
|
||||
int priority = -1;
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
size_t len;
|
||||
String16 key(parser.getAttributeName(i, &len));
|
||||
if (key == String16("targetPackage")) {
|
||||
const char16_t *p = parser.getAttributeStringValue(i, &len);
|
||||
if (p != NULL) {
|
||||
target = String16(p, len);
|
||||
}
|
||||
} else if (key == String16("priority")) {
|
||||
Res_value v;
|
||||
if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
|
||||
priority = v.data;
|
||||
if (priority < 0 || priority > 9999) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target == String16(target_package_name)) {
|
||||
return priority;
|
||||
}
|
||||
return NO_OVERLAY_TAG;
|
||||
}
|
||||
|
||||
int parse_manifest(const void *data, size_t size, const char *target_package_name)
|
||||
{
|
||||
ResXMLTree parser;
|
||||
parser.setTo(data, size);
|
||||
if (parser.getError() != NO_ERROR) {
|
||||
ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
ResXMLParser::event_code_t type;
|
||||
do {
|
||||
type = parser.next();
|
||||
if (type == ResXMLParser::START_TAG) {
|
||||
size_t len;
|
||||
String16 tag(parser.getElementName(&len));
|
||||
if (tag == String16("overlay")) {
|
||||
return parse_overlay_tag(parser, target_package_name);
|
||||
}
|
||||
}
|
||||
} while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
|
||||
|
||||
return NO_OVERLAY_TAG;
|
||||
}
|
||||
|
||||
int parse_apk(const char *path, const char *target_package_name)
|
||||
{
|
||||
std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(path));
|
||||
if (zip.get() == NULL) {
|
||||
ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path);
|
||||
return -1;
|
||||
}
|
||||
ZipEntryRO entry;
|
||||
if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) {
|
||||
ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
uint32_t uncompLen = 0;
|
||||
uint16_t method;
|
||||
if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) {
|
||||
ALOGW("%s: failed to read entry info\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (method != ZipFileRO::kCompressDeflated) {
|
||||
ALOGW("%s: cannot handle zip compression method %" PRIu16 "\n", __FUNCTION__, method);
|
||||
return -1;
|
||||
}
|
||||
FileMap *dataMap = zip->createEntryFileMap(entry);
|
||||
if (dataMap == NULL) {
|
||||
ALOGW("%s: failed to create FileMap\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
char *buf = new char[uncompLen];
|
||||
if (NULL == buf) {
|
||||
ALOGW("%s: failed to allocate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
|
||||
delete dataMap;
|
||||
return -1;
|
||||
}
|
||||
StreamingZipInflater inflater(dataMap, uncompLen);
|
||||
if (inflater.read(buf, uncompLen) < 0) {
|
||||
ALOGW("%s: failed to inflate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
|
||||
delete[] buf;
|
||||
delete dataMap;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int priority = parse_manifest(buf, static_cast<size_t>(uncompLen), target_package_name);
|
||||
delete[] buf;
|
||||
delete dataMap;
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
|
||||
int idmap_scan(const char *target_package_name, const char *target_apk_path,
|
||||
const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
|
||||
{
|
||||
String8 filename = String8(idmap_dir);
|
||||
filename.appendPath("overlays.list");
|
||||
|
||||
SortedVector<Overlay> overlayVector;
|
||||
const size_t N = overlay_dirs->size();
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
const char *overlay_dir = overlay_dirs->itemAt(i);
|
||||
DIR *dir = opendir(overlay_dir);
|
||||
if (dir == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct dirent *dirent;
|
||||
while ((dirent = readdir(dir)) != NULL) {
|
||||
struct stat st;
|
||||
char overlay_apk_path[PATH_MAX + 1];
|
||||
snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
|
||||
if (stat(overlay_apk_path, &st) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int priority = parse_apk(overlay_apk_path, target_package_name);
|
||||
if (priority < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String8 idmap_path(idmap_dir);
|
||||
idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
|
||||
idmap_path.append("@idmap");
|
||||
|
||||
if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
|
||||
ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
|
||||
target_apk_path, overlay_apk_path, idmap_path.string());
|
||||
continue;
|
||||
}
|
||||
|
||||
Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
|
||||
overlayVector.add(overlay);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
if (!writePackagesList(filename.string(), overlayVector)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -2065,6 +2065,9 @@ public class PackageParser {
|
||||
com.android.internal.R.styleable.AndroidManifestResourceOverlay);
|
||||
pkg.mOverlayTarget = sa.getString(
|
||||
com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
|
||||
pkg.mOverlayPriority = sa.getInt(
|
||||
com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
|
||||
-1);
|
||||
sa.recycle();
|
||||
|
||||
if (pkg.mOverlayTarget == null) {
|
||||
@@ -2072,6 +2075,12 @@ public class PackageParser {
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
}
|
||||
if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
|
||||
outError[0] = "<overlay> priority must be between 0 and 9999";
|
||||
mParseError =
|
||||
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||
return null;
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
|
||||
} else if (tagName.equals(TAG_KEY_SETS)) {
|
||||
@@ -5509,6 +5518,7 @@ public class PackageParser {
|
||||
public String mRequiredAccountType;
|
||||
|
||||
public String mOverlayTarget;
|
||||
public int mOverlayPriority;
|
||||
public boolean mTrustedOverlay;
|
||||
|
||||
/**
|
||||
@@ -5985,6 +5995,7 @@ public class PackageParser {
|
||||
mRestrictedAccountType = dest.readString();
|
||||
mRequiredAccountType = dest.readString();
|
||||
mOverlayTarget = dest.readString();
|
||||
mOverlayPriority = dest.readInt();
|
||||
mTrustedOverlay = (dest.readInt() == 1);
|
||||
mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
|
||||
mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
|
||||
@@ -6100,6 +6111,7 @@ public class PackageParser {
|
||||
dest.writeString(mRestrictedAccountType);
|
||||
dest.writeString(mRequiredAccountType);
|
||||
dest.writeString(mOverlayTarget);
|
||||
dest.writeInt(mOverlayPriority);
|
||||
dest.writeInt(mTrustedOverlay ? 1 : 0);
|
||||
dest.writeArraySet(mSigningKeys);
|
||||
dest.writeArraySet(mUpgradeKeySets);
|
||||
@@ -6548,7 +6560,6 @@ public class PackageParser {
|
||||
ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
|
||||
}
|
||||
ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
|
||||
ai.resourceDirs = state.resourceDirs;
|
||||
}
|
||||
|
||||
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
|
||||
|
||||
@@ -31,8 +31,6 @@ import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Per-user state information about a package.
|
||||
* @hide
|
||||
@@ -56,8 +54,6 @@ public class PackageUserState {
|
||||
public ArraySet<String> disabledComponents;
|
||||
public ArraySet<String> enabledComponents;
|
||||
|
||||
public String[] resourceDirs;
|
||||
|
||||
public PackageUserState() {
|
||||
installed = true;
|
||||
hidden = false;
|
||||
@@ -85,8 +81,6 @@ public class PackageUserState {
|
||||
installReason = o.installReason;
|
||||
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
|
||||
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
|
||||
resourceDirs =
|
||||
o.resourceDirs == null ? null : Arrays.copyOf(o.resourceDirs, o.resourceDirs.length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,6 +119,96 @@ jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
|
||||
return block;
|
||||
}
|
||||
|
||||
// This is called by zygote (running as user root) as part of preloadResources.
|
||||
static void verifySystemIdmaps()
|
||||
{
|
||||
pid_t pid;
|
||||
char system_id[10];
|
||||
|
||||
snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
|
||||
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
ALOGE("failed to fork for idmap: %s", strerror(errno));
|
||||
break;
|
||||
case 0: // child
|
||||
{
|
||||
struct __user_cap_header_struct capheader;
|
||||
struct __user_cap_data_struct capdata;
|
||||
|
||||
memset(&capheader, 0, sizeof(capheader));
|
||||
memset(&capdata, 0, sizeof(capdata));
|
||||
|
||||
capheader.version = _LINUX_CAPABILITY_VERSION;
|
||||
capheader.pid = 0;
|
||||
|
||||
if (capget(&capheader, &capdata) != 0) {
|
||||
ALOGE("capget: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
capdata.effective = capdata.permitted;
|
||||
if (capset(&capheader, &capdata) != 0) {
|
||||
ALOGE("capset: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgid(AID_SYSTEM) != 0) {
|
||||
ALOGE("setgid: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(AID_SYSTEM) != 0) {
|
||||
ALOGE("setuid: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Generic idmap parameters
|
||||
const char* argv[8];
|
||||
int argc = 0;
|
||||
struct stat st;
|
||||
|
||||
memset(argv, NULL, sizeof(argv));
|
||||
argv[argc++] = AssetManager::IDMAP_BIN;
|
||||
argv[argc++] = "--scan";
|
||||
argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
|
||||
argv[argc++] = AssetManager::TARGET_APK_PATH;
|
||||
argv[argc++] = AssetManager::IDMAP_DIR;
|
||||
|
||||
// Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
|
||||
// use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
|
||||
char subdir[PROP_VALUE_MAX];
|
||||
int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PERSIST_PROPERTY,
|
||||
subdir);
|
||||
if (len == 0) {
|
||||
len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
|
||||
}
|
||||
if (len > 0) {
|
||||
String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
|
||||
if (stat(overlayPath.string(), &st) == 0) {
|
||||
argv[argc++] = overlayPath.string();
|
||||
}
|
||||
}
|
||||
if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
|
||||
argv[argc++] = AssetManager::OVERLAY_DIR;
|
||||
}
|
||||
|
||||
// Finally, invoke idmap (if any overlay directory exists)
|
||||
if (argc > 5) {
|
||||
execv(AssetManager::IDMAP_BIN, (char* const*)argv);
|
||||
ALOGE("failed to execv for idmap: %s", strerror(errno));
|
||||
exit(1); // should never get here
|
||||
} else {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: // parent
|
||||
waitpid(pid, NULL, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// this guy is exported to other jni routines
|
||||
@@ -1507,6 +1597,9 @@ static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jo
|
||||
|
||||
static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
|
||||
{
|
||||
if (isSystem) {
|
||||
verifySystemIdmaps();
|
||||
}
|
||||
AssetManager* am = new AssetManager();
|
||||
if (am == NULL) {
|
||||
jniThrowException(env, "java/lang/OutOfMemoryError", "");
|
||||
|
||||
@@ -202,6 +202,15 @@ bool AssetManager::addAssetPath(
|
||||
*cookie = static_cast<int32_t>(mAssetPaths.size());
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Load overlays, if any
|
||||
asset_path oap;
|
||||
for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) {
|
||||
oap.isSystemAsset = isSystemAsset;
|
||||
mAssetPaths.add(oap);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mResources != NULL) {
|
||||
appendPathToResTable(ap, appAsLib);
|
||||
}
|
||||
@@ -484,6 +493,11 @@ FileType AssetManager::getFileType(const char* fileName)
|
||||
}
|
||||
|
||||
bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) const {
|
||||
// skip those ap's that correspond to system overlays
|
||||
if (ap.isSystemOverlay) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Asset* ass = NULL;
|
||||
ResTable* sharedRes = NULL;
|
||||
bool shared = true;
|
||||
@@ -525,6 +539,14 @@ bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) con
|
||||
ALOGV("Creating shared resources for %s", ap.path.string());
|
||||
sharedRes = new ResTable();
|
||||
sharedRes->add(ass, idmap, nextEntryIdx + 1, false);
|
||||
#ifdef __ANDROID__
|
||||
const char* data = getenv("ANDROID_DATA");
|
||||
LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
|
||||
String8 overlaysListPath(data);
|
||||
overlaysListPath.appendPath(kResourceCache);
|
||||
overlaysListPath.appendPath("overlays.list");
|
||||
addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, nextEntryIdx);
|
||||
#endif
|
||||
sharedRes = const_cast<AssetManager*>(this)->
|
||||
mZipSet.setZipResourceTable(ap.path, sharedRes);
|
||||
}
|
||||
@@ -633,6 +655,58 @@ Asset* AssetManager::openIdmapLocked(const struct asset_path& ap) const
|
||||
return ass;
|
||||
}
|
||||
|
||||
void AssetManager::addSystemOverlays(const char* pathOverlaysList,
|
||||
const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const
|
||||
{
|
||||
FILE* fin = fopen(pathOverlaysList, "r");
|
||||
if (fin == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (TEMP_FAILURE_RETRY(flock(fileno(fin), LOCK_SH)) != 0) {
|
||||
fclose(fin);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
char buf[1024];
|
||||
while (fgets(buf, sizeof(buf), fin)) {
|
||||
// format of each line:
|
||||
// <path to apk><space><path to idmap><newline>
|
||||
char* space = strchr(buf, ' ');
|
||||
char* newline = strchr(buf, '\n');
|
||||
asset_path oap;
|
||||
|
||||
if (space == NULL || newline == NULL || newline < space) {
|
||||
continue;
|
||||
}
|
||||
|
||||
oap.path = String8(buf, space - buf);
|
||||
oap.type = kFileTypeRegular;
|
||||
oap.idmap = String8(space + 1, newline - space - 1);
|
||||
oap.isSystemOverlay = true;
|
||||
|
||||
Asset* oass = const_cast<AssetManager*>(this)->
|
||||
openNonAssetInPathLocked("resources.arsc",
|
||||
Asset::ACCESS_BUFFER,
|
||||
oap);
|
||||
|
||||
if (oass != NULL) {
|
||||
Asset* oidmap = openIdmapLocked(oap);
|
||||
offset++;
|
||||
sharedRes->add(oass, oidmap, offset + 1, false);
|
||||
const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
|
||||
const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
|
||||
delete oidmap;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
TEMP_FAILURE_RETRY(flock(fileno(fin), LOCK_UN));
|
||||
#endif
|
||||
fclose(fin);
|
||||
}
|
||||
|
||||
const ResTable& AssetManager::getResources(bool required) const
|
||||
{
|
||||
const ResTable* rt = getResTable(required);
|
||||
@@ -1372,6 +1446,20 @@ bool AssetManager::SharedZip::isUpToDate()
|
||||
return mModWhen == modWhen;
|
||||
}
|
||||
|
||||
void AssetManager::SharedZip::addOverlay(const asset_path& ap)
|
||||
{
|
||||
mOverlays.add(ap);
|
||||
}
|
||||
|
||||
bool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const
|
||||
{
|
||||
if (idx >= mOverlays.size()) {
|
||||
return false;
|
||||
}
|
||||
*out = mOverlays[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
AssetManager::SharedZip::~SharedZip()
|
||||
{
|
||||
if (kIsDebug) {
|
||||
@@ -1490,6 +1578,22 @@ bool AssetManager::ZipSet::isUpToDate()
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay)
|
||||
{
|
||||
int idx = getIndex(path);
|
||||
sp<SharedZip> zip = mZipFile[idx];
|
||||
zip->addOverlay(overlay);
|
||||
}
|
||||
|
||||
bool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const
|
||||
{
|
||||
sp<SharedZip> zip = SharedZip::get(path, false);
|
||||
if (zip == NULL) {
|
||||
return false;
|
||||
}
|
||||
return zip->getOverlay(idx, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the zip file's index.
|
||||
*
|
||||
|
||||
@@ -202,10 +202,12 @@ public:
|
||||
private:
|
||||
struct asset_path
|
||||
{
|
||||
asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemAsset(false) {}
|
||||
asset_path() : path(""), type(kFileTypeRegular), idmap(""),
|
||||
isSystemOverlay(false), isSystemAsset(false) {}
|
||||
String8 path;
|
||||
FileType type;
|
||||
String8 idmap;
|
||||
bool isSystemOverlay;
|
||||
bool isSystemAsset;
|
||||
};
|
||||
|
||||
@@ -235,6 +237,9 @@ private:
|
||||
|
||||
Asset* openIdmapLocked(const struct asset_path& ap) const;
|
||||
|
||||
void addSystemOverlays(const char* pathOverlaysList, const String8& targetPackagePath,
|
||||
ResTable* sharedRes, size_t offset) const;
|
||||
|
||||
class SharedZip : public RefBase {
|
||||
public:
|
||||
static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true);
|
||||
@@ -249,6 +254,9 @@ private:
|
||||
|
||||
bool isUpToDate();
|
||||
|
||||
void addOverlay(const asset_path& ap);
|
||||
bool getOverlay(size_t idx, asset_path* out) const;
|
||||
|
||||
protected:
|
||||
~SharedZip();
|
||||
|
||||
@@ -263,6 +271,8 @@ private:
|
||||
Asset* mResourceTableAsset;
|
||||
ResTable* mResourceTable;
|
||||
|
||||
Vector<asset_path> mOverlays;
|
||||
|
||||
static Mutex gLock;
|
||||
static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
|
||||
};
|
||||
@@ -296,6 +306,9 @@ private:
|
||||
|
||||
bool isUpToDate();
|
||||
|
||||
void addOverlay(const String8& path, const asset_path& overlay);
|
||||
bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
|
||||
|
||||
private:
|
||||
void closeZip(int idx);
|
||||
|
||||
|
||||
@@ -118,8 +118,6 @@
|
||||
<uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
|
||||
<!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<!-- Permission needed to enable/disable overlays -->
|
||||
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
|
||||
|
||||
<application android:label="@string/app_label"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
@@ -106,25 +105,22 @@ public class SystemServiceManager {
|
||||
+ ": service constructor threw an exception", ex);
|
||||
}
|
||||
|
||||
startService(service);
|
||||
// Register it.
|
||||
mServices.add(service);
|
||||
|
||||
// Start it.
|
||||
try {
|
||||
service.onStart();
|
||||
} catch (RuntimeException ex) {
|
||||
throw new RuntimeException("Failed to start service " + name
|
||||
+ ": onStart threw an exception", ex);
|
||||
}
|
||||
return service;
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
public void startService(@NonNull final SystemService service) {
|
||||
// Register it.
|
||||
mServices.add(service);
|
||||
// Start it.
|
||||
try {
|
||||
service.onStart();
|
||||
} catch (RuntimeException ex) {
|
||||
throw new RuntimeException("Failed to start service " + service.getClass().getName()
|
||||
+ ": onStart threw an exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the specified boot phase for all system services that have been started up to
|
||||
* this point.
|
||||
|
||||
@@ -664,38 +664,7 @@ public final class OverlayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void updateAssets(final int userId, List<String> targetPackageNames) {
|
||||
final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
|
||||
final boolean updateFrameworkRes = targetPackageNames.contains("android");
|
||||
if (updateFrameworkRes) {
|
||||
targetPackageNames = pm.getTargetPackageNames(userId);
|
||||
}
|
||||
|
||||
final Map<String, List<String>> pendingChanges = new ArrayMap<>(targetPackageNames.size());
|
||||
synchronized (mLock) {
|
||||
final int N = targetPackageNames.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final String targetPackageName = targetPackageNames.get(i);
|
||||
pendingChanges.put(targetPackageName,
|
||||
mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
|
||||
}
|
||||
}
|
||||
|
||||
final int N = targetPackageNames.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final String targetPackageName = targetPackageNames.get(i);
|
||||
if (!pm.setEnabledOverlayPackages(
|
||||
userId, targetPackageName, pendingChanges.get(targetPackageName))) {
|
||||
Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
|
||||
targetPackageName, userId));
|
||||
}
|
||||
}
|
||||
|
||||
final IActivityManager am = ActivityManagerNative.getDefault();
|
||||
try {
|
||||
am.scheduleApplicationInfoChanged(targetPackageNames, userId);
|
||||
} catch (RemoteException e) {
|
||||
// Intentionally left empty.
|
||||
}
|
||||
// TODO: implement when we integrate OMS properly
|
||||
}
|
||||
|
||||
private void schedulePersistSettings() {
|
||||
|
||||
@@ -661,12 +661,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final ArrayMap<String, Set<String>> mKnownCodebase =
|
||||
new ArrayMap<String, Set<String>>();
|
||||
|
||||
// List of APK paths to load for each user and package. This data is never
|
||||
// persisted by the package manager. Instead, the overlay manager will
|
||||
// ensure the data is up-to-date in runtime.
|
||||
@GuardedBy("mPackages")
|
||||
final SparseArray<ArrayMap<String, ArrayList<String>>> mEnabledOverlayPaths =
|
||||
new SparseArray<ArrayMap<String, ArrayList<String>>>();
|
||||
// Tracks available target package names -> overlay package paths.
|
||||
final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
|
||||
new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
|
||||
|
||||
/**
|
||||
* Tracks new system packages [received in an OTA] that we expect to
|
||||
@@ -3737,7 +3734,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
|
||||
ps.readUserState(userId), userId);
|
||||
if (ai != null) {
|
||||
rebaseEnabledOverlays(ai, userId);
|
||||
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
|
||||
}
|
||||
return ai;
|
||||
@@ -3772,7 +3768,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
ApplicationInfo ai = PackageParser.generateApplicationInfo(
|
||||
p, flags, ps.readUserState(userId), userId);
|
||||
if (ai != null) {
|
||||
rebaseEnabledOverlays(ai, userId);
|
||||
ai.packageName = resolveExternalPackageNameLPr(p);
|
||||
}
|
||||
return ai;
|
||||
@@ -3789,26 +3784,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void rebaseEnabledOverlays(@NonNull ApplicationInfo ai, int userId) {
|
||||
List<String> paths = new ArrayList<>();
|
||||
ArrayMap<String, ArrayList<String>> userSpecificOverlays =
|
||||
mEnabledOverlayPaths.get(userId);
|
||||
if (userSpecificOverlays != null) {
|
||||
if (!"android".equals(ai.packageName)) {
|
||||
ArrayList<String> frameworkOverlays = userSpecificOverlays.get("android");
|
||||
if (frameworkOverlays != null) {
|
||||
paths.addAll(frameworkOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> appOverlays = userSpecificOverlays.get(ai.packageName);
|
||||
if (appOverlays != null) {
|
||||
paths.addAll(appOverlays);
|
||||
}
|
||||
}
|
||||
ai.resourceDirs = paths.size() > 0 ? paths.toArray(new String[paths.size()]) : null;
|
||||
}
|
||||
|
||||
private String normalizePackageNameLPr(String packageName) {
|
||||
String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
|
||||
return normalizedPackageName != null ? normalizedPackageName : packageName;
|
||||
@@ -7172,7 +7147,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
|
||||
ps.readUserState(userId), userId);
|
||||
if (ai != null) {
|
||||
rebaseEnabledOverlays(ai, userId);
|
||||
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
|
||||
}
|
||||
} else {
|
||||
@@ -7196,7 +7170,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
|
||||
ps.readUserState(userId), userId);
|
||||
if (ai != null) {
|
||||
rebaseEnabledOverlays(ai, userId);
|
||||
ai.packageName = resolveExternalPackageNameLPr(p);
|
||||
list.add(ai);
|
||||
}
|
||||
@@ -7340,7 +7313,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
|
||||
ps.readUserState(userId), userId);
|
||||
if (ai != null) {
|
||||
rebaseEnabledOverlays(ai, userId);
|
||||
finalList.add(ai);
|
||||
}
|
||||
}
|
||||
@@ -7476,6 +7448,60 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return finalList;
|
||||
}
|
||||
|
||||
private void createIdmapsForPackageLI(PackageParser.Package pkg) {
|
||||
ArrayMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName);
|
||||
if (overlays == null) {
|
||||
Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages");
|
||||
return;
|
||||
}
|
||||
for (PackageParser.Package opkg : overlays.values()) {
|
||||
// Not much to do if idmap fails: we already logged the error
|
||||
// and we certainly don't want to abort installation of pkg simply
|
||||
// because an overlay didn't fit properly. For these reasons,
|
||||
// ignore the return value of createIdmapForPackagePairLI.
|
||||
createIdmapForPackagePairLI(pkg, opkg);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
|
||||
PackageParser.Package opkg) {
|
||||
if (!opkg.mTrustedOverlay) {
|
||||
Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
|
||||
opkg.baseCodePath + ": overlay not trusted");
|
||||
return false;
|
||||
}
|
||||
ArrayMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
|
||||
if (overlaySet == null) {
|
||||
Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
|
||||
opkg.baseCodePath + " but target package has no known overlays");
|
||||
return false;
|
||||
}
|
||||
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
|
||||
// TODO: generate idmap for split APKs
|
||||
try {
|
||||
mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid);
|
||||
} catch (InstallerException e) {
|
||||
Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
|
||||
+ opkg.baseCodePath);
|
||||
return false;
|
||||
}
|
||||
PackageParser.Package[] overlayArray =
|
||||
overlaySet.values().toArray(new PackageParser.Package[0]);
|
||||
Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
|
||||
public int compare(PackageParser.Package p1, PackageParser.Package p2) {
|
||||
return p1.mOverlayPriority - p2.mOverlayPriority;
|
||||
}
|
||||
};
|
||||
Arrays.sort(overlayArray, cmp);
|
||||
|
||||
pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
|
||||
int i = 0;
|
||||
for (PackageParser.Package p : overlayArray) {
|
||||
pkg.applicationInfo.resourceDirs[i++] = p.baseCodePath;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + dir.getAbsolutePath() + "]");
|
||||
try {
|
||||
@@ -9964,6 +9990,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// writer
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
|
||||
|
||||
boolean createIdmapFailed = false;
|
||||
synchronized (mPackages) {
|
||||
// We don't expect installation to fail beyond this point
|
||||
|
||||
@@ -10304,9 +10331,36 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Create idmap files for pairs of (packages, overlay packages).
|
||||
// Note: "android", ie framework-res.apk, is handled by native layers.
|
||||
if (pkg.mOverlayTarget != null) {
|
||||
// This is an overlay package.
|
||||
if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
|
||||
if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
|
||||
mOverlays.put(pkg.mOverlayTarget,
|
||||
new ArrayMap<String, PackageParser.Package>());
|
||||
}
|
||||
ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
|
||||
map.put(pkg.packageName, pkg);
|
||||
PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
|
||||
if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
|
||||
createIdmapFailed = true;
|
||||
}
|
||||
}
|
||||
} else if (mOverlays.containsKey(pkg.packageName) &&
|
||||
!pkg.packageName.equals("android")) {
|
||||
// This is a regular package, with one or more known overlay packages.
|
||||
createIdmapsForPackageLI(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
|
||||
if (createIdmapFailed) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
|
||||
"scanPackageLI failed to createIdmap");
|
||||
}
|
||||
}
|
||||
|
||||
private static void maybeRenameForeignDexMarkers(PackageParser.Package existing,
|
||||
@@ -20105,7 +20159,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
public static final int DUMP_FROZEN = 1 << 19;
|
||||
public static final int DUMP_DEXOPT = 1 << 20;
|
||||
public static final int DUMP_COMPILER_STATS = 1 << 21;
|
||||
public static final int DUMP_ENABLED_OVERLAYS = 1 << 22;
|
||||
|
||||
public static final int OPTION_SHOW_FILTERS = 1 << 0;
|
||||
|
||||
@@ -20225,7 +20278,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
pw.println(" check-permission <permission> <package> [<user>]: does pkg hold perm?");
|
||||
pw.println(" dexopt: dump dexopt state");
|
||||
pw.println(" compiler-stats: dump compiler statistics");
|
||||
pw.println(" enabled-overlays: dump list of enabled overlay packages");
|
||||
pw.println(" <package.name>: info about given package");
|
||||
return;
|
||||
} else if ("--checkin".equals(opt)) {
|
||||
@@ -20354,8 +20406,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
dumpState.setDump(DumpState.DUMP_DEXOPT);
|
||||
} else if ("compiler-stats".equals(cmd)) {
|
||||
dumpState.setDump(DumpState.DUMP_COMPILER_STATS);
|
||||
} else if ("enabled-overlays".equals(cmd)) {
|
||||
dumpState.setDump(DumpState.DUMP_ENABLED_OVERLAYS);
|
||||
} else if ("write".equals(cmd)) {
|
||||
synchronized (mPackages) {
|
||||
mSettings.writeLPr();
|
||||
@@ -20726,11 +20776,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
dumpCompilerStatsLPr(pw, packageName);
|
||||
}
|
||||
|
||||
if (!checkin && dumpState.isDumping(DumpState.DUMP_ENABLED_OVERLAYS)) {
|
||||
if (dumpState.onTitlePrinted()) pw.println();
|
||||
dumpEnabledOverlaysLPr(pw);
|
||||
}
|
||||
|
||||
if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
|
||||
if (dumpState.onTitlePrinted()) pw.println();
|
||||
mSettings.dumpReadMessagesLPr(pw, dumpState);
|
||||
@@ -20827,23 +20872,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpEnabledOverlaysLPr(PrintWriter pw) {
|
||||
pw.println("Enabled overlay paths:");
|
||||
final int N = mEnabledOverlayPaths.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final int userId = mEnabledOverlayPaths.keyAt(i);
|
||||
pw.println(String.format(" User %d:", userId));
|
||||
final ArrayMap<String, ArrayList<String>> userSpecificOverlays =
|
||||
mEnabledOverlayPaths.valueAt(i);
|
||||
final int M = userSpecificOverlays.size();
|
||||
for (int j = 0; j < M; j++) {
|
||||
final String targetPackageName = userSpecificOverlays.keyAt(j);
|
||||
final ArrayList<String> overlayPackagePaths = userSpecificOverlays.valueAt(j);
|
||||
pw.println(String.format(" %s: %s", targetPackageName, overlayPackagePaths));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String dumpDomainString(String packageName) {
|
||||
List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
|
||||
.getList();
|
||||
@@ -22947,43 +22975,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setEnabledOverlayPackages(int userId, @NonNull String targetPackageName,
|
||||
@Nullable List<String> overlayPackageNames) {
|
||||
synchronized (mPackages) {
|
||||
if (targetPackageName == null || mPackages.get(targetPackageName) == null) {
|
||||
Slog.e(TAG, "failed to find package " + targetPackageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
ArrayList<String> paths = null;
|
||||
if (overlayPackageNames != null) {
|
||||
final int N = overlayPackageNames.size();
|
||||
paths = new ArrayList<String>(N);
|
||||
for (int i = 0; i < N; i++) {
|
||||
final String packageName = overlayPackageNames.get(i);
|
||||
final PackageParser.Package pkg = mPackages.get(packageName);
|
||||
if (pkg == null) {
|
||||
Slog.e(TAG, "failed to find package " + packageName);
|
||||
return false;
|
||||
}
|
||||
paths.add(pkg.baseCodePath);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayMap<String, ArrayList<String>> userSpecificOverlays =
|
||||
mEnabledOverlayPaths.get(userId);
|
||||
if (userSpecificOverlays == null) {
|
||||
userSpecificOverlays = new ArrayMap<String, ArrayList<String>>();
|
||||
mEnabledOverlayPaths.put(userId, userSpecificOverlays);
|
||||
}
|
||||
|
||||
if (paths != null && paths.size() > 0) {
|
||||
userSpecificOverlays.put(targetPackageName, paths);
|
||||
} else {
|
||||
userSpecificOverlays.remove(targetPackageName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
|
||||
List<String> overlayPackageNames) {
|
||||
// TODO: implement when we integrate OMS properly
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ import com.android.server.media.projection.MediaProjectionManagerService;
|
||||
import com.android.server.net.NetworkPolicyManagerService;
|
||||
import com.android.server.net.NetworkStatsService;
|
||||
import com.android.server.notification.NotificationManagerService;
|
||||
import com.android.server.om.OverlayManagerService;
|
||||
import com.android.server.os.DeviceIdentifiersPolicyService;
|
||||
import com.android.server.os.SchedulingPolicyService;
|
||||
import com.android.server.pm.Installer;
|
||||
@@ -593,11 +592,6 @@ public final class SystemServer {
|
||||
mActivityManagerService.setSystemProcess();
|
||||
traceEnd();
|
||||
|
||||
// Manages Overlay packages
|
||||
traceBeginAndSlog("StartOverlayManagerService");
|
||||
mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
|
||||
traceEnd();
|
||||
|
||||
// The sensor service needs access to package manager service, app ops
|
||||
// service, and permissions service, therefore we start it after them.
|
||||
// Start sensor service in a separate thread. Completion should be checked
|
||||
|
||||
@@ -197,6 +197,7 @@ public class PackageParserTest {
|
||||
assertEquals(a.installLocation, b.installLocation);
|
||||
assertEquals(a.coreApp, b.coreApp);
|
||||
assertEquals(a.mRequiredForAllUsers, b.mRequiredForAllUsers);
|
||||
assertEquals(a.mOverlayPriority, b.mOverlayPriority);
|
||||
assertEquals(a.mTrustedOverlay, b.mTrustedOverlay);
|
||||
assertEquals(a.use32bitAbi, b.use32bitAbi);
|
||||
assertEquals(a.packageName, b.packageName);
|
||||
@@ -432,6 +433,7 @@ public class PackageParserTest {
|
||||
pkg.installLocation = 100;
|
||||
pkg.coreApp = true;
|
||||
pkg.mRequiredForAllUsers = true;
|
||||
pkg.mOverlayPriority = 100;
|
||||
pkg.mTrustedOverlay = true;
|
||||
pkg.use32bitAbi = true;
|
||||
pkg.packageName = "foo";
|
||||
|
||||
Reference in New Issue
Block a user