Merge "Add new internal resolve method"
diff --git a/Android.mk b/Android.mk
index b204da7..109f610 100644
--- a/Android.mk
+++ b/Android.mk
@@ -931,6 +931,7 @@
-since $(SRC_API_DIR)/23.txt 23 \
-since $(SRC_API_DIR)/24.txt 24 \
-since $(SRC_API_DIR)/25.txt 25 \
+ -since ./frameworks/base/api/current.txt O \
-werror -hide 111 -hide 113 \
-overview $(LOCAL_PATH)/core/java/overview.html
diff --git a/cmds/idmap/Android.mk b/cmds/idmap/Android.mk
index 50ccb07..eb6da18e 100644
--- a/cmds/idmap/Android.mk
+++ b/cmds/idmap/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := idmap.cpp create.cpp scan.cpp inspect.cpp
+LOCAL_SRC_FILES := idmap.cpp create.cpp inspect.cpp
LOCAL_SHARED_LIBRARIES := liblog libutils libandroidfw
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
index 3ab1915..d388977 100644
--- a/cmds/idmap/idmap.cpp
+++ b/cmds/idmap/idmap.cpp
@@ -13,8 +13,6 @@
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\
@@ -49,11 +47,6 @@
--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\
\n\
@@ -97,16 +90,6 @@
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;
@@ -167,36 +150,6 @@
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
@@ -235,14 +188,6 @@
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]);
}
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
index 8d4210b..5914de9 100644
--- a/cmds/idmap/idmap.h
+++ b/cmds/idmap/idmap.h
@@ -25,12 +25,6 @@
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_
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
deleted file mode 100644
index ab6adfb..0000000
--- a/cmds/idmap/scan.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-#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;
-}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 56f1e0c..f801e45 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2065,9 +2065,6 @@
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) {
@@ -2075,12 +2072,6 @@
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)) {
@@ -5518,7 +5509,6 @@
public String mRequiredAccountType;
public String mOverlayTarget;
- public int mOverlayPriority;
public boolean mTrustedOverlay;
/**
@@ -5995,7 +5985,6 @@
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);
@@ -6111,7 +6100,6 @@
dest.writeString(mRestrictedAccountType);
dest.writeString(mRequiredAccountType);
dest.writeString(mOverlayTarget);
- dest.writeInt(mOverlayPriority);
dest.writeInt(mTrustedOverlay ? 1 : 0);
dest.writeArraySet(mSigningKeys);
dest.writeArraySet(mUpgradeKeySets);
@@ -6560,6 +6548,7 @@
ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
}
ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
+ ai.resourceDirs = state.resourceDirs;
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 24f1164..ee56a18 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -31,6 +31,8 @@
import com.android.internal.util.ArrayUtils;
+import java.util.Arrays;
+
/**
* Per-user state information about a package.
* @hide
@@ -54,6 +56,8 @@
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
+ public String[] resourceDirs;
+
public PackageUserState() {
installed = true;
hidden = false;
@@ -81,6 +85,8 @@
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);
}
/**
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 37e32ff..4cf55ba 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -222,19 +222,21 @@
*/
final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
boolean resolveRefs) {
- final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
- if (block < 0) {
- return false;
- }
+ synchronized (this) {
+ final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
+ if (block < 0) {
+ return false;
+ }
- // Convert the changing configurations flags populated by native code.
- outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
- outValue.changingConfigurations);
+ // Convert the changing configurations flags populated by native code.
+ outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+ outValue.changingConfigurations);
- if (outValue.type == TypedValue.TYPE_STRING) {
- outValue.string = mStringBlocks[block].get(outValue.data);
+ if (outValue.type == TypedValue.TYPE_STRING) {
+ outValue.string = mStringBlocks[block].get(outValue.data);
+ }
+ return true;
}
- return true;
}
/**
@@ -244,18 +246,20 @@
* @param resId the resource id of the string array
*/
final CharSequence[] getResourceTextArray(@ArrayRes int resId) {
- final int[] rawInfoArray = getArrayStringInfo(resId);
- final int rawInfoArrayLen = rawInfoArray.length;
- final int infoArrayLen = rawInfoArrayLen / 2;
- int block;
- int index;
- final CharSequence[] retArray = new CharSequence[infoArrayLen];
- for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
- block = rawInfoArray[i];
- index = rawInfoArray[i + 1];
- retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
+ synchronized (this) {
+ final int[] rawInfoArray = getArrayStringInfo(resId);
+ final int rawInfoArrayLen = rawInfoArray.length;
+ final int infoArrayLen = rawInfoArrayLen / 2;
+ int block;
+ int index;
+ final CharSequence[] retArray = new CharSequence[infoArrayLen];
+ for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
+ block = rawInfoArray[i];
+ index = rawInfoArray[i + 1];
+ retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
+ }
+ return retArray;
}
- return retArray;
}
/**
@@ -320,8 +324,10 @@
}
/*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
- // Cookies map to string blocks starting at 1.
- return mStringBlocks[cookie - 1].get(id);
+ synchronized (this) {
+ // Cookies map to string blocks starting at 1.
+ return mStringBlocks[cookie - 1].get(id);
+ }
}
/**
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 356804e..80ec03e 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -189,7 +189,9 @@
// TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
String[] availableLanguages = {
"as",
+ "bg",
"bn",
+ "cu",
"cy",
"da",
"de-1901", "de-1996", "de-CH-1901",
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 3d012bf..67f9f8f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -59,6 +59,7 @@
private static final int ALLOW_LIBS = 0x02;
private static final int ALLOW_PERMISSIONS = 0x04;
private static final int ALLOW_APP_CONFIGS = 0x08;
+ private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
private static final int ALLOW_ALL = ~0;
// Group-ids that are given to all packages as read from etc/permissions/*.xml.
@@ -225,6 +226,13 @@
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
+ // Allow Vendor to customize system configs around libs, features, permissions and apps
+ int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+ ALLOW_APP_CONFIGS;
+ readPermissions(Environment.buildPath(
+ Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
+ readPermissions(Environment.buildPath(
+ Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
@@ -313,6 +321,7 @@
boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
+ boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0;
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
@@ -553,7 +562,7 @@
associatedPkgs.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
- } else if ("privapp-permissions".equals(name) && allowAppConfigs) {
+ } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
readPrivAppPermissions(parser);
} else {
XmlUtils.skipCurrentTag(parser);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 723dce6..314595f 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -119,96 +119,6 @@
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
@@ -1597,9 +1507,6 @@
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", "");
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index acacd76..84111ae 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -202,15 +202,6 @@
*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);
}
@@ -493,11 +484,6 @@
}
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;
@@ -539,14 +525,6 @@
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);
}
@@ -655,58 +633,6 @@
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);
@@ -1446,20 +1372,6 @@
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) {
@@ -1578,22 +1490,6 @@
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.
*
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index becd307..f1e8b93 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -202,12 +202,10 @@
private:
struct asset_path
{
- asset_path() : path(""), type(kFileTypeRegular), idmap(""),
- isSystemOverlay(false), isSystemAsset(false) {}
+ asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemAsset(false) {}
String8 path;
FileType type;
String8 idmap;
- bool isSystemOverlay;
bool isSystemAsset;
};
@@ -237,9 +235,6 @@
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);
@@ -254,9 +249,6 @@
bool isUpToDate();
- void addOverlay(const asset_path& ap);
- bool getOverlay(size_t idx, asset_path* out) const;
-
protected:
~SharedZip();
@@ -271,8 +263,6 @@
Asset* mResourceTableAsset;
ResTable* mResourceTable;
- Vector<asset_path> mOverlays;
-
static Mutex gLock;
static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
};
@@ -306,9 +296,6 @@
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);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 34164b16..5b4dd48 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -118,6 +118,8 @@
<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"
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/res/values/arrays_tv.xml
new file mode 100644
index 0000000..08b1ab1
--- /dev/null
+++ b/packages/SystemUI/res/values/arrays_tv.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2017, 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.
+ */
+-->
+<resources>
+ <!-- List of package name or class name which are considered as Settings,
+ so PIP location should be adjusted to the left of the side panel.
+ This can be overriden in an overlay -->
+ <string-array name="tv_pip_settings_class_name" translatable="false">
+ <item>com.android.tv.settings</item>
+ <item>com.google.android.leanbacklauncher/.settings.HomeScreenSettingsActivity</item>
+ <item>com.google.android.apps.mediashell/.settings.CastSettingsActivity</item>
+ <item>com.google.android.katniss.setting/.SpeechSettingsActivity</item>
+ <item>com.google.android.katniss.setting/.SearchSettingsActivity</item>
+ <item>com.google.android.gsf.notouch/.UsageDiagnosticsSettingActivity</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 376a0b6..df01aab 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -68,34 +68,10 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean DEBUG_FORCE_ONBOARDING =
SystemProperties.getBoolean("debug.tv.pip_force_onboarding", false);
+ private static final String SETTINGS_PACKAGE_AND_CLASS_DELIMITER = "/";
private static PipManager sPipManager;
-
- /**
- * List of package and class name which are considered as Settings,
- * so PIP location should be adjusted to the left of the side panel.
- */
- private static final List<Pair<String, String>> sSettingsPackageAndClassNamePairList;
- static {
- sSettingsPackageAndClassNamePairList = new ArrayList<>();
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.android.tv.settings", null));
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.google.android.leanbacklauncher",
- "com.google.android.leanbacklauncher.settings.HomeScreenSettingsActivity"));
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.google.android.apps.mediashell",
- "com.google.android.apps.mediashell.settings.CastSettingsActivity"));
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.google.android.katniss",
- "com.google.android.katniss.setting.SpeechSettingsActivity"));
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.google.android.katniss",
- "com.google.android.katniss.setting.SearchSettingsActivity"));
- sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
- "com.google.android.gsf.notouch",
- "com.google.android.gsf.notouch.UsageDiagnosticsSettingActivity"));
- }
+ private static List<Pair<String, String>> sSettingsPackageAndClassNamePairList;
/**
* State when there's no PIP.
@@ -252,6 +228,31 @@
mOnboardingShown = Prefs.getBoolean(
mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
+ if (sSettingsPackageAndClassNamePairList == null) {
+ String[] settings = mContext.getResources().getStringArray(
+ R.array.tv_pip_settings_class_name);
+ sSettingsPackageAndClassNamePairList = new ArrayList<>();
+ if (settings != null) {
+ for (int i = 0; i < settings.length; i++) {
+ Pair<String, String> entry = null;
+ String[] packageAndClassName =
+ settings[i].split(SETTINGS_PACKAGE_AND_CLASS_DELIMITER);
+ switch (packageAndClassName.length) {
+ case 1:
+ entry = Pair.<String, String>create(packageAndClassName[0], null);
+ break;
+ case 2:
+ entry = Pair.<String, String>create(
+ packageAndClassName[0],
+ packageAndClassName[0] + packageAndClassName[1]);
+ }
+ if (entry != null) {
+ sSettingsPackageAndClassNamePairList.add(entry);
+ }
+ }
+ }
+ }
+
loadConfigurationsAndApply();
mPipRecentsOverlayManager = new PipRecentsOverlayManager(context);
mMediaSessionManager =
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 3f97d4f..cb13a3d 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.annotation.NonNull;
import android.content.Context;
import android.os.Trace;
import android.util.Slog;
@@ -105,22 +106,25 @@
+ ": service constructor threw an exception", ex);
}
- // 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);
- }
+ startService(service);
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.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 30b267f..7524351 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23165,10 +23165,11 @@
}
void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
+ final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mLruProcesses.get(i);
- if (app.thread == null) {
+ if (app.thread == null || app.pid == Process.myPid()) {
continue;
}
@@ -23181,7 +23182,7 @@
final String packageName = app.pkgList.keyAt(j);
if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
try {
- final ApplicationInfo ai = mPackageManagerInt.getApplicationInfo(
+ final ApplicationInfo ai = packageManager.getApplicationInfo(
packageName, app.userId);
if (ai != null) {
app.thread.scheduleApplicationInfoChanged(ai);
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index cc709ce..ba4d46a 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -26,7 +26,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -42,7 +41,6 @@
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
@@ -646,7 +644,7 @@
Slog.d(TAG, String.format("send broadcast %s", intent));
}
try {
- ActivityManagerNative.getDefault().broadcastIntent(null, intent, null, null, 0,
+ ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
userId);
} catch (RemoteException e) {
@@ -664,7 +662,38 @@
}
private void updateAssets(final int userId, List<String> targetPackageNames) {
- // TODO: implement when we integrate OMS properly
+ 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 = ActivityManager.getService();
+ try {
+ am.scheduleApplicationInfoChanged(targetPackageNames, userId);
+ } catch (RemoteException e) {
+ // Intentionally left empty.
+ }
}
private void schedulePersistSettings() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 33bd350..fbf953f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -661,9 +661,12 @@
final ArrayMap<String, Set<String>> mKnownCodebase =
new ArrayMap<String, Set<String>>();
- // Tracks available target package names -> overlay package paths.
- final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
- new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
+ // 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 new system packages [received in an OTA] that we expect to
@@ -3734,6 +3737,7 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
ps.readUserState(userId), userId);
if (ai != null) {
+ rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
}
return ai;
@@ -3768,6 +3772,7 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(
p, flags, ps.readUserState(userId), userId);
if (ai != null) {
+ rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(p);
}
return ai;
@@ -3784,6 +3789,26 @@
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;
@@ -7214,6 +7239,7 @@
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
ps.readUserState(userId), userId);
if (ai != null) {
+ rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
}
} else {
@@ -7237,6 +7263,7 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
+ rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(p);
list.add(ai);
}
@@ -7380,6 +7407,7 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
+ rebaseEnabledOverlays(ai, userId);
finalList.add(ai);
}
}
@@ -7515,60 +7543,6 @@
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 {
@@ -10057,7 +10031,6 @@
// writer
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
- boolean createIdmapFailed = false;
synchronized (mPackages) {
// We don't expect installation to fail beyond this point
@@ -10398,36 +10371,9 @@
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,
@@ -20226,6 +20172,7 @@
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;
@@ -20345,6 +20292,7 @@
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)) {
@@ -20473,6 +20421,8 @@
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();
@@ -20843,6 +20793,11 @@
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);
@@ -20939,6 +20894,23 @@
}
}
+ 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();
@@ -23040,10 +23012,43 @@
}
@Override
- public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
- List<String> overlayPackageNames) {
- // TODO: implement when we integrate OMS properly
- return false;
+ 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 ResolveInfo resolveIntent(Intent intent, String resolvedType,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a5f1945..e586482 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -82,6 +82,7 @@
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;
@@ -592,6 +593,11 @@
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
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 384f49f..28596f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -197,7 +197,6 @@
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);
@@ -433,7 +432,6 @@
pkg.installLocation = 100;
pkg.coreApp = true;
pkg.mRequiredForAllUsers = true;
- pkg.mOverlayPriority = 100;
pkg.mTrustedOverlay = true;
pkg.use32bitAbi = true;
pkg.packageName = "foo";
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index f193ea4..eb8a1cc 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -14,7 +14,9 @@
LANG_TO_SCRIPT = {
'as': 'Beng',
+ 'bg': 'Cyrl',
'bn': 'Beng',
+ 'cu': 'Cyrl',
'cy': 'Latn',
'da': 'Latn',
'de': 'Latn',