oms-patches -> vendor/extra
authorLuK1337 <priv.luk@gmail.com>
Tue, 14 Feb 2017 11:57:47 +0000 (12:57 +0100)
committerLuK1337 <priv.luk@gmail.com>
Tue, 14 Feb 2017 13:15:43 +0000 (14:15 +0100)
Change-Id: Id57eaf3c592bb0d6b888bb38834c04f46a01b596

126 files changed:
Android.mk [new file with mode: 0644]
build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch [deleted file]
extra.xml [new file with mode: 0644]
frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch [deleted file]
frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch [deleted file]
frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch [deleted file]
frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch [deleted file]
frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch [deleted file]
frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch [deleted file]
frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch [deleted file]
frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch [deleted file]
frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch [deleted file]
frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch [deleted file]
frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch [deleted file]
frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch [deleted file]
frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch [deleted file]
frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch [deleted file]
frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch [deleted file]
frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch [deleted file]
frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch [deleted file]
frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch [deleted file]
frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch [deleted file]
frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch [deleted file]
frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch [deleted file]
frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch [deleted file]
frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch [deleted file]
frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch [deleted file]
frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch [deleted file]
frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch [deleted file]
frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch [deleted file]
frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch [deleted file]
frameworks/base/0029-Themes-Expose-QS-battery.patch [deleted file]
frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch [deleted file]
frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch [deleted file]
frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch [deleted file]
frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch [deleted file]
frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch [deleted file]
frameworks/base/0035-Expose-external-qs-tile-tint-color.patch [deleted file]
frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch [deleted file]
frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch [deleted file]
frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch [deleted file]
frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch [deleted file]
packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch [deleted file]
packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch [deleted file]
packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch [deleted file]
packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch [deleted file]
packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch [deleted file]
packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch [deleted file]
packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch [deleted file]
packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch [deleted file]
packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch [deleted file]
packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch [deleted file]
packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch [deleted file]
packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch [deleted file]
packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch [deleted file]
packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch [deleted file]
packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch [deleted file]
packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch [deleted file]
packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch [deleted file]
packages/apps/Settings/0013-Expose-switchbar-background-color.patch [deleted file]
packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch [deleted file]
packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch [deleted file]
patch.sh
patches/build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch [new file with mode: 0644]
patches/frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch [new file with mode: 0644]
patches/frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch [new file with mode: 0644]
patches/frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch [new file with mode: 0644]
patches/frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch [new file with mode: 0644]
patches/frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch [new file with mode: 0644]
patches/frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch [new file with mode: 0644]
patches/frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch [new file with mode: 0644]
patches/frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch [new file with mode: 0644]
patches/frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch [new file with mode: 0644]
patches/frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch [new file with mode: 0644]
patches/frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch [new file with mode: 0644]
patches/frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch [new file with mode: 0644]
patches/frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch [new file with mode: 0644]
patches/frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch [new file with mode: 0644]
patches/frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch [new file with mode: 0644]
patches/frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch [new file with mode: 0644]
patches/frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch [new file with mode: 0644]
patches/frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch [new file with mode: 0644]
patches/frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch [new file with mode: 0644]
patches/frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch [new file with mode: 0644]
patches/frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch [new file with mode: 0644]
patches/frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch [new file with mode: 0644]
patches/frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch [new file with mode: 0644]
patches/frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch [new file with mode: 0644]
patches/frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch [new file with mode: 0644]
patches/frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch [new file with mode: 0644]
patches/frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch [new file with mode: 0644]
patches/frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch [new file with mode: 0644]
patches/frameworks/base/0029-Themes-Expose-QS-battery.patch [new file with mode: 0644]
patches/frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch [new file with mode: 0644]
patches/frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch [new file with mode: 0644]
patches/frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch [new file with mode: 0644]
patches/frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch [new file with mode: 0644]
patches/frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch [new file with mode: 0644]
patches/frameworks/base/0035-Expose-external-qs-tile-tint-color.patch [new file with mode: 0644]
patches/frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch [new file with mode: 0644]
patches/frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch [new file with mode: 0644]
patches/frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch [new file with mode: 0644]
patches/frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch [new file with mode: 0644]
patches/packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch [new file with mode: 0644]
patches/packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch [new file with mode: 0644]
patches/packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch [new file with mode: 0644]
patches/packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch [new file with mode: 0644]
patches/packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch [new file with mode: 0644]
patches/packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch [new file with mode: 0644]
patches/packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch [new file with mode: 0644]
patches/packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch [new file with mode: 0644]
patches/packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch [new file with mode: 0644]
patches/packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch [new file with mode: 0644]
patches/packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch [new file with mode: 0644]
patches/packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch [new file with mode: 0644]
patches/packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch [new file with mode: 0644]
patches/packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch [new file with mode: 0644]
patches/packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch [new file with mode: 0644]
patches/packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch [new file with mode: 0644]
patches/packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch [new file with mode: 0644]
patches/packages/apps/Settings/0013-Expose-switchbar-background-color.patch [new file with mode: 0644]
patches/packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch [new file with mode: 0644]
patches/packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch [new file with mode: 0644]
patches/system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch [new file with mode: 0644]
product.mk [new file with mode: 0644]
system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch [deleted file]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..5053e7d
--- /dev/null
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch b/build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch
deleted file mode 100644 (file)
index 80b0242..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 9c60c359e98e9c862411c08e72bb7a1520b736d1 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Mon, 27 Jul 2015 12:24:40 +0200
-Subject: [PATCH] OMS-N: adb shell command to access OverlayManagerService
-
-Add a command to communicate with the OverlayManagerService for
-debugging purposes. This mirrors the am and pm commands.
-
-This commit restores the functionality after the Nougat rebase from
-Sony.
-
-Example use:
-    $ adb shell om list
-    com.android.systemui
-        [ ] com.test.awesome-home-button
-
-    $ adb shell om enable com.test.awesome-home-button
-
-    $ adb shell om list
-    com.android.systemui
-        [x] com.test.awesome-home-button
-
-Co-authored-by: Martin Wallgren <martin.wallgren@sonymobile.com>
-Signed-off-by: Zoran Jovanovic <zoran.jovanovic@sonymobile.com>
-Change-Id: If424b8ef6052e4121902b630279c0ebaf416203c
----
- target/product/base.mk | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/target/product/base.mk b/target/product/base.mk
-index dcd48e7..a12f939 100644
---- a/target/product/base.mk
-+++ b/target/product/base.mk
-@@ -108,6 +108,7 @@ PRODUCT_PACKAGES += \
-     mtpd \
-     ndc \
-     netd \
-+    om \
-     ping \
-     ping6 \
-     platform.xml \
--- 
-2.9.3
-
diff --git a/extra.xml b/extra.xml
new file mode 100644 (file)
index 0000000..edf9f07
--- /dev/null
+++ b/extra.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest>
+  <project name="luk1337/android_vendor_extra" path="vendor/extra" remote="github" />
+  <project name="TeamSubstratum/masquerade" path="packages/apps/masquerade" remote="github" revision="n" />
+</manifest>
diff --git a/frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch b/frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch
deleted file mode 100644 (file)
index 342173e..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-From 75d5463e848764c3255c32d126415faceca62023 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Tue, 15 Dec 2015 16:08:31 +0100
-Subject: [PATCH 01/38] OMS7-N: Support tagging resources as OK to overlay
- [1/11]
-
-This will allow applications to have a resource xml defining what
-resources that are safe to overlay by third party overlay packages.
-The format of the tag is <overlay type="..." name="..."/> and it will
-result in the FLAG_OVELAY being set on the resource entry.
-
-An overlay package with resources that are not tagged as OK
-to overlay by the target application, is considered to be a dangerous
-overlay.
-
-Idmaps generated for dangerous overlays will be flagged as dangerous in
-the idmap header. It is still possible to use both idmap and overlays that
-are dangerous, but it might not be advisable.
-
-The intention is to allow dangerous overlays to be used if
-they are pre-installed or if the signature of the overlay package
-matches the signature of the target package.
-
-Change-Id: I08d11de845c1679017798ea1636ef4c36f820d8e
----
- cmds/idmap/create.cpp             |  2 +-
- cmds/idmap/inspect.cpp            |  6 +++
- include/androidfw/ResourceTypes.h | 10 ++--
- libs/androidfw/AssetManager.cpp   |  2 +-
- libs/androidfw/ResourceTypes.cpp  | 27 ++++++++---
- tools/aapt/ResourceTable.cpp      | 96 ++++++++++++++++++++++++++++++++++++++-
- tools/aapt/ResourceTable.h        | 36 ++++++++++++++-
- 7 files changed, 164 insertions(+), 15 deletions(-)
-
-diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
-index c13d318..8656b0e 100644
---- a/cmds/idmap/create.cpp
-+++ b/cmds/idmap/create.cpp
-@@ -106,7 +106,7 @@ fail:
-         uint32_t cached_target_crc, cached_overlay_crc;
-         String8 cached_target_path, cached_overlay_path;
--        if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc,
-+        if (!ResTable::getIdmapInfo(buf, N, NULL, NULL, &cached_target_crc, &cached_overlay_crc,
-                     &cached_target_path, &cached_overlay_path)) {
-             return true;
-         }
-diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
-index f6afc85..924090f 100644
---- a/cmds/idmap/inspect.cpp
-+++ b/cmds/idmap/inspect.cpp
-@@ -192,6 +192,12 @@ namespace {
-         if (err != NO_ERROR) {
-             return err;
-         }
-+        print("", "dangerous", i, "");
-+
-+        err = buf.nextUint32(&i);
-+        if (err != NO_ERROR) {
-+            return err;
-+        }
-         print("", "base crc", i, "");
-         err = buf.nextUint32(&i);
-diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
-index 12a6b0f..6094a57 100644
---- a/include/androidfw/ResourceTypes.h
-+++ b/include/androidfw/ResourceTypes.h
-@@ -1382,7 +1382,11 @@ struct ResTable_entry
-         // If set, this is a weak resource and may be overriden by strong
-         // resources of the same name/type. This is only useful during
-         // linking with other resource tables.
--        FLAG_WEAK = 0x0004
-+        FLAG_WEAK = 0x0004,
-+        // If set, this resource has been declared OK to overlay, so overlay
-+        // packages may be added to the resource table to provide alternative
-+        // resource values.
-+        FLAG_OVERLAY = 0x0008,
-     };
-     uint16_t flags;
-     
-@@ -1861,14 +1865,14 @@ public:
-             const char* targetPath, const char* overlayPath,
-             void** outData, size_t* outSize) const;
--    static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256;
-+    static const size_t IDMAP_HEADER_SIZE_BYTES = 5 * sizeof(uint32_t) + 2 * 256;
-     // Retrieve idmap meta-data.
-     //
-     // This function only requires the idmap header (the first
-     // IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
-     static bool getIdmapInfo(const void* idmap, size_t size,
--            uint32_t* pVersion,
-+            uint32_t* pVersion, uint32_t* pDangerous,
-             uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
-             String8* pTargetPath, String8* pOverlayPath);
-diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
-index fdd0caf..edc625b 100644
---- a/libs/androidfw/AssetManager.cpp
-+++ b/libs/androidfw/AssetManager.cpp
-@@ -252,7 +252,7 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
-     String8 targetPath;
-     String8 overlayPath;
-     if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
--                NULL, NULL, NULL, &targetPath, &overlayPath)) {
-+                NULL, NULL, NULL, NULL, &targetPath, &overlayPath)) {
-         ALOGW("failed to read idmap file %s\n", idmapPath.string());
-         delete idmap;
-         return false;
-diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
-index e8c6fcf..022f19e 100644
---- a/libs/androidfw/ResourceTypes.cpp
-+++ b/libs/androidfw/ResourceTypes.cpp
-@@ -59,7 +59,7 @@ namespace android {
- #endif
- #define IDMAP_MAGIC             0x504D4449
--#define IDMAP_CURRENT_VERSION   0x00000001
-+#define IDMAP_CURRENT_VERSION   0x00000002
- #define APP_PACKAGE_ID      0x7f
- #define CMSDK_PACKAGE_ID    0x3f
-@@ -6601,6 +6601,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
-         return UNKNOWN_ERROR;
-     }
-+    bool isDangerous = false;
-     KeyedVector<uint8_t, IdmapTypeMap> map;
-     // overlaid packages are assumed to contain only one package group
-@@ -6675,6 +6676,13 @@ status_t ResTable::createIdmap(const ResTable& overlay,
-                 }
-             }
-             typeMap.entryMap.add(Res_GETENTRY(overlayResID));
-+
-+            Entry entry;
-+            if (getEntry(pg, typeIndex, entryIndex, NULL, &entry)) {
-+                return UNKNOWN_ERROR;
-+            }
-+            isDangerous = isDangerous ||
-+                ((dtohs(entry.entry->flags) & ResTable_entry::FLAG_OVERLAY) == 0);
-         }
-         if (!typeMap.entryMap.isEmpty()) {
-@@ -6697,6 +6705,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
-     uint32_t* data = (uint32_t*)*outData;
-     *data++ = htodl(IDMAP_MAGIC);
-     *data++ = htodl(IDMAP_CURRENT_VERSION);
-+    *data++ = htodl(isDangerous ? 1 : 0);
-     *data++ = htodl(targetCrc);
-     *data++ = htodl(overlayCrc);
-     const char* paths[] = { targetPath, overlayPath };
-@@ -6737,7 +6746,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
- }
- bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
--                            uint32_t* pVersion,
-+                            uint32_t* pVersion, uint32_t* pDangerous,
-                             uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
-                             String8* pTargetPath, String8* pOverlayPath)
- {
-@@ -6748,17 +6757,20 @@ bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
-     if (pVersion) {
-         *pVersion = dtohl(map[1]);
-     }
-+    if (pDangerous) {
-+        *pDangerous = dtohl(map[2]);
-+    }
-     if (pTargetCrc) {
--        *pTargetCrc = dtohl(map[2]);
-+        *pTargetCrc = dtohl(map[3]);
-     }
-     if (pOverlayCrc) {
--        *pOverlayCrc = dtohl(map[3]);
-+        *pOverlayCrc = dtohl(map[4]);
-     }
-     if (pTargetPath) {
--        pTargetPath->setTo(reinterpret_cast<const char*>(map + 4));
-+        pTargetPath->setTo(reinterpret_cast<const char*>(map + 5));
-     }
-     if (pOverlayPath) {
--        pOverlayPath->setTo(reinterpret_cast<const char*>(map + 4 + 256 / sizeof(uint32_t)));
-+        pOverlayPath->setTo(reinterpret_cast<const char*>(map + 5 + 256 / sizeof(uint32_t)));
-     }
-     return true;
- }
-@@ -7085,6 +7097,9 @@ void ResTable::print(bool inclValues) const
-                     if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) {
-                         printf(" (PUBLIC)");
-                     }
-+                    if ((dtohs(ent->flags)&ResTable_entry::FLAG_OVERLAY) != 0) {
-+                        printf(" (OVERLAY)");
-+                    }
-                     printf("\n");
-                     if (inclValues) {
-diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
-index a1b1879..b2d0480 100644
---- a/tools/aapt/ResourceTable.cpp
-+++ b/tools/aapt/ResourceTable.cpp
-@@ -800,6 +800,7 @@ status_t compileResourceFile(Bundle* bundle,
-     const String16 string_array16("string-array");
-     const String16 integer_array16("integer-array");
-     const String16 public16("public");
-+    const String16 overlay16("overlay");
-     const String16 public_padding16("public-padding");
-     const String16 private_symbols16("private-symbols");
-     const String16 java_symbol16("java-symbol");
-@@ -1003,6 +1004,41 @@ status_t compileResourceFile(Bundle* bundle,
-                 }
-                 continue;
-+            } else if (strcmp16(block.getElementName(&len), overlay16.string()) == 0) {
-+                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
-+
-+                String16 type;
-+                const ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
-+                if (typeIdx < 0) {
-+                    srcPos.error("A 'type' attribute is required for <overlay>\n");
-+                    hasErrors = localHasErrors = true;
-+                }
-+                type = String16(block.getAttributeStringValue(typeIdx, &len));
-+
-+                String16 name;
-+                const ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
-+                if (nameIdx < 0) {
-+                    srcPos.error("A 'name' attribute is required for <overlay>\n");
-+                    hasErrors = localHasErrors = true;
-+                }
-+                name = String16(block.getAttributeStringValue(nameIdx, &len));
-+
-+                if (!localHasErrors) {
-+                    err = outTable->addOverlay(srcPos, myPackage, type, name);
-+                    if (err < NO_ERROR) {
-+                        hasErrors = localHasErrors = true;
-+                    }
-+                }
-+
-+                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
-+                    if (code == ResXMLTree::END_TAG) {
-+                        if (strcmp16(block.getElementName(&len), overlay16.string()) == 0) {
-+                            break;
-+                        }
-+                    }
-+                }
-+                continue;
-+
-             } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
-                 SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
-             
-@@ -1865,6 +1901,29 @@ status_t ResourceTable::addPublic(const SourcePos& sourcePos,
-     return t->addPublic(sourcePos, name, ident);
- }
-+status_t ResourceTable::addOverlay(const SourcePos& sourcePos,
-+                                  const String16& package,
-+                                  const String16& type,
-+                                  const String16& name)
-+{
-+    uint32_t rid = mAssets->getIncludedResources()
-+        .identifierForName(name.string(), name.size(),
-+                           type.string(), type.size(),
-+                           package.string(), package.size());
-+    if (rid != 0) {
-+        sourcePos.error("Error declaring overlay resource %s/%s for included package %s\n",
-+                String8(type).string(), String8(name).string(),
-+                String8(package).string());
-+        return UNKNOWN_ERROR;
-+    }
-+
-+    sp<Type> t = getType(package, type, sourcePos);
-+    if (t == NULL) {
-+        return UNKNOWN_ERROR;
-+    }
-+    return t->addOverlay(sourcePos, name);
-+}
-+
- status_t ResourceTable::addEntry(const SourcePos& sourcePos,
-                                  const String16& package,
-                                  const String16& type,
-@@ -2665,6 +2724,11 @@ status_t ResourceTable::assignResourceIds()
-                 firstError = err;
-             }
-+            err = t->applyOverlay();
-+            if (err != NO_ERROR && firstError == NO_ERROR) {
-+                firstError = err;
-+            }
-+
-             const size_t N = t->getOrderedConfigs().size();
-             t->setIndex(ti + 1 + typeIdOffset);
-@@ -3254,7 +3318,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
-                         index[ei] = htodl(data->getSize()-typeStart-typeSize);
-                         // Create the entry.
--                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
-+                        ssize_t amt = e->flatten(bundle, data, cl->getPublic(), cl->getOverlay());
-                         if (amt < 0) {
-                             return amt;
-                         }
-@@ -3759,7 +3823,8 @@ status_t ResourceTable::Entry::remapStringValue(StringPool* strings)
-     return NO_ERROR;
- }
--ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>& data, bool isPublic)
-+ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>& data, bool isPublic,
-+        bool isOverlay)
- {
-     size_t amt = 0;
-     ResTable_entry header;
-@@ -3772,6 +3837,9 @@ ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>&
-     if (isPublic) {
-         header.flags |= htods(header.FLAG_PUBLIC);
-     }
-+    if (isOverlay) {
-+        header.flags |= htods(header.FLAG_OVERLAY);
-+    }
-     header.key.index = htodl(mNameIndex);
-     if (ty != TYPE_BAG) {
-         status_t err = data->writeData(&header, sizeof(header));
-@@ -3912,6 +3980,13 @@ status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
-     return NO_ERROR;
- }
-+status_t ResourceTable::Type::addOverlay(const SourcePos& sourcePos,
-+                                         const String16& name)
-+{
-+    mOverlay.add(name, Overlay(sourcePos, String16()));
-+    return NO_ERROR;
-+}
-+
- void ResourceTable::Type::canAddEntry(const String16& name)
- {
-     mCanAddEntries.add(name);
-@@ -4014,6 +4089,7 @@ sp<ResourceTable::ConfigList> ResourceTable::Type::removeEntry(const String16& e
-     }
-     mPublic.removeItem(entry);
-+    mOverlay.removeItem(entry);
-     return removed;
- }
-@@ -4115,6 +4191,22 @@ status_t ResourceTable::Type::applyPublicEntryOrder()
-     return hasError ? STATUST(UNKNOWN_ERROR) : NO_ERROR;
- }
-+status_t ResourceTable::Type::applyOverlay() {
-+    const size_t N = mOverlay.size();
-+    const size_t M = mOrderedConfigs.size();
-+    for (size_t i = 0; i < N; i++) {
-+        const String16& name = mOverlay.keyAt(i);
-+        for (size_t j = 0; j < M; j++) {
-+            sp<ConfigList> e = mOrderedConfigs.itemAt(j);
-+            if (e->getName() == name) {
-+                e->setOverlay(true);
-+                break;
-+            }
-+        }
-+    }
-+    return NO_ERROR;
-+}
-+
- ResourceTable::Package::Package(const String16& name, size_t packageId)
-     : mName(name), mPackageId(packageId),
-       mTypeStringsMapping(0xffffffff),
-diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
-index 54d56cf..7e9b044 100644
---- a/tools/aapt/ResourceTable.h
-+++ b/tools/aapt/ResourceTable.h
-@@ -139,6 +139,11 @@ public:
-                        const String16& name,
-                        const uint32_t ident);
-+    status_t addOverlay(const SourcePos& pos,
-+                       const String16& package,
-+                       const String16& type,
-+                       const String16& name);
-+
-     status_t addEntry(const SourcePos& pos,
-                       const String16& package,
-                       const String16& type,
-@@ -388,7 +393,7 @@ public:
-         status_t remapStringValue(StringPool* strings);
--        ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic);
-+        ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic, bool isOverlay);
-         const SourcePos& getPos() const { return mPos; }
-@@ -407,7 +412,7 @@ public:
-     class ConfigList : public RefBase {
-     public:
-         ConfigList(const String16& name, const SourcePos& pos)
--            : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { }
-+            : mName(name), mPos(pos), mPublic(false), mOverlay(false), mEntryIndex(-1) { }
-         virtual ~ConfigList() { }
-         
-         String16 getName() const { return mName; }
-@@ -427,6 +432,9 @@ public:
-         bool getPublic() const { return mPublic; }
-         void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; }
-         const SourcePos& getPublicSourcePos() { return mPublicSourcePos; }
-+
-+        void setOverlay(bool o) { mOverlay = o; }
-+        bool getOverlay() const { return mOverlay; }
-         
-         void addEntry(const ResTable_config& config, const sp<Entry>& entry) {
-             mEntries.add(config, entry);
-@@ -440,6 +448,7 @@ public:
-         String16 mTypeComment;
-         bool mPublic;
-         SourcePos mPublicSourcePos;
-+        bool mOverlay;
-         int32_t mEntryIndex;
-         DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries;
-     };
-@@ -467,6 +476,24 @@ public:
-         String16    comment;
-         uint32_t    ident;
-     };
-+
-+    class Overlay {
-+    public:
-+        Overlay() : sourcePos() { }
-+        Overlay(const SourcePos& pos, const String16& _comment)
-+            : sourcePos(pos), comment(_comment) { }
-+        Overlay(const Overlay& o) : sourcePos(o.sourcePos), comment(o.comment) { }
-+        ~Overlay() { }
-+
-+        Overlay& operator=(const Overlay& o) {
-+            sourcePos = o.sourcePos;
-+            comment = o.comment;
-+            return *this;
-+        }
-+
-+        SourcePos   sourcePos;
-+        String16    comment;
-+    };
-     
-     class Type : public RefBase {
-     public:
-@@ -478,6 +505,9 @@ public:
-         status_t addPublic(const SourcePos& pos,
-                            const String16& name,
-                            const uint32_t ident);
-+
-+        status_t addOverlay(const SourcePos& pos,
-+                            const String16& name);
-                            
-         void canAddEntry(const String16& name);
-         
-@@ -505,6 +535,7 @@ public:
-         void setIndex(int32_t index) { mIndex = index; }
-         status_t applyPublicEntryOrder();
-+        status_t applyOverlay();
-         const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
-         const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
-@@ -516,6 +547,7 @@ public:
-         String16 mName;
-         SourcePos* mFirstPublicSourcePos;
-         DefaultKeyedVector<String16, Public> mPublic;
-+        DefaultKeyedVector<String16, Overlay> mOverlay;
-         DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
-         Vector<sp<ConfigList> > mOrderedConfigs;
-         SortedVector<String16> mCanAddEntries;
--- 
-2.9.3
-
diff --git a/frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch b/frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch
deleted file mode 100644 (file)
index 919e42c..0000000
+++ /dev/null
@@ -1,3082 +0,0 @@
-From 90815d5667efdc258011508a5599a45bd3d66756 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Tue, 15 Dec 2015 16:40:23 +0100
-Subject: [PATCH 02/38] OMS7-N: Introduce the OverlayManagerService [2/11]
-
-Add a new system service to manage Runtime Resource Overlays. This will
-offload the PackageManagerService and allow administration of overlay
-packages while affected packages continue to execute.
-
-Overlays can be enabled or disabled during runtime. To the running
-application the change is invisible. Technically, the overlay is added
-or removed from the running application similarly to how multi-window
-affects resources.
-
-Before an overlay can be enabled it has to be approved. This happens
-during package installation or upgrade and if an error occurs, the
-overlay is marked as not approved.
-
-The system performs the following security checks, in
-the order listed, to determine if an overlay can be approved:
-
-  1. Is the overlay package pre-installed? If yes, OK to use.
-
-  2. Are the target and overlay packages signed with the same
-     certificate? If yes, OK to use.
-
-  3. Is the overlay dangerous? If no, OK to use.
-
-An overlay is said to be dangerous if it modifies resources not
-explicitly specified by the target as OK to overlay. (This is done by
-adding <overlay type="..." name="..."/> tags to the target's resources.)
-
-The decision to approve/not approve an overlay is not re-evaluated until
-the next time either the overlay or its target package is changed.
-
-The order in which a set of overlays is loaded may also be changed
-during runtime. The underlying mechanics are the same as for when an
-overlay is enabled or disabled.
-
-When an overlay changes state, e.g. becomes enabled, the
-OverlayManagerService will broadcast one of the new intents
-android.intent.action.OVERLAY_ADDED, *_CHANGED, *_REMOVED or
-*.OVERLAYS_REORDERED.
-
-Clients that wish to read information about overlays for users other
-than themselves are required to hold the
-android.permission.INTERACT_ACROSS_USERS_FULL permission. This mirrors
-the protection level of PackageManager.getPackageInfo.
-
-Clients that wish to change the information are required to
-hold the permission android.permission.CHANGE_CONFIGURATION.
-
-Each pair of overlay package and corresponding target package is
-respresented by a new OverlayInfo class. This class mirrors the
-existing PackageInfo class.
-
-Overlay packages are handled per Android user. The data is persisted in
-/data/system/overlays.xml.
-
-Change-Id: Icc3c7daa25345d20bc5014b865024422eab72f5b
----
- Android.mk                                         |   1 +
- core/java/android/content/Context.java             |  10 +
- core/java/android/content/Intent.java              |  34 +
- core/java/android/content/om/IOverlayManager.aidl  | 129 +++
- core/java/android/content/om/OverlayInfo.aidl      |  19 +
- core/java/android/content/om/OverlayInfo.java      | 290 +++++++
- .../android/content/pm/PackageManagerInternal.java |  24 +
- core/res/AndroidManifest.xml                       |   4 +
- .../java/com/android/server/om/IdmapManager.java   | 116 +++
- .../android/server/om/OverlayManagerService.java   | 901 +++++++++++++++++++++
- .../server/om/OverlayManagerServiceImpl.java       | 478 +++++++++++
- .../android/server/om/OverlayManagerSettings.java  | 656 +++++++++++++++
- .../server/om/OverlayManagerShellCommand.java      | 179 ++++
- .../android/server/pm/PackageManagerService.java   |  41 +
- 14 files changed, 2882 insertions(+)
- create mode 100644 core/java/android/content/om/IOverlayManager.aidl
- create mode 100644 core/java/android/content/om/OverlayInfo.aidl
- create mode 100644 core/java/android/content/om/OverlayInfo.java
- create mode 100644 services/core/java/com/android/server/om/IdmapManager.java
- create mode 100644 services/core/java/com/android/server/om/OverlayManagerService.java
- create mode 100644 services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
- create mode 100644 services/core/java/com/android/server/om/OverlayManagerSettings.java
- create mode 100644 services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-
-diff --git a/Android.mk b/Android.mk
-index bdb4555..df42780 100644
---- a/Android.mk
-+++ b/Android.mk
-@@ -137,6 +137,7 @@ LOCAL_SRC_FILES += \
-       core/java/android/content/ISyncContext.aidl \
-       core/java/android/content/ISyncServiceAdapter.aidl \
-       core/java/android/content/ISyncStatusObserver.aidl \
-+      core/java/android/content/om/IOverlayManager.aidl \
-       core/java/android/content/pm/ILauncherApps.aidl \
-       core/java/android/content/pm/IOnAppsChangedListener.aidl \
-       core/java/android/content/pm/IOtaDexopt.aidl \
-diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
-index 3a2f471..1ca44e0 100644
---- a/core/java/android/content/Context.java
-+++ b/core/java/android/content/Context.java
-@@ -3656,6 +3656,16 @@ public abstract class Context {
-     public static final String GATEKEEPER_SERVICE = "android.service.gatekeeper.IGateKeeperService";
-     /**
-+     * Use with {@link #getSystemService} to retrieve a {@link
-+     * android.content.om.OverlayManager} for managing overlay packages.
-+     *
-+     * @see #getSystemService
-+     * @see android.content.om.OverlayManager
-+     * @hide
-+     */
-+    public static final String OVERLAY_SERVICE = "overlay";
-+
-+    /**
-      * Determine whether the given permission is allowed for a particular
-      * process and user ID running in the system.
-      *
-diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
-index 861aae5..1afae79 100644
---- a/core/java/android/content/Intent.java
-+++ b/core/java/android/content/Intent.java
-@@ -3092,6 +3092,40 @@ public class Intent implements Parcelable, Cloneable {
-             "android.intent.action.MEDIA_RESOURCE_GRANTED";
-     /**
-+     * Broadcast Action: An overlay package has been installed. The data
-+     * contains the name of the added overlay package.
-+     * @hide
-+     */
-+    public static final String ACTION_OVERLAY_ADDED = "android.intent.action.OVERLAY_ADDED";
-+
-+    /**
-+     * Broadcast Action: An overlay package has changed. The data contains the
-+     * name of the overlay package which has changed. This is broadcast on all
-+     * changes to the OverlayInfo returned by {@link
-+     * android.content.om.IOverlayManager#getOverlayInfo(String, int)}. The
-+     * most common change is a state change that will change whether the
-+     * overlay is enabled or not.
-+     * @hide
-+     */
-+    public static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
-+
-+    /**
-+     * Broadcast Action: An overlay package has been removed. The data contains
-+     * the name of the overlay package which has been removed.
-+     * @hide
-+     */
-+    public static final String ACTION_OVERLAY_REMOVED = "android.intent.action.OVERLAY_REMOVED";
-+
-+    /**
-+     * Broadcast Action: The order of a package's list of overlay packages has
-+     * changed. The data contains the package name of the overlay package that
-+     * had its position in the list adjusted.
-+     * @hide
-+     */
-+    public static final String
-+            ACTION_OVERLAY_PRIORITY_CHANGED = "android.intent.action.OVERLAY_PRIORITY_CHANGED";
-+
-+    /**
-      * Activity Action: Allow the user to select and return one or more existing
-      * documents. When invoked, the system will display the various
-      * {@link DocumentsProvider} instances installed on the device, letting the
-diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
-new file mode 100644
-index 0000000..4f5d960
---- /dev/null
-+++ b/core/java/android/content/om/IOverlayManager.aidl
-@@ -0,0 +1,129 @@
-+/*
-+ * Copyright (C) 2015 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package android.content.om;
-+
-+import android.content.om.OverlayInfo;
-+
-+/**
-+ * Api for getting information about overlay packages.
-+ *
-+ * {@hide}
-+ */
-+interface IOverlayManager {
-+    /**
-+     * Returns information about all installed overlay packages for the
-+     * specified user. If there are no installed overlay packages for this user,
-+     * an empty map is returned (i.e. null is never returned). The returned map is a
-+     * mapping of target package names to lists of overlays. Each list for a
-+     * given target package is sorted in priority order, with the overlay with
-+     * the highest priority at the end of the list.
-+     *
-+     * @param userId The user to get the OverlayInfos for.
-+     * @return A Map<String, List<OverlayInfo>> with target package names
-+     *         mapped to lists of overlays; if no overlays exist for the
-+     *         requested user, an empty map is returned.
-+     */
-+    Map getAllOverlays(in int userId);
-+
-+    /**
-+     * Returns information about all overlays for the given target package for
-+     * the specified user. The returned list is ordered according to the
-+     * overlay priority with the highest priority at the end of the list.
-+     *
-+     * @param targetPackageName The name of the target package.
-+     * @param userId The user to get the OverlayInfos for.
-+     * @return A list of OverlayInfo objects; if no overlays exist for the
-+     *         requested package, an empty list is returned.
-+     */
-+    List getOverlayInfosForTarget(in String targetPackageName, in int userId);
-+
-+    /**
-+     * Returns information about the overlay with the given package name for the
-+     * specified user.
-+     *
-+     * @param packageName The name of the overlay package.
-+     * @param userId The user to get the OverlayInfo for.
-+     * @return The OverlayInfo for the overlay package; or null if no such
-+     *         overlay package exists.
-+     */
-+    OverlayInfo getOverlayInfo(in String packageName, in int userId);
-+
-+    /**
-+     * Request that an overlay package be enabled or disabled when possible to
-+     * do so.
-+     *
-+     * It is always possible to disable an overlay, but due to technical and
-+     * security reasons it may not always be possible to enable an overlay. An
-+     * example of the latter is when the related target package is not
-+     * installed. If the technical obstacle is later overcome, the overlay is
-+     * automatically enabled at that point in time.
-+     *
-+     * An enabled overlay is a part of target package's resources, i.e. it will
-+     * be part of any lookups performed via {@link android.content.res.Resources}
-+     * and {@link android.content.res.AssetManager}. A disabled overlay will no
-+     * longer affect the resources of the target package. If the target is
-+     * currently running, its outdated resources will be replaced by new ones.
-+     * This happens the same way as when an application enters or exits split
-+     * window mode.
-+     *
-+     * @param packageName The name of the overlay package.
-+     * @param enable true to enable the overlay, false to disable it.
-+     * @param userId The user for which to change the overlay.
-+     * @return true if the system successfully registered the request, false
-+     *         otherwise.
-+     */
-+    boolean setEnabled(in String packageName, in boolean enable, in int userId);
-+
-+    /**
-+     * Change the priority of the given overlay to be just higher than the
-+     * overlay with package name newParentPackageName. Both overlay packages
-+     * must have the same target and user.
-+     *
-+     * @see getOverlayInfosForTarget
-+     *
-+     * @param packageName The name of the overlay package whose priority should
-+     *        be adjusted.
-+     * @param newParentPackageName The name of the overlay package the newly
-+     *        adjusted overlay package should just outrank.
-+     * @param userId The user for which to change the overlay.
-+     */
-+    boolean setPriority(in String packageName, in String newParentPackageName, in int userId);
-+
-+    /**
-+     * Change the priority of the given overlay to the highest priority relative to
-+     * the other overlays with the same target and user.
-+     *
-+     * @see getOverlayInfosForTarget
-+     *
-+     * @param packageName The name of the overlay package whose priority should
-+     *        be adjusted.
-+     * @param userId The user for which to change the overlay.
-+     */
-+    boolean setHighestPriority(in String packageName, in int userId);
-+
-+    /**
-+     * Change the priority of the overlay to the lowest priority relative to
-+     * the other overlays for the same target and user.
-+     *
-+     * @see getOverlayInfosForTarget
-+     *
-+     * @param packageName The name of the overlay package whose priority should
-+     *        be adjusted.
-+     * @param userId The user for which to change the overlay.
-+     */
-+    boolean setLowestPriority(in String packageName, in int userId);
-+}
-diff --git a/core/java/android/content/om/OverlayInfo.aidl b/core/java/android/content/om/OverlayInfo.aidl
-new file mode 100644
-index 0000000..e7d413d
---- /dev/null
-+++ b/core/java/android/content/om/OverlayInfo.aidl
-@@ -0,0 +1,19 @@
-+/*
-+ * Copyright (C) 2015 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package android.content.om;
-+
-+parcelable OverlayInfo;
-diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
-new file mode 100644
-index 0000000..a25cf0c
---- /dev/null
-+++ b/core/java/android/content/om/OverlayInfo.java
-@@ -0,0 +1,290 @@
-+/*
-+ * Copyright (C) 2015 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package android.content.om;
-+
-+import android.annotation.NonNull;
-+import android.os.Parcel;
-+import android.os.Parcelable;
-+
-+/**
-+ * Immutable overlay information about a package. All PackageInfos that
-+ * represent an overlay package will have a corresponding OverlayInfo.
-+ *
-+ * @hide
-+ */
-+public final class OverlayInfo implements Parcelable {
-+    /**
-+     * An internal state used as the initial state of an overlay. OverlayInfo
-+     * objects exposed outside the {@link
-+     * com.android.server.om.OverlayManagerService} should never have this
-+     * state.
-+     */
-+    public static final int STATE_NOT_APPROVED_UNKNOWN = -1;
-+
-+    /**
-+     * The overlay package is disabled by the PackageManager.
-+     */
-+    public static final int STATE_NOT_APPROVED_COMPONENT_DISABLED = 0;
-+
-+    /**
-+     * The target package of the overlay is not installed.
-+     */
-+    public static final int STATE_NOT_APPROVED_MISSING_TARGET = 1;
-+
-+    /**
-+     * Creation of idmap file failed (e.g. no matching resources).
-+     */
-+    public static final int STATE_NOT_APPROVED_NO_IDMAP = 2;
-+
-+    /**
-+     * The overlay package is dangerous, i.e. it touches resources not explicitly
-+     * OK'd by the target package.
-+     */
-+    public static final int STATE_NOT_APPROVED_DANGEROUS_OVERLAY = 3;
-+
-+    /**
-+     * The OverlayInfo is currently disabled but it is allowed to be enabled
-+     * ({@link #STATE_APPROVED_ENABLED}) in the future.
-+     */
-+    public static final int STATE_APPROVED_DISABLED = 4;
-+
-+    /**
-+     * The OverlayInfo is enabled but can be disabled
-+     * ({@link #STATE_APPROVED_DISABLED}) in the future.
-+     */
-+    public static final int STATE_APPROVED_ENABLED = 5;
-+
-+    /**
-+     * Package name of the overlay package
-+     */
-+    public final String packageName;
-+
-+    /**
-+     * Package name of the target package
-+     */
-+    public final String targetPackageName;
-+
-+    /**
-+     * Full path to the base APK for this overlay package
-+     */
-+    public final String baseCodePath;
-+
-+    /**
-+     * The state of this OverlayInfo as defined by the STATE_* constants in this class.
-+     * <p/>
-+     * The state of an OverlayInfo determines if it is approved and/or enabled. An OverlayInfo with
-+     * one of the STATE_NOT_APPROVED_* states cannot be enabled, and can thus never be part of the
-+     * best match in the resource lookup.
-+     * <p/>
-+     * The only way to get an overlay package to be active and be part of the best matching in the
-+     * resource lookup is if the corresponding OverlayInfo is in an STATE_*_ENABLED state.
-+     *
-+     * @see #STATE_NOT_APPROVED_COMPONENT_DISABLED
-+     * @see #STATE_NOT_APPROVED_MISSING_TARGET
-+     * @see #STATE_NOT_APPROVED_NO_IDMAP
-+     * @see #STATE_NOT_APPROVED_DANGEROUS_OVERLAY
-+     * @see #STATE_APPROVED_DISABLED
-+     * @see #STATE_APPROVED_ENABLED
-+     */
-+    public final int state;
-+
-+    /**
-+     * User handle for which this overlay applies
-+     */
-+    public final int userId;
-+
-+    /**
-+     * Create a new OverlayInfo based on source with an updated state.
-+     *
-+     * @param source the source OverlayInfo to base the new instance on
-+     * @param state the new state for the source OverlayInfo
-+     */
-+    public OverlayInfo(@NonNull OverlayInfo source, int state) {
-+        this(source.packageName, source.targetPackageName, source.baseCodePath, state,
-+                source.userId);
-+    }
-+
-+    public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
-+            @NonNull String baseCodePath, int state, int userId) {
-+        this.packageName = packageName;
-+        this.targetPackageName = targetPackageName;
-+        this.baseCodePath = baseCodePath;
-+        this.state = state;
-+        this.userId = userId;
-+        ensureValidState();
-+    }
-+
-+    public OverlayInfo(Parcel source) {
-+        packageName = source.readString();
-+        targetPackageName = source.readString();
-+        baseCodePath = source.readString();
-+        state = source.readInt();
-+        userId = source.readInt();
-+        ensureValidState();
-+    }
-+
-+    private void ensureValidState() {
-+        if (packageName == null) {
-+            throw new IllegalArgumentException("packageName must not be null");
-+        }
-+        if (targetPackageName == null) {
-+            throw new IllegalArgumentException("targetPackageName must not be null");
-+        }
-+        if (baseCodePath == null) {
-+            throw new IllegalArgumentException("baseCodePath must not be null");
-+        }
-+        switch (state) {
-+            case STATE_NOT_APPROVED_UNKNOWN:
-+            case STATE_NOT_APPROVED_COMPONENT_DISABLED:
-+            case STATE_NOT_APPROVED_MISSING_TARGET:
-+            case STATE_NOT_APPROVED_NO_IDMAP:
-+            case STATE_NOT_APPROVED_DANGEROUS_OVERLAY:
-+            case STATE_APPROVED_DISABLED:
-+            case STATE_APPROVED_ENABLED:
-+                break;
-+            default:
-+                throw new IllegalArgumentException("State " + state + " is not a valid state");
-+        }
-+    }
-+
-+    @Override
-+    public int describeContents() {
-+        return 0;
-+    }
-+
-+    @Override
-+    public void writeToParcel(Parcel dest, int flags) {
-+        dest.writeString(packageName);
-+        dest.writeString(targetPackageName);
-+        dest.writeString(baseCodePath);
-+        dest.writeInt(state);
-+        dest.writeInt(userId);
-+    }
-+
-+    public static final Parcelable.Creator<OverlayInfo> CREATOR = new Parcelable.Creator<OverlayInfo>() {
-+        @Override
-+        public OverlayInfo createFromParcel(Parcel source) {
-+            return new OverlayInfo(source);
-+        }
-+
-+        @Override
-+        public OverlayInfo[] newArray(int size) {
-+            return new OverlayInfo[size];
-+        }
-+    };
-+
-+    /**
-+     * Returns true if this overlay is enabled, i.e. should be used to overlay
-+     * the resources in the target package.
-+     *
-+     * Disabled overlay packages are installed but are currently not in use.
-+     *
-+     * @return true if the overlay is enabled, else false.
-+     */
-+    public boolean isEnabled() {
-+        switch (state) {
-+            case STATE_APPROVED_ENABLED:
-+                return true;
-+            default:
-+                return false;
-+        }
-+    }
-+
-+    /**
-+     * Returns true if this overlay is approved.
-+     *
-+     * @return true if this overlay is approved, else false.
-+     */
-+    public boolean isApproved() {
-+        switch (state) {
-+            case STATE_APPROVED_ENABLED:
-+            case STATE_APPROVED_DISABLED:
-+                return true;
-+            default:
-+                return false;
-+        }
-+    }
-+
-+    public static String stateToString(int state) {
-+        switch (state) {
-+            case STATE_NOT_APPROVED_UNKNOWN:
-+                return "STATE_NOT_APPROVED_UNKNOWN";
-+            case STATE_NOT_APPROVED_COMPONENT_DISABLED:
-+                return "STATE_NOT_APPROVED_COMPONENT_DISABLED";
-+            case STATE_NOT_APPROVED_MISSING_TARGET:
-+                return "STATE_NOT_APPROVED_MISSING_TARGET";
-+            case STATE_NOT_APPROVED_NO_IDMAP:
-+                return "STATE_NOT_APPROVED_NO_IDMAP";
-+            case STATE_NOT_APPROVED_DANGEROUS_OVERLAY:
-+                return "STATE_NOT_APPROVED_DANGEROUS_OVERLAY";
-+            case STATE_APPROVED_DISABLED:
-+                return "STATE_APPROVED_DISABLED";
-+            case STATE_APPROVED_ENABLED:
-+                return "STATE_APPROVED_ENABLED";
-+            default:
-+                return "<unknown state>";
-+        }
-+    }
-+
-+    @Override
-+    public int hashCode() {
-+        final int prime = 31;
-+        int result = 1;
-+        result = prime * result + userId;
-+        result = prime * result + state;
-+        result = prime * result + ((packageName == null) ? 0 : packageName.hashCode());
-+        result = prime * result + ((targetPackageName == null) ? 0 : targetPackageName.hashCode());
-+        result = prime * result + ((baseCodePath == null) ? 0 : baseCodePath.hashCode());
-+        return result;
-+    }
-+
-+    @Override
-+    public boolean equals(Object obj) {
-+        if (this == obj) {
-+            return true;
-+        }
-+        if (obj == null) {
-+            return false;
-+        }
-+        if (getClass() != obj.getClass()) {
-+            return false;
-+        }
-+        OverlayInfo other = (OverlayInfo) obj;
-+        if (userId != other.userId) {
-+            return false;
-+        }
-+        if (state != other.state) {
-+            return false;
-+        }
-+        if (!packageName.equals(other.packageName)) {
-+            return false;
-+        }
-+        if (!targetPackageName.equals(other.targetPackageName)) {
-+            return false;
-+        }
-+        if (!baseCodePath.equals(other.baseCodePath)) {
-+            return false;
-+        }
-+        return true;
-+    }
-+
-+    @Override
-+    public String toString() {
-+        return "OverlayInfo { overlay=" + packageName + ", target=" + targetPackageName + ", state="
-+                + state + " (" + stateToString(state) + "), userId=" + userId + " }";
-+    }
-+}
-diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
-index f5bcf64..bdbdd1e 100644
---- a/core/java/android/content/pm/PackageManagerInternal.java
-+++ b/core/java/android/content/pm/PackageManagerInternal.java
-@@ -168,4 +168,28 @@ public abstract class PackageManagerInternal {
-      * @return Whether was launched.
-      */
-     public abstract boolean wasPackageEverLaunched(String packageName, int userId);
-+
-+    /**
-+     * Get all overlay packages for a user.
-+     * @param userId The user for which to get the overlays.
-+     * @return A list of overlay packages. An empty list is returned if the
-+     *         user has no installed overlay packages.
-+     */
-+    public abstract List<PackageInfo> getOverlayPackages(int userId);
-+
-+    /**
-+     * Get the names of all target packages for a user.
-+     * @param userId The user for which to get the package names.
-+     * @return A list of target package names. This list includes the "android" package.
-+     */
-+    public abstract List<String> getTargetPackageNames(int userId);
-+
-+    /**
-+     * Set which overlay to use for a package.
-+     * @param userId The user for which to update the overlays.
-+     * @param packageName The package name of the package for which to update the overlays.
-+     * @param resourceDirs The paths to the overlay packages to use, ordered in the order in
-+     *                     which to load the paths, or null if no overlays should be used.
-+     */
-+    public abstract void setResourceDirs(int userId, String packageName, String[] resourceDirs);
- }
-diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
-index c2f12ef..986be28 100644
---- a/core/res/AndroidManifest.xml
-+++ b/core/res/AndroidManifest.xml
-@@ -84,6 +84,10 @@
-     <protected-broadcast android:name="android.intent.action.USER_INITIALIZE" />
-     <protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
-     <protected-broadcast android:name="android.intent.action.SU_SESSION_CHANGED" />
-+    <protected-broadcast android:name="android.intent.action.OVERLAY_ADDED" />
-+    <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
-+    <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
-+    <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
-     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
-     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
-diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
-new file mode 100644
-index 0000000..e2a3775
---- /dev/null
-+++ b/services/core/java/com/android/server/om/IdmapManager.java
-@@ -0,0 +1,116 @@
-+/*
-+ * Copyright (C) 2016 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package com.android.server.om;
-+
-+import static com.android.server.om.OverlayManagerService.DEBUG;
-+import static com.android.server.om.OverlayManagerService.TAG;
-+
-+import android.annotation.NonNull;
-+import android.content.om.OverlayInfo;
-+import android.content.pm.PackageInfo;
-+import android.os.UserHandle;
-+import android.util.Slog;
-+import com.android.internal.os.InstallerConnection.InstallerException;
-+import com.android.server.pm.Installer;
-+
-+import java.io.DataInputStream;
-+import java.io.File;
-+import java.io.FileInputStream;
-+import java.io.IOException;
-+
-+/**
-+ * Handle the creation and deletion of idmap files.
-+ *
-+ * The actual work is performed by the idmap binary, launched through Installer
-+ * and installd.
-+ *
-+ * Note: this class is subclassed in the OMS unit tests, and hence not marked as final.
-+ */
-+class IdmapManager {
-+    private final Installer mInstaller;
-+
-+    IdmapManager(final Installer installer) {
-+        mInstaller = installer;
-+    }
-+
-+    boolean createIdmap(@NonNull final PackageInfo targetPackage,
-+            @NonNull final PackageInfo overlayPackage, int userId) {
-+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-+        if (DEBUG) {
-+            Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " +
-+                    overlayPackage.packageName);
-+        }
-+        final int sharedGid = UserHandle.getSharedAppGid(targetPackage.applicationInfo.uid);
-+        final String targetPath = targetPackage.applicationInfo.getBaseCodePath();
-+        final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
-+        try {
-+            mInstaller.idmap(targetPath, overlayPath, sharedGid);
-+        } catch (InstallerException e) {
-+            Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " +
-+                    overlayPath + ": " + e.getMessage());
-+            return false;
-+        }
-+        return true;
-+    }
-+
-+    boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
-+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-+        if (DEBUG) {
-+            Slog.d(TAG, "remove idmap for " + oi.baseCodePath);
-+        }
-+        try {
-+            mInstaller.removeIdmap(oi.baseCodePath);
-+        } catch (InstallerException e) {
-+            Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage());
-+            return false;
-+        }
-+        return true;
-+    }
-+
-+    boolean idmapExists(@NonNull final OverlayInfo oi) {
-+        // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-+        return new File(getIdmapPath(oi.baseCodePath)).isFile();
-+    }
-+
-+    boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
-+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-+        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
-+    }
-+
-+    boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) {
-+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-+        return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath()));
-+    }
-+
-+    private String getIdmapPath(@NonNull final String baseCodePath) {
-+        final StringBuilder sb = new StringBuilder("/data/resource-cache/");
-+        sb.append(baseCodePath.substring(1).replace('/', '@'));
-+        sb.append("@idmap");
-+        return sb.toString();
-+    }
-+
-+    private boolean isDangerous(@NonNull final String idmapPath) {
-+        try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) {
-+            final int magic = dis.readInt();
-+            final int version = dis.readInt();
-+            final int dangerous = dis.readInt();
-+            return dangerous != 0;
-+        } catch (IOException e) {
-+            return true;
-+        }
-+    }
-+}
-diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
-new file mode 100644
-index 0000000..ec148dd
---- /dev/null
-+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
-@@ -0,0 +1,901 @@
-+/*
-+ * Copyright (C) 2016 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package com.android.server.om;
-+
-+import static android.app.AppGlobals.getPackageManager;
-+import static android.content.Intent.ACTION_PACKAGE_ADDED;
-+import static android.content.Intent.ACTION_PACKAGE_CHANGED;
-+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
-+import static android.content.Intent.ACTION_USER_REMOVED;
-+import static android.content.pm.PackageManager.SIGNATURE_MATCH;
-+
-+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;
-+import android.content.Intent;
-+import android.content.IntentFilter;
-+import android.content.om.IOverlayManager;
-+import android.content.om.OverlayInfo;
-+import android.content.pm.IPackageManager;
-+import android.content.pm.PackageInfo;
-+import android.content.pm.PackageManagerInternal;
-+import android.content.pm.UserInfo;
-+import android.net.Uri;
-+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.UserHandle;
-+import android.util.ArrayMap;
-+import android.util.AtomicFile;
-+import android.util.Slog;
-+import android.util.SparseArray;
-+
-+import com.android.server.FgThread;
-+import com.android.server.IoThread;
-+import com.android.server.LocalServices;
-+import com.android.server.SystemService;
-+import com.android.server.pm.Installer;
-+import com.android.server.pm.UserManagerService;
-+
-+import org.xmlpull.v1.XmlPullParserException;
-+
-+import java.io.File;
-+import java.io.FileDescriptor;
-+import java.io.FileInputStream;
-+import java.io.FileOutputStream;
-+import java.io.IOException;
-+import java.io.PrintWriter;
-+import java.util.ArrayList;
-+import java.util.Collection;
-+import java.util.Collections;
-+import java.util.HashMap;
-+import java.util.Iterator;
-+import java.util.List;
-+import java.util.Map;
-+import java.util.concurrent.atomic.AtomicBoolean;
-+
-+/**
-+ * Service to manage asset overlays.
-+ *
-+ * <p>Asset overlays are additional resources that come from apks loaded
-+ * alongside the system and app apks. This service, the OverlayManagerService
-+ * (OMS), tracks which installed overlays to use and provides methods to change
-+ * this. Changes propagate to running applications as part of the Activity
-+ * lifecycle. This allows Activities to reread their resources at a well
-+ * defined point.</p>
-+ *
-+ * <p>By itself, the OMS will not change what overlays should be active.
-+ * Instead, it is only responsible for making sure that overlays *can* be used
-+ * from a technical and security point of view and to activate overlays in
-+ * response to external requests. The responsibility to toggle overlays on and
-+ * off lies within components that implement different use-cases such as themes
-+ * or dynamic customization.</p>
-+ *
-+ * <p>The OMS receives input from three sources:</p>
-+ *
-+ * <ul>
-+ *     <li>Callbacks from the SystemService class, specifically when the
-+ *     Android framework is booting and when the end user switches Android
-+ *     users.</li>
-+ *
-+ *     <li>Intents from the PackageManagerService (PMS). Overlays are regular
-+ *     apks, and whenever a package is installed (or removed, or has a
-+ *     component enabled or disabled), the PMS broadcasts this as an intent.
-+ *     When the OMS receives one of these intents, it updates its internal
-+ *     representation of the available overlays and, if there was a visible
-+ *     change, triggers an asset refresh in the affected apps.</li>
-+ *
-+ *     <li>External requests via the {@link IOverlayManager AIDL interface}.
-+ *     The interface allows clients to read information about the currently
-+ *     available overlays, change whether an overlay should be used or not, and
-+ *     change the relative order in which overlay packages are loaded.
-+ *     Read-access is granted if the request targets the same Android user as
-+ *     the caller runs as, or if the caller holds the
-+ *     INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
-+ *     caller is granted read-access and additionaly holds the
-+ *     CHANGE_CONFIGURATION permission.</li>
-+ * </ul>
-+ *
-+ * <p>The AIDL interface works with String package names, int user IDs, and
-+ * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
-+ * specific pair of target and overlay packages and include information such as
-+ * the current state of the overlay. OverlayInfo objects are immutable.</p>
-+ *
-+ * <p>Internally, OverlayInfo objects are maintained by the
-+ * OverlayManagerSettings class. The OMS and its helper classes are notified of
-+ * changes to the settings by the OverlayManagerSettings.ChangeListener
-+ * callback interface. The file /data/system/overlays.xml is used to persist
-+ * the settings.</p>
-+ *
-+ * <p>Creation and deletion of idmap files are handled by the IdmapManager
-+ * class.</p>
-+ *
-+ * <p>The following is an overview of OMS and its related classes. Note how box
-+ * (2) does the heavy lifting, box (1) interacts with the Android framework,
-+ * and box (3) replaces box (1) during unit testing.</p>
-+ *
-+ * <pre>
-+ *         Android framework
-+ *            |         ^
-+ *      . . . | . . . . | . . . .
-+ *     .      |         |       .
-+ *     .    AIDL,   broadcasts  .
-+ *     .   intents      |       .
-+ *     .      |         |       . . . . . . . . . . . .
-+ *     .      v         |       .                     .
-+ *     .  OverlayManagerService . OverlayManagerTests .
-+ *     .                  \     .     /               .
-+ *     . (1)               \    .    /            (3) .
-+ *      . . . . . . . . . . \ . . . / . . . . . . . . .
-+ *     .                     \     /              .
-+ *     . (2)                  \   /               .
-+ *     .           OverlayManagerServiceImpl      .
-+ *     .                  |            |          .
-+ *     .                  |            |          .
-+ *     . OverlayManagerSettings     IdmapManager  .
-+ *     .                                          .
-+ *     . . . .  . . . . . . . . . . . . . . . . . .
-+ * </pre>
-+ *
-+ * <p>Finally, here is a list of keywords used in the OMS context.</p>
-+ *
-+ * <ul>
-+ *     <li><b>target [package]</b> -- A regular apk that may have its resource
-+ *     pool extended  by zero or more overlay packages.</li>
-+ *
-+ *     <li><b>overlay [package]</b> -- An apk that provides additional
-+ *     resources to another apk.</li>
-+ *
-+ *     <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
-+ *
-+ *     <li><b>approved</b> -- An overlay is approved if the OMS has verified
-+ *     that it can be used technically speaking (its target package is
-+ *     installed, at least one resource name in both packages match, the
-+ *     idmap was created, etc) and that it is secure to do so. External
-+ *     clients can not change this state.</li>
-+ *
-+ *     <li><b>not approved</b> -- The opposite of approved.</li>
-+ *
-+ *     <li><b>enabled</b> -- An overlay currently in active use and thus part
-+ *     of resource lookups. This requires the overlay to be approved. Only
-+ *     external clients can change this state.</li>
-+ *
-+ *     <li><b>disabled</b> -- The opposite of enabled.</li>
-+ *
-+ *     <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
-+ *     used during resource lookup. Also the name of the binary that creates
-+ *     the mapping.</li>
-+ * </ul>
-+ */
-+public final class OverlayManagerService extends SystemService {
-+
-+    static final String TAG = "OverlayManager";
-+
-+    static final boolean DEBUG = false;
-+
-+    private final Object mLock = new Object();
-+
-+    private final AtomicFile mSettingsFile;
-+
-+    private final PackageManagerHelper mPackageManager;
-+
-+    private final UserManagerService mUserManager;
-+
-+    private final OverlayManagerSettings mSettings;
-+
-+    private final OverlayManagerServiceImpl mImpl;
-+
-+    private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
-+
-+    public OverlayManagerService(@NonNull final Context context,
-+            @NonNull final Installer installer) {
-+        super(context);
-+        mSettingsFile =
-+            new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"));
-+        mPackageManager = new PackageManagerHelper();
-+        mUserManager = UserManagerService.getInstance();
-+        IdmapManager im = new IdmapManager(installer);
-+        mSettings = new OverlayManagerSettings();
-+        mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings);
-+
-+        final IntentFilter packageFilter = new IntentFilter();
-+        packageFilter.addAction(ACTION_PACKAGE_ADDED);
-+        packageFilter.addAction(ACTION_PACKAGE_CHANGED);
-+        packageFilter.addAction(ACTION_PACKAGE_REMOVED);
-+        packageFilter.addDataScheme("package");
-+        getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
-+                packageFilter, null, null);
-+
-+        final IntentFilter userFilter = new IntentFilter();
-+        userFilter.addAction(ACTION_USER_REMOVED);
-+        getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
-+                userFilter, null, null);
-+
-+        restoreSettings();
-+        onSwitchUser(UserHandle.USER_SYSTEM);
-+        schedulePersistSettings();
-+
-+        mSettings.addChangeListener(new OverlayChangeListener());
-+
-+        publishBinderService(Context.OVERLAY_SERVICE, mService);
-+        publishLocalService(OverlayManagerService.class, this);
-+    }
-+
-+    @Override
-+    public void onStart() {
-+        // Intentionally left empty.
-+    }
-+
-+    @Override
-+    public void onSwitchUser(final int newUserId) {
-+        // ensure overlays in the settings are up-to-date, and propagate
-+        // any asset changes to the rest of the system
-+        final List<String> targets;
-+        synchronized (mLock) {
-+            targets = mImpl.onSwitchUser(newUserId);
-+        }
-+        updateAssets(newUserId, targets);
-+    }
-+
-+    public List<String> getEnabledOverlayPaths(@NonNull final String packageName,
-+            final int userId) {
-+        synchronized (mLock) {
-+            return mImpl.onGetEnabledOverlayPaths(packageName, userId);
-+        }
-+    }
-+
-+    private final class PackageReceiver extends BroadcastReceiver {
-+        @Override
-+        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
-+            final Uri data = intent.getData();
-+            if (data == null) {
-+                Slog.e(TAG, "Cannot handle package broadcast with null data");
-+                return;
-+            }
-+            final String packageName = data.getSchemeSpecificPart();
-+
-+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-+
-+            final int[] userIds;
-+            final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
-+            if (extraUid == UserHandle.USER_NULL) {
-+                userIds = mUserManager.getUserIds();
-+            } else {
-+                userIds = new int[] { UserHandle.getUserId(extraUid) };
-+            }
-+
-+            switch (intent.getAction()) {
-+                case ACTION_PACKAGE_ADDED:
-+                    if (replacing) {
-+                        onPackageUpgraded(packageName, userIds);
-+                    } else {
-+                        onPackageAdded(packageName, userIds);
-+                    }
-+                    break;
-+                case ACTION_PACKAGE_CHANGED:
-+                    onPackageChanged(packageName, userIds);
-+                    break;
-+                case ACTION_PACKAGE_REMOVED:
-+                    if (replacing) {
-+                        onPackageUpgrading(packageName, userIds);
-+                    } else {
-+                        onPackageRemoved(packageName, userIds);
-+                    }
-+                    break;
-+                default:
-+                    // do nothing
-+                    break;
-+            }
-+        }
-+
-+        private void onPackageAdded(@NonNull final String packageName,
-+                @NonNull final int[] userIds) {
-+            for (final int userId : userIds) {
-+                synchronized (mLock) {
-+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
-+                    if (pi != null) {
-+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
-+                        if (!isOverlayPackage(pi)) {
-+                            mImpl.onTargetPackageAdded(packageName, userId);
-+                        } else {
-+                            mImpl.onOverlayPackageAdded(packageName, userId);
-+                        }
-+                    }
-+                }
-+            }
-+        }
-+
-+        private void onPackageChanged(@NonNull final String packageName,
-+                @NonNull final int[] userIds) {
-+            for (int userId : userIds) {
-+                synchronized (mLock) {
-+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
-+                    if (pi != null) {
-+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
-+                        if (!isOverlayPackage(pi)) {
-+                            mImpl.onTargetPackageChanged(packageName, userId);
-+                        } else {
-+                            mImpl.onOverlayPackageChanged(packageName, userId);
-+                        }
-+                    }
-+                }
-+            }
-+        }
-+
-+        private void onPackageUpgrading(@NonNull final String packageName,
-+                @NonNull final int[] userIds) {
-+            for (int userId : userIds) {
-+                synchronized (mLock) {
-+                    mPackageManager.forgetPackageInfo(packageName, userId);
-+                    final OverlayInfo oi = mImpl.onGetOverlayInfo(packageName, userId);
-+                    if (oi == null) {
-+                        mImpl.onTargetPackageUpgrading(packageName, userId);
-+                    } else {
-+                        mImpl.onOverlayPackageUpgrading(packageName, userId);
-+                    }
-+                }
-+            }
-+        }
-+
-+        private void onPackageUpgraded(@NonNull final String packageName,
-+                @NonNull final int[] userIds) {
-+            for (int userId : userIds) {
-+                synchronized (mLock) {
-+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
-+                    if (pi != null) {
-+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
-+                        if (!isOverlayPackage(pi)) {
-+                            mImpl.onTargetPackageUpgraded(packageName, userId);
-+                        } else {
-+                            mImpl.onOverlayPackageUpgraded(packageName, userId);
-+                        }
-+                    }
-+                }
-+            }
-+        }
-+
-+        private void onPackageRemoved(@NonNull final String packageName,
-+                @NonNull final int[] userIds) {
-+            for (int userId : userIds) {
-+                synchronized (mLock) {
-+                    mPackageManager.forgetPackageInfo(packageName, userId);
-+                    final OverlayInfo oi = mImpl.onGetOverlayInfo(packageName, userId);
-+                    if (oi == null) {
-+                        mImpl.onTargetPackageRemoved(packageName, userId);
-+                    } else {
-+                        mImpl.onOverlayPackageRemoved(packageName, userId);
-+                    }
-+                }
-+            }
-+        }
-+    }
-+
-+    private final class UserReceiver extends BroadcastReceiver {
-+        @Override
-+        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
-+            switch (intent.getAction()) {
-+                case ACTION_USER_REMOVED:
-+                    final int userId =
-+                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-+                    if (userId != UserHandle.USER_NULL) {
-+                        synchronized (mLock) {
-+                            mImpl.onUserRemoved(userId);
-+                            mPackageManager.forgetAllPackageInfos(userId);
-+                        }
-+                    }
-+                    break;
-+                default:
-+                    // do nothing
-+                    break;
-+            }
-+        }
-+    }
-+
-+    private final IBinder mService = new IOverlayManager.Stub() {
-+        @Override
-+        public Map<String, List<OverlayInfo>> getAllOverlays(int userId)
-+                throws RemoteException {
-+            userId = handleIncomingUser(userId, "getAllOverlays");
-+
-+            synchronized (mLock) {
-+                return mImpl.onGetOverlaysForUser(userId);
-+            }
-+        }
-+
-+        @Override
-+        public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
-+                int userId) throws RemoteException {
-+            userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
-+            if (targetPackageName == null) {
-+                return Collections.emptyList();
-+            }
-+
-+            synchronized (mLock) {
-+                return mImpl.onGetOverlayInfosForTarget(targetPackageName, userId);
-+            }
-+        }
-+
-+        @Override
-+        public OverlayInfo getOverlayInfo(@Nullable final String packageName,
-+                int userId) throws RemoteException {
-+            userId = handleIncomingUser(userId, "getOverlayInfo");
-+            if (packageName == null) {
-+                return null;
-+            }
-+
-+            synchronized (mLock) {
-+                return mImpl.onGetOverlayInfo(packageName, userId);
-+            }
-+        }
-+
-+        @Override
-+        public boolean setEnabled(@Nullable final String packageName, final boolean enable,
-+                int userId) throws RemoteException {
-+            enforceChangeConfigurationPermission("setEnabled");
-+            userId = handleIncomingUser(userId, "setEnabled");
-+            if (packageName == null) {
-+                return false;
-+            }
-+
-+            final long ident = Binder.clearCallingIdentity();
-+            try {
-+                synchronized (mLock) {
-+                    return mImpl.onSetEnabled(packageName, enable, userId);
-+                }
-+            } finally {
-+                Binder.restoreCallingIdentity(ident);
-+            }
-+        }
-+
-+        @Override
-+        public boolean setPriority(@Nullable final String packageName,
-+                @Nullable final String parentPackageName, int userId) throws RemoteException {
-+            enforceChangeConfigurationPermission("setPriority");
-+            userId = handleIncomingUser(userId, "setPriority");
-+            if (packageName == null || parentPackageName == null) {
-+                return false;
-+            }
-+
-+            final long ident = Binder.clearCallingIdentity();
-+            try {
-+                synchronized (mLock) {
-+                    return mImpl.onSetPriority(packageName, parentPackageName, userId);
-+                }
-+            } finally {
-+                Binder.restoreCallingIdentity(ident);
-+            }
-+        }
-+
-+        @Override
-+        public boolean setHighestPriority(@Nullable final String packageName, int userId)
-+                throws RemoteException {
-+            enforceChangeConfigurationPermission("setHighestPriority");
-+            userId = handleIncomingUser(userId, "setHighestPriority");
-+            if (packageName == null) {
-+                return false;
-+            }
-+
-+            final long ident = Binder.clearCallingIdentity();
-+            try {
-+                synchronized (mLock) {
-+                    return mImpl.onSetHighestPriority(packageName, userId);
-+                }
-+            } finally {
-+                Binder.restoreCallingIdentity(ident);
-+            }
-+        }
-+
-+        @Override
-+        public boolean setLowestPriority(@Nullable final String packageName, int userId)
-+                throws RemoteException {
-+            enforceChangeConfigurationPermission("setLowestPriority");
-+            userId = handleIncomingUser(userId, "setLowestPriority");
-+            if (packageName == null) {
-+                return false;
-+            }
-+
-+            final long ident = Binder.clearCallingIdentity();
-+            try {
-+                synchronized (mLock) {
-+                    return mImpl.onSetLowestPriority(packageName, userId);
-+                }
-+            } finally {
-+                Binder.restoreCallingIdentity(ident);
-+            }
-+        }
-+
-+        @Override
-+        public void onShellCommand(@NonNull final FileDescriptor in,
-+                @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
-+                @NonNull final String[] args, @NonNull final ResultReceiver resultReceiver) {
-+            (new OverlayManagerShellCommand(this)).exec(
-+                    this, in, out, err, args, resultReceiver);
-+        }
-+
-+        @Override
-+        protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw,
-+                @NonNull final String[] argv) {
-+            enforceDumpPermission("dump");
-+
-+            final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]);
-+
-+            synchronized (mLock) {
-+                mImpl.onDump(pw);
-+                mPackageManager.dump(pw, verbose);
-+            }
-+        }
-+
-+        /**
-+         * Ensure that the caller has permission to interact with the given userId.
-+         * If the calling user is not the same as the provided user, the caller needs
-+         * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
-+         * root).
-+         *
-+         * @param userId the user to interact with
-+         * @param message message for any SecurityException
-+         */
-+        private int handleIncomingUser(final int userId, @NonNull final String message) {
-+            return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
-+                    Binder.getCallingUid(), userId, false, true, message, null);
-+        }
-+
-+        /**
-+         * Enforce that the caller holds the CHANGE_CONFIGURATION permission (or is
-+         * system or root).
-+         *
-+         * @param message used as message if SecurityException is thrown
-+         * @throws SecurityException if the permission check fails
-+         */
-+        private void enforceChangeConfigurationPermission(@NonNull final String message) {
-+            final int callingUid = Binder.getCallingUid();
-+
-+            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
-+                getContext().enforceCallingOrSelfPermission(
-+                        android.Manifest.permission.CHANGE_CONFIGURATION, message);
-+            }
-+        }
-+
-+        /**
-+         * Enforce that the caller holds the DUMP permission (or is system or root).
-+         *
-+         * @param message used as message if SecurityException is thrown
-+         * @throws SecurityException if the permission check fails
-+         */
-+        private void enforceDumpPermission(@NonNull final String message) {
-+            final int callingUid = Binder.getCallingUid();
-+
-+            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
-+                getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
-+                        message);
-+            }
-+        }
-+    };
-+
-+    private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
-+        return pi != null && pi.overlayTarget != null;
-+    }
-+
-+    private final class OverlayChangeListener implements OverlayManagerSettings.ChangeListener {
-+        @Override
-+        public void onSettingsChanged() {
-+            schedulePersistSettings();
-+        }
-+
-+        @Override
-+        public void onOverlayAdded(@NonNull final OverlayInfo oi) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
-+        }
-+
-+        @Override
-+        public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
-+        }
-+
-+        @Override
-+        public void onOverlayChanged(@NonNull final OverlayInfo oi,
-+                @NonNull final OverlayInfo oldOi) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
-+        }
-+
-+        @Override
-+        public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
-+        }
-+
-+        private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
-+                final boolean doUpdate) {
-+            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
-+        }
-+
-+        private final class BroadcastRunnable extends Thread {
-+            private final String mAction;
-+            private final OverlayInfo mOverlayInfo;
-+            private final boolean mDoUpdate;
-+
-+            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
-+                    final boolean doUpdate) {
-+                mAction = action;
-+                mOverlayInfo = oi;
-+                mDoUpdate = doUpdate;
-+            }
-+
-+            public void run() {
-+                if (mDoUpdate) {
-+                    updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
-+                }
-+                sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
-+                        mOverlayInfo.userId);
-+            }
-+
-+            private void sendBroadcast(@NonNull final String action,
-+                    @NonNull final String targetPackageName, @NonNull final String packageName,
-+                    final int userId) {
-+                final Intent intent = new Intent(action, Uri.fromParts("package",
-+                            String.format("%s/%s", targetPackageName, packageName), null));
-+                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-+                if (DEBUG) {
-+                    Slog.d(TAG, String.format("send broadcast %s", intent));
-+                }
-+                try {
-+                    ActivityManagerNative.getDefault().broadcastIntent(null, intent, null, null, 0,
-+                            null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
-+                            userId);
-+                } catch (RemoteException e) {
-+                    // Intentionally left empty.
-+                }
-+            }
-+
-+        }
-+    }
-+
-+    private void updateAssets(final int userId, final String targetPackageName) {
-+        final List<String> list = new ArrayList<>();
-+        list.add(targetPackageName);
-+        updateAssets(userId, list);
-+    }
-+
-+    private void updateAssets(final int userId, List<String> targetPackageNames) {
-+        // TODO: uncomment 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, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
-+        // synchronized (mLock) {
-+        //     final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
-+        //     for (final String packageName : targetPackageNames) {
-+        //         final List<String> paths = new ArrayList<>();
-+        //         paths.addAll(frameworkPaths);
-+        //         if (!"android".equals(packageName)) {
-+        //             paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
-+        //         }
-+        //         allPaths.put(packageName,
-+        //             paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
-+        //     }
-+        // }
-+
-+        // for (String packageName : targetPackageNames) {
-+        //     pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
-+        // }
-+
-+        // final IActivityManager am = ActivityManagerNative.getDefault();
-+        // try {
-+        //     am.updateAssets(userId, targetPackageNames);
-+        // } catch (RemoteException e) {
-+        //     // Intentionally left empty.
-+        // }
-+    }
-+
-+    private void schedulePersistSettings() {
-+        if (mPersistSettingsScheduled.get()) {
-+            return;
-+        }
-+        mPersistSettingsScheduled.set(true);
-+        IoThread.getHandler().post(new Runnable() {
-+            @Override
-+            public void run() {
-+                mPersistSettingsScheduled.set(false);
-+                synchronized (mLock) {
-+                    FileOutputStream stream = null;
-+                    try {
-+                        stream = mSettingsFile.startWrite();
-+                        mSettings.persist(stream);
-+                        mSettingsFile.finishWrite(stream);
-+                    } catch (IOException | XmlPullParserException e) {
-+                        mSettingsFile.failWrite(stream);
-+                        Slog.e(TAG, "failed to persist overlay state", e);
-+                    }
-+                }
-+            }
-+        });
-+    }
-+
-+    private void restoreSettings() {
-+        synchronized (mLock) {
-+            if (!mSettingsFile.getBaseFile().exists()) {
-+                return;
-+            }
-+            try (final FileInputStream stream = mSettingsFile.openRead()) {
-+                mSettings.restore(stream);
-+
-+                // We might have data for dying users if the device was
-+                // restarted before we received USER_REMOVED. Remove data for
-+                // users that will not exist after the system is ready.
-+
-+                for (final UserInfo deadUser : getDeadUsers()) {
-+                    final int userId = deadUser.getUserHandle().getIdentifier();
-+                    mSettings.removeUser(userId);
-+                }
-+            } catch (IOException | XmlPullParserException e) {
-+                Slog.e(TAG, "failed to restore overlay state", e);
-+            }
-+        }
-+    }
-+
-+    private List<UserInfo> getDeadUsers() {
-+        final List<UserInfo> users = mUserManager.getUsers(false);
-+        final List<UserInfo> onlyLiveUsers = mUserManager.getUsers(true);
-+
-+        // UserInfo doesn't implement equals, so we'll roll our own
-+        // Collection.removeAll implementation
-+        final Iterator<UserInfo> iter = users.iterator();
-+        while (iter.hasNext()) {
-+            final UserInfo ui = iter.next();
-+            for (final UserInfo live : onlyLiveUsers) {
-+                if (ui.id == live.id) {
-+                    iter.remove();
-+                    break;
-+                }
-+            }
-+        }
-+
-+        return users;
-+    }
-+
-+    private static final class PackageManagerHelper implements
-+        OverlayManagerServiceImpl.PackageManagerHelper {
-+
-+        private final IPackageManager mPackageManager;
-+        private final PackageManagerInternal mPackageManagerInternal;
-+
-+        // Use a cache for performance and for consistency within OMS: because
-+        // additional PACKAGE_* intents may be delivered while we process an
-+        // intent, querying the PackageManagerService for the actual current
-+        // state may lead to contradictions within OMS. Better then to lag
-+        // behind until all pending intents have been processed.
-+        private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
-+
-+        public PackageManagerHelper() {
-+            mPackageManager = getPackageManager();
-+            mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-+        }
-+
-+        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
-+                final boolean useCache) {
-+            if (useCache) {
-+                final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
-+                if (cachedPi != null) {
-+                    return cachedPi;
-+                }
-+            }
-+            try {
-+                final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
-+                if (useCache && pi != null) {
-+                    cachePackageInfo(packageName, userId, pi);
-+                }
-+                return pi;
-+            } catch (RemoteException e) {
-+                // Intentionally left empty.
-+            }
-+            return null;
-+        }
-+
-+        @Override
-+        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
-+            return getPackageInfo(packageName, userId, true);
-+        }
-+
-+        @Override
-+        public boolean signaturesMatching(@NonNull final String packageName1,
-+                @NonNull final String packageName2, final int userId) {
-+            // The package manager does not support different versions of packages
-+            // to be installed for different users: ignore userId for now.
-+            try {
-+                return mPackageManager.checkSignatures(packageName1, packageName2) == SIGNATURE_MATCH;
-+            } catch (RemoteException e) {
-+                // Intentionally left blank
-+            }
-+            return false;
-+        }
-+
-+        @Override
-+        public List<PackageInfo> getOverlayPackages(final int userId) {
-+            return mPackageManagerInternal.getOverlayPackages(userId);
-+        }
-+
-+        public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
-+                final int userId) {
-+            final HashMap<String, PackageInfo> map = mCache.get(userId);
-+            return map == null ? null : map.get(packageName);
-+        }
-+
-+        public void cachePackageInfo(@NonNull final String packageName, final int userId,
-+                @NonNull final PackageInfo pi) {
-+            HashMap<String, PackageInfo> map = mCache.get(userId);
-+            if (map == null) {
-+                map = new HashMap<>();
-+                mCache.put(userId, map);
-+            }
-+            map.put(packageName, pi);
-+        }
-+
-+        public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
-+            final HashMap<String, PackageInfo> map = mCache.get(userId);
-+            if (map == null) {
-+                return;
-+            }
-+            map.remove(packageName);
-+            if (map.isEmpty()) {
-+                mCache.delete(userId);
-+            }
-+        }
-+
-+        public void forgetAllPackageInfos(final int userId) {
-+            mCache.delete(userId);
-+        }
-+
-+        private static final String TAB1 = "    ";
-+        private static final String TAB2 = TAB1 + TAB1;
-+
-+        public void dump(@NonNull final PrintWriter pw, final boolean verbose) {
-+            pw.println("PackageInfo cache");
-+
-+            if (!verbose) {
-+                int n = 0;
-+                for (int i = 0; i < mCache.size(); i++) {
-+                    final int userId = mCache.keyAt(i);
-+                    n += mCache.get(userId).size();
-+                }
-+                pw.println(TAB1 + n + " package(s)");
-+                return;
-+            }
-+
-+            if (mCache.size() == 0) {
-+                pw.println(TAB1 + "<empty>");
-+                return;
-+            }
-+
-+            for (int i = 0; i < mCache.size(); i++) {
-+                final int userId = mCache.keyAt(i);
-+                pw.println(TAB1 + "User " + userId);
-+                final HashMap<String, PackageInfo> map = mCache.get(userId);
-+                for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
-+                    pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
-+                }
-+            }
-+        }
-+    }
-+}
-diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-new file mode 100644
-index 0000000..2a0d88b
---- /dev/null
-+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-@@ -0,0 +1,478 @@
-+/*
-+ * Copyright (C) 2016 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package com.android.server.om;
-+
-+import static android.content.om.OverlayInfo.STATE_APPROVED_DISABLED;
-+import static android.content.om.OverlayInfo.STATE_APPROVED_ENABLED;
-+import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_COMPONENT_DISABLED;
-+import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
-+import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_MISSING_TARGET;
-+import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_NO_IDMAP;
-+import static com.android.server.om.OverlayManagerService.DEBUG;
-+import static com.android.server.om.OverlayManagerService.TAG;
-+
-+import android.annotation.NonNull;
-+import android.annotation.Nullable;
-+import android.content.om.OverlayInfo;
-+import android.content.pm.ApplicationInfo;
-+import android.content.pm.PackageInfo;
-+import android.util.ArrayMap;
-+import android.util.ArraySet;
-+import android.util.Slog;
-+
-+import java.io.PrintWriter;
-+import java.util.ArrayList;
-+import java.util.Iterator;
-+import java.util.List;
-+import java.util.Map;
-+import java.util.Set;
-+
-+/**
-+ * Internal implementation of OverlayManagerService.
-+ *
-+ * Methods in this class should only be called by the OverlayManagerService.
-+ * This class is not thread-safe; the caller is expected to ensure the
-+ * necessary thread synchronization.
-+ *
-+ * @see OverlayManagerService
-+ */
-+final class OverlayManagerServiceImpl {
-+    private final PackageManagerHelper mPackageManager;
-+    private final IdmapManager mIdmapManager;
-+    private final OverlayManagerSettings mSettings;
-+
-+    OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
-+            @NonNull final IdmapManager idmapManager,
-+            @NonNull final OverlayManagerSettings settings) {
-+        mPackageManager = packageManager;
-+        mIdmapManager = idmapManager;
-+        mSettings = settings;
-+    }
-+
-+    /*
-+     * Call this when switching to a new Android user. Will return a list of
-+     * target packages that must refresh their overlays. This list is the union
-+     * of two sets: the set of targets with currently active overlays, and the
-+     * set of targets that had, but no longer have, active overlays.
-+     */
-+    List<String> onSwitchUser(final int newUserId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
-+        }
-+
-+        final Set<String> packagesToUpdateAssets = new ArraySet<>();
-+        final Map<String, List<OverlayInfo>> tmp = mSettings.getOverlaysForUser(newUserId);
-+        final Map<String, OverlayInfo> storedOverlayInfos = new ArrayMap<>(tmp.size());
-+        for (final List<OverlayInfo> chunk: tmp.values()) {
-+            for (final OverlayInfo oi: chunk) {
-+                storedOverlayInfos.put(oi.packageName, oi);
-+            }
-+        }
-+
-+        for (PackageInfo overlayPackage: mPackageManager.getOverlayPackages(newUserId)) {
-+            final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
-+            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
-+                if (oi != null) {
-+                    packagesToUpdateAssets.add(oi.targetPackageName);
-+                }
-+                mSettings.init(overlayPackage.packageName, newUserId,
-+                        overlayPackage.overlayTarget,
-+                        overlayPackage.applicationInfo.getBaseCodePath());
-+            }
-+
-+            try {
-+                final PackageInfo targetPackage =
-+                    mPackageManager.getPackageInfo(overlayPackage.overlayTarget, newUserId);
-+                updateState(targetPackage, overlayPackage, newUserId);
-+            } catch (OverlayManagerSettings.BadKeyException e) {
-+                Slog.e(TAG, "failed to update settings", e);
-+                mSettings.remove(overlayPackage.packageName, newUserId);
-+            }
-+
-+            packagesToUpdateAssets.add(overlayPackage.overlayTarget);
-+            storedOverlayInfos.remove(overlayPackage.packageName);
-+        }
-+
-+        // any OverlayInfo left in storedOverlayInfos is no longer
-+        // installed and should be removed
-+        for (final OverlayInfo oi: storedOverlayInfos.values()) {
-+            mSettings.remove(oi.packageName, oi.userId);
-+            removeIdmapIfPossible(oi);
-+            packagesToUpdateAssets.add(oi.targetPackageName);
-+        }
-+
-+        // remove target packages that are not installed
-+        final Iterator<String> iter = packagesToUpdateAssets.iterator();
-+        while (iter.hasNext()) {
-+            String targetPackageName = iter.next();
-+            if (mPackageManager.getPackageInfo(targetPackageName, newUserId) == null) {
-+                iter.remove();
-+            }
-+        }
-+
-+        return new ArrayList<String>(packagesToUpdateAssets);
-+    }
-+
-+    void onUserRemoved(final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onUserRemoved userId=" + userId);
-+        }
-+        mSettings.removeUser(userId);
-+    }
-+
-+    void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
-+    }
-+
-+    void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
-+    }
-+
-+    void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        updateAllOverlaysForTarget(packageName, userId, null);
-+    }
-+
-+    void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
-+    }
-+
-+    void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        updateAllOverlaysForTarget(packageName, userId, null);
-+    }
-+
-+    private void updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
-+            @Nullable final PackageInfo targetPackage) {
-+        final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
-+        for (final OverlayInfo oi : ois) {
-+            final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
-+            if (overlayPackage == null) {
-+                mSettings.remove(oi.packageName, oi.userId);
-+                removeIdmapIfPossible(oi);
-+            } else {
-+                try {
-+                    updateState(targetPackage, overlayPackage, userId);
-+                } catch (OverlayManagerSettings.BadKeyException e) {
-+                    Slog.e(TAG, "failed to update settings", e);
-+                    mSettings.remove(oi.packageName, userId);
-+                }
-+            }
-+        }
-+    }
-+
-+    void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        if (overlayPackage == null) {
-+            Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
-+            onOverlayPackageRemoved(packageName, userId);
-+            return;
-+        }
-+
-+        final PackageInfo targetPackage =
-+            mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
-+
-+        mSettings.init(packageName, userId, overlayPackage.overlayTarget,
-+                overlayPackage.applicationInfo.getBaseCodePath());
-+        try {
-+            updateState(targetPackage, overlayPackage, userId);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            Slog.e(TAG, "failed to update settings", e);
-+            mSettings.remove(packageName, userId);
-+        }
-+    }
-+
-+    void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        if (overlayPackage == null) {
-+            Slog.w(TAG, "overlay package " + packageName + " was changed, but couldn't be found");
-+            onOverlayPackageRemoved(packageName, userId);
-+            return;
-+        }
-+
-+        final PackageInfo targetPackage =
-+            mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
-+
-+        try {
-+            updateState(targetPackage, overlayPackage, userId);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            Slog.e(TAG, "failed to update settings", e);
-+            mSettings.remove(packageName, userId);
-+        }
-+    }
-+
-+    void onOverlayPackageUpgrading(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onOverlayPackageUpgrading packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        try {
-+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
-+            mSettings.setUpgrading(packageName, userId, true);
-+            removeIdmapIfPossible(oi);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            Slog.e(TAG, "failed to update settings", e);
-+            mSettings.remove(packageName, userId);
-+        }
-+    }
-+
-+    void onOverlayPackageUpgraded(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onOverlayPackageUpgraded packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        if (overlayPackage == null) {
-+            Slog.w(TAG, "overlay package " + packageName + " was upgraded, but couldn't be found");
-+            onOverlayPackageRemoved(packageName, userId);
-+            return;
-+        }
-+
-+        try {
-+            final String storedTargetPackageName = mSettings.getTargetPackageName(packageName, userId);
-+            if (!overlayPackage.overlayTarget.equals(storedTargetPackageName)) {
-+                // Sneaky little hobbitses, changing the overlay's target package
-+                // from one version to the next! We can't use the old version's
-+                // state.
-+                mSettings.remove(packageName, userId);
-+                onOverlayPackageAdded(packageName, userId);
-+                return;
-+            }
-+
-+            mSettings.setUpgrading(packageName, userId, false);
-+            final PackageInfo targetPackage =
-+                mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
-+            updateState(targetPackage, overlayPackage, userId);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            Slog.e(TAG, "failed to update settings", e);
-+            mSettings.remove(packageName, userId);
-+        }
-+    }
-+
-+    void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, "onOverlayPackageRemoved packageName=" + packageName + " userId=" + userId);
-+        }
-+
-+        try {
-+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
-+            mSettings.remove(packageName, userId);
-+            removeIdmapIfPossible(oi);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            Slog.e(TAG, "failed to remove overlay package", e);
-+        }
-+    }
-+
-+    OverlayInfo onGetOverlayInfo(@NonNull final String packageName, final int userId) {
-+        try {
-+            return mSettings.getOverlayInfo(packageName, userId);
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            return null;
-+        }
-+    }
-+
-+    List<OverlayInfo> onGetOverlayInfosForTarget(@NonNull final String targetPackageName,
-+            final int userId) {
-+        return mSettings.getOverlaysForTarget(targetPackageName, userId);
-+    }
-+
-+    Map<String, List<OverlayInfo>> onGetOverlaysForUser(final int userId) {
-+        return mSettings.getOverlaysForUser(userId);
-+    }
-+
-+    boolean onSetEnabled(@NonNull final String packageName, final boolean enable,
-+            final int userId) {
-+        if (DEBUG) {
-+            Slog.d(TAG, String.format("onSetEnabled packageName=%s enable=%s userId=%d",
-+                        packageName, enable, userId));
-+        }
-+
-+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-+        if (overlayPackage == null) {
-+            return false;
-+        }
-+
-+        try {
-+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
-+            final PackageInfo targetPackage =
-+                mPackageManager.getPackageInfo(oi.targetPackageName, userId);
-+            mSettings.setEnabled(packageName, userId, enable);
-+            updateState(targetPackage, overlayPackage, userId);
-+            return true;
-+        } catch (OverlayManagerSettings.BadKeyException e) {
-+            return false;
-+        }
-+    }
-+
-+    boolean onSetPriority(@NonNull final String packageName,
-+            @NonNull final String newParentPackageName, final int userId) {
-+        return mSettings.setPriority(packageName, newParentPackageName, userId);
-+    }
-+
-+    boolean onSetHighestPriority(@NonNull final String packageName, final int userId) {
-+        return mSettings.setHighestPriority(packageName, userId);
-+    }
-+
-+    boolean onSetLowestPriority(@NonNull final String packageName, final int userId) {
-+        return mSettings.setLowestPriority(packageName, userId);
-+    }
-+
-+    void onDump(@NonNull final PrintWriter pw) {
-+        mSettings.dump(pw);
-+    }
-+
-+    List<String> onGetEnabledOverlayPaths(@NonNull final String targetPackageName,
-+            final int userId) {
-+        final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId);
-+        final List<String> paths = new ArrayList<>(overlays.size());
-+        for (final OverlayInfo oi : overlays) {
-+            if (oi.isEnabled()) {
-+                paths.add(oi.baseCodePath);
-+            }
-+        }
-+        return paths;
-+    }
-+
-+    private void updateState(@Nullable final PackageInfo targetPackage,
-+            @NonNull final PackageInfo overlayPackage, final int userId)
-+        throws OverlayManagerSettings.BadKeyException {
-+        if (targetPackage != null) {
-+            mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
-+        }
-+
-+        mSettings.setBaseCodePath(overlayPackage.packageName, userId,
-+                overlayPackage.applicationInfo.getBaseCodePath());
-+
-+        final int currentState = mSettings.getState(overlayPackage.packageName, userId);
-+        final int newState = calculateNewState(targetPackage, overlayPackage, userId);
-+        if (currentState != newState) {
-+            if (DEBUG) {
-+                Slog.d(TAG, String.format("%s:%d: %s -> %s",
-+                            overlayPackage.packageName, userId,
-+                            OverlayInfo.stateToString(currentState),
-+                            OverlayInfo.stateToString(newState)));
-+            }
-+            mSettings.setState(overlayPackage.packageName, userId, newState);
-+        }
-+    }
-+
-+    private int calculateNewState(@Nullable final PackageInfo targetPackage,
-+            @NonNull final PackageInfo overlayPackage, final int userId)
-+        throws OverlayManagerSettings.BadKeyException {
-+        if (!overlayPackage.applicationInfo.enabled) {
-+            return STATE_NOT_APPROVED_COMPONENT_DISABLED;
-+        }
-+
-+        if (targetPackage == null) {
-+            return STATE_NOT_APPROVED_MISSING_TARGET;
-+        }
-+
-+        if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
-+            return STATE_NOT_APPROVED_NO_IDMAP;
-+        }
-+
-+        final boolean enableIfApproved = mSettings.getEnabled(overlayPackage.packageName, userId);
-+
-+        if (mPackageManager.signaturesMatching(targetPackage.packageName,
-+                    overlayPackage.packageName, userId)) {
-+            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-+        }
-+
-+        if ((overlayPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-+            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-+        }
-+
-+        if (!mIdmapManager.isDangerous(overlayPackage, userId)) {
-+            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-+        }
-+
-+        return STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
-+    }
-+
-+    private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
-+        // For a given package, all Android users share the same idmap file.
-+        // This works because Android currently does not support users to
-+        // install different versions of the same package. It also means we
-+        // cannot remove an idmap file if any user still needs it.
-+        //
-+        // When/if the Android framework allows different versions of the same
-+        // package to be installed for different users, idmap file handling
-+        // should be revised:
-+        //
-+        // - an idmap file should be unique for each {user, package} pair
-+        //
-+        // - the path to the idmap file should be passed to the native Asset
-+        //   Manager layers, just like the path to the apk is passed today
-+        //
-+        // As part of that change, calls to this method should be replaced by
-+        // direct calls to IdmapManager.removeIdmap, without looping over all
-+        // users.
-+
-+        if (!mIdmapManager.idmapExists(oi)) {
-+            return;
-+        }
-+        final List<Integer> userIds = mSettings.getUsers();
-+        for (final int userId : userIds) {
-+            try {
-+                final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
-+                if (tmp != null && tmp.isEnabled()) {
-+                    // someone is still using the idmap file -> we cannot remove it
-+                    return;
-+                }
-+            } catch (OverlayManagerSettings.BadKeyException e) {
-+                // intentionally left empty
-+            }
-+        }
-+        mIdmapManager.removeIdmap(oi, oi.userId);
-+    }
-+
-+    interface PackageManagerHelper {
-+        PackageInfo getPackageInfo(@NonNull String packageName, int userId);
-+        boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
-+                                   int userId);
-+        List<PackageInfo> getOverlayPackages(int userId);
-+    }
-+}
-diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
-new file mode 100644
-index 0000000..af0bb64
---- /dev/null
-+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
-@@ -0,0 +1,656 @@
-+/*
-+ * Copyright (C) 2016 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package com.android.server.om;
-+
-+import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_UNKNOWN;
-+import static com.android.server.om.OverlayManagerService.DEBUG;
-+import static com.android.server.om.OverlayManagerService.TAG;
-+
-+import android.annotation.NonNull;
-+import android.annotation.Nullable;
-+import android.content.om.OverlayInfo;
-+import android.util.AndroidRuntimeException;
-+import android.util.ArrayMap;
-+import android.util.Slog;
-+import android.util.Xml;
-+
-+import com.android.internal.util.FastXmlSerializer;
-+import com.android.internal.util.XmlUtils;
-+
-+import org.xmlpull.v1.XmlPullParser;
-+import org.xmlpull.v1.XmlPullParserException;
-+
-+import java.io.IOException;
-+import java.io.InputStream;
-+import java.io.InputStreamReader;
-+import java.io.OutputStream;
-+import java.io.PrintWriter;
-+import java.util.ArrayList;
-+import java.util.Collections;
-+import java.util.Iterator;
-+import java.util.List;
-+import java.util.ListIterator;
-+import java.util.Map;
-+
-+/**
-+ * Data structure representing the current state of all overlay packages in the
-+ * system.
-+ *
-+ * Modifications to the data are exposed through the ChangeListener interface.
-+ *
-+ * @see ChangeListener
-+ * @see OverlayManagerService
-+ */
-+final class OverlayManagerSettings {
-+    private final List<ChangeListener> mListeners = new ArrayList<>();
-+
-+    private final ArrayList<SettingsItem> mItems = new ArrayList<>();
-+
-+    void init(@NonNull final String packageName, final int userId,
-+            @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
-+        remove(packageName, userId);
-+        final SettingsItem item =
-+            new SettingsItem(packageName, userId, targetPackageName, baseCodePath);
-+        mItems.add(item);
-+    }
-+
-+    void remove(@NonNull final String packageName, final int userId) {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            return;
-+        }
-+        final OverlayInfo oi = item.getOverlayInfo();
-+        mItems.remove(item);
-+        if (oi != null) {
-+            notifyOverlayRemoved(oi);
-+        }
-+    }
-+
-+    boolean contains(@NonNull final String packageName, final int userId) {
-+        return select(packageName, userId) != null;
-+    }
-+
-+    OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        return item.getOverlayInfo();
-+    }
-+
-+    String getTargetPackageName(@NonNull final String packageName, final int userId)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        return item.getTargetPackageName();
-+    }
-+
-+    void setBaseCodePath(@NonNull final String packageName, final int userId,
-+            @NonNull final String path) throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        item.setBaseCodePath(path);
-+        notifySettingsChanged();
-+    }
-+
-+    boolean getUpgrading(@NonNull final String packageName, final int userId)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        return item.isUpgrading();
-+    }
-+
-+    void setUpgrading(@NonNull final String packageName, final int userId, final boolean newValue)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        if (newValue == item.isUpgrading()) {
-+            return; // nothing to do
-+        }
-+
-+        if (newValue) {
-+            final OverlayInfo oi = item.getOverlayInfo();
-+            item.setUpgrading(true);
-+            item.setState(STATE_NOT_APPROVED_UNKNOWN);
-+            notifyOverlayRemoved(oi);
-+        } else {
-+            item.setUpgrading(false);
-+        }
-+        notifySettingsChanged();
-+    }
-+
-+    boolean getEnabled(@NonNull final String packageName, final int userId) throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        return item.isEnabled();
-+    }
-+
-+    void setEnabled(@NonNull final String packageName, final int userId, final boolean enable)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        if (enable == item.isEnabled()) {
-+            return; // nothing to do
-+        }
-+
-+        item.setEnabled(enable);
-+        notifySettingsChanged();
-+    }
-+
-+    int getState(@NonNull final String packageName, final int userId) throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        return item.getState();
-+    }
-+
-+    void setState(@NonNull final String packageName, final int userId, final int state)
-+            throws BadKeyException {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null) {
-+            throw new BadKeyException(packageName, userId);
-+        }
-+        final OverlayInfo previous = item.getOverlayInfo();
-+        item.setState(state);
-+        final OverlayInfo current = item.getOverlayInfo();
-+        if (previous.state == STATE_NOT_APPROVED_UNKNOWN) {
-+            notifyOverlayAdded(current);
-+            notifySettingsChanged();
-+        } else if (current.state != previous.state) {
-+            notifyOverlayChanged(current, previous);
-+            notifySettingsChanged();
-+        }
-+    }
-+
-+    List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
-+            final int userId) {
-+        final List<SettingsItem> items = selectWhereTarget(targetPackageName, userId);
-+        if (items.isEmpty()) {
-+            return Collections.emptyList();
-+        }
-+        final List<OverlayInfo> out = new ArrayList<>(items.size());
-+        for (final SettingsItem item : items) {
-+            if (item.isUpgrading()) {
-+                continue;
-+            }
-+            out.add(item.getOverlayInfo());
-+        }
-+        return out;
-+    }
-+
-+    Map<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
-+        final List<SettingsItem> items = selectWhereUser(userId);
-+        if (items.isEmpty()) {
-+            return Collections.emptyMap();
-+        }
-+        final Map<String, List<OverlayInfo>> out = new ArrayMap<>(items.size());
-+        for (final SettingsItem item : items) {
-+            if (item.isUpgrading()) {
-+                continue;
-+            }
-+            final String targetPackageName = item.getTargetPackageName();
-+            if (!out.containsKey(targetPackageName)) {
-+                out.put(targetPackageName, new ArrayList<OverlayInfo>());
-+            }
-+            final List<OverlayInfo> overlays = out.get(targetPackageName);
-+            overlays.add(item.getOverlayInfo());
-+        }
-+        return out;
-+    }
-+
-+    List<String> getTargetPackageNamesForUser(final int userId) {
-+        final List<SettingsItem> items = selectWhereUser(userId);
-+        if (items.isEmpty()) {
-+            return Collections.emptyList();
-+        }
-+        final List<String> out = new ArrayList<>();
-+        for (final SettingsItem item : items) {
-+            if (item.isUpgrading()) {
-+                continue;
-+            }
-+            final String targetPackageName = item.getTargetPackageName();
-+            if (!out.contains(targetPackageName)) {
-+                out.add(targetPackageName);
-+            }
-+        }
-+        return out;
-+    }
-+
-+    List<Integer> getUsers() {
-+        final ArrayList<Integer> users = new ArrayList<>();
-+        for (final SettingsItem item : mItems) {
-+            if (!users.contains(item.userId)) {
-+                users.add(item.userId);
-+            }
-+        }
-+        return users;
-+    }
-+
-+    void removeUser(final int userId) {
-+        final Iterator<SettingsItem> iter = mItems.iterator();
-+        while (iter.hasNext()) {
-+            final SettingsItem item = iter.next();
-+            if (item.userId == userId) {
-+                iter.remove();
-+            }
-+        }
-+    }
-+
-+    boolean setPriority(@NonNull final String packageName,
-+            @NonNull final String newParentPackageName, final int userId) {
-+        if (packageName.equals(newParentPackageName)) {
-+            return false;
-+        }
-+        final SettingsItem rowToMove = select(packageName, userId);
-+        if (rowToMove == null || rowToMove.isUpgrading()) {
-+            return false;
-+        }
-+        final SettingsItem newParentRow = select(newParentPackageName, userId);
-+        if (newParentRow == null || newParentRow.isUpgrading()) {
-+            return false;
-+        }
-+        if (!rowToMove.getTargetPackageName().equals(newParentRow.getTargetPackageName())) {
-+            return false;
-+        }
-+
-+        mItems.remove(rowToMove);
-+        final ListIterator<SettingsItem> iter = mItems.listIterator();
-+        while (iter.hasNext()) {
-+            final SettingsItem item = iter.next();
-+            if (item.userId == userId && item.packageName.equals(newParentPackageName)) {
-+                iter.add(rowToMove);
-+                notifyOverlayPriorityChanged(rowToMove.getOverlayInfo());
-+                notifySettingsChanged();
-+                return true;
-+            }
-+        }
-+
-+        Slog.wtf(TAG, "failed to find the parent item a second time");
-+        return false;
-+    }
-+
-+    boolean setLowestPriority(@NonNull final String packageName, final int userId) {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null || item.isUpgrading()) {
-+            return false;
-+        }
-+        mItems.remove(item);
-+        mItems.add(0, item);
-+        notifyOverlayPriorityChanged(item.getOverlayInfo());
-+        notifySettingsChanged();
-+        return true;
-+    }
-+
-+    boolean setHighestPriority(@NonNull final String packageName, final int userId) {
-+        final SettingsItem item = select(packageName, userId);
-+        if (item == null || item.isUpgrading()) {
-+            return false;
-+        }
-+        mItems.remove(item);
-+        mItems.add(item);
-+        notifyOverlayPriorityChanged(item.getOverlayInfo());
-+        notifySettingsChanged();
-+        return true;
-+    }
-+
-+    private static final String TAB1 = "    ";
-+    private static final String TAB2 = TAB1 + TAB1;
-+    private static final String TAB3 = TAB2 + TAB1;
-+
-+    void dump(@NonNull final PrintWriter pw) {
-+        pw.println("Settings");
-+        dumpItems(pw);
-+        dumpListeners(pw);
-+    }
-+
-+    private void dumpItems(@NonNull final PrintWriter pw) {
-+        pw.println(TAB1 + "Items");
-+
-+        if (mItems.isEmpty()) {
-+            pw.println(TAB2 + "<none>");
-+            return;
-+        }
-+
-+        for (final SettingsItem item : mItems) {
-+            final StringBuilder sb = new StringBuilder();
-+            sb.append(TAB2 + item.packageName + ":" + item.userId + " {\n");
-+            sb.append(TAB3 + "packageName.......: " + item.packageName + "\n");
-+            sb.append(TAB3 + "userId............: " + item.userId + "\n");
-+            sb.append(TAB3 + "targetPackageName.: " + item.getTargetPackageName() + "\n");
-+            sb.append(TAB3 + "baseCodePath......: " + item.getBaseCodePath() + "\n");
-+            sb.append(TAB3 + "state.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
-+            sb.append(TAB3 + "isEnabled.........: " + item.isEnabled() + "\n");
-+            sb.append(TAB3 + "isUpgrading.......: " + item.isUpgrading() + "\n");
-+            sb.append(TAB2 + "}");
-+            pw.println(sb.toString());
-+        }
-+    }
-+
-+    private void dumpListeners(@NonNull final PrintWriter pw) {
-+        pw.println(TAB1 + "Change listeners");
-+
-+        if (mListeners.isEmpty()) {
-+            pw.println(TAB2 + "<none>");
-+            return;
-+        }
-+
-+        for (ChangeListener ch : mListeners) {
-+            pw.println(TAB2 + ch);
-+        }
-+
-+    }
-+
-+    void restore(@NonNull final InputStream is) throws IOException, XmlPullParserException {
-+        Serializer.restore(mItems, is);
-+    }
-+
-+    void persist(@NonNull final OutputStream os) throws IOException, XmlPullParserException {
-+        Serializer.persist(mItems, os);
-+    }
-+
-+    private static final class Serializer {
-+        private static final String TAG_OVERLAYS = "overlays";
-+        private static final String TAG_ITEM = "item";
-+
-+        private static final String ATTR_BASE_CODE_PATH = "baseCodePath";
-+        private static final String ATTR_IS_ENABLED = "isEnabled";
-+        private static final String ATTR_IS_UPGRADING = "isUpgrading";
-+        private static final String ATTR_PACKAGE_NAME = "packageName";
-+        private static final String ATTR_STATE = "state";
-+        private static final String ATTR_TARGET_PACKAGE_NAME = "targetPackageName";
-+        private static final String ATTR_USER_ID = "userId";
-+        private static final String ATTR_VERSION = "version";
-+
-+        private static final int CURRENT_VERSION = 1;
-+
-+        public static void restore(@NonNull final ArrayList<SettingsItem> table,
-+                @NonNull final InputStream is) throws IOException, XmlPullParserException {
-+
-+            table.clear();
-+            final XmlPullParser parser = Xml.newPullParser();
-+            parser.setInput(new InputStreamReader(is));
-+            XmlUtils.beginDocument(parser, TAG_OVERLAYS);
-+            int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION);
-+            if (version != CURRENT_VERSION) {
-+                throw new XmlPullParserException("unrecognized version " + version);
-+            }
-+            int depth = parser.getDepth();
-+
-+            while (XmlUtils.nextElementWithin(parser, depth)) {
-+                switch (parser.getName()) {
-+                    case TAG_ITEM:
-+                        final SettingsItem item = restoreRow(parser, depth + 1);
-+                        table.add(item);
-+                        break;
-+                }
-+            }
-+        }
-+
-+        private static SettingsItem restoreRow(@NonNull final XmlPullParser parser, final int depth)
-+                throws IOException {
-+            final String packageName = XmlUtils.readStringAttribute(parser, ATTR_PACKAGE_NAME);
-+            final int userId = XmlUtils.readIntAttribute(parser, ATTR_USER_ID);
-+            final String targetPackageName = XmlUtils.readStringAttribute(parser,
-+                    ATTR_TARGET_PACKAGE_NAME);
-+            final String baseCodePath = XmlUtils.readStringAttribute(parser, ATTR_BASE_CODE_PATH);
-+            final int state = XmlUtils.readIntAttribute(parser, ATTR_STATE);
-+            final boolean isEnabled = XmlUtils.readBooleanAttribute(parser, ATTR_IS_ENABLED);
-+            final boolean isUpgrading = XmlUtils.readBooleanAttribute(parser, ATTR_IS_UPGRADING);
-+
-+            return new SettingsItem(packageName, userId, targetPackageName, baseCodePath, state,
-+                    isEnabled, isUpgrading);
-+        }
-+
-+        public static void persist(@NonNull final ArrayList<SettingsItem> table,
-+                @NonNull final OutputStream os) throws IOException, XmlPullParserException {
-+            final FastXmlSerializer xml = new FastXmlSerializer();
-+            xml.setOutput(os, "utf-8");
-+            xml.startDocument(null, true);
-+            xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-+            xml.startTag(null, TAG_OVERLAYS);
-+            XmlUtils.writeIntAttribute(xml, ATTR_VERSION, CURRENT_VERSION);
-+
-+            for (final SettingsItem item : table) {
-+                persistRow(xml, item);
-+            }
-+            xml.endTag(null, TAG_OVERLAYS);
-+            xml.endDocument();
-+        }
-+
-+        private static void persistRow(@NonNull final FastXmlSerializer xml,
-+                @NonNull final SettingsItem item) throws IOException {
-+            xml.startTag(null, TAG_ITEM);
-+            XmlUtils.writeStringAttribute(xml, ATTR_PACKAGE_NAME, item.packageName);
-+            XmlUtils.writeIntAttribute(xml, ATTR_USER_ID, item.userId);
-+            XmlUtils.writeStringAttribute(xml, ATTR_TARGET_PACKAGE_NAME, item.targetPackageName);
-+            XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.baseCodePath);
-+            XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.state);
-+            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.isEnabled);
-+            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_UPGRADING, item.isUpgrading);
-+            xml.endTag(null, TAG_ITEM);
-+        }
-+    }
-+
-+    private static final class SettingsItem {
-+        private final int userId;
-+        private final String packageName;
-+        private final String targetPackageName;
-+        private String baseCodePath;
-+        private int state;
-+        private boolean isEnabled;
-+        private boolean isUpgrading;
-+        private OverlayInfo cache;
-+
-+        SettingsItem(@NonNull final String packageName, final int userId,
-+                @NonNull final String targetPackageName, @NonNull final String baseCodePath,
-+                final int state, final boolean isEnabled, final boolean isUpgrading) {
-+            this.packageName = packageName;
-+            this.userId = userId;
-+            this.targetPackageName = targetPackageName;
-+            this.baseCodePath = baseCodePath;
-+            this.state = state;
-+            this.isEnabled = isEnabled;
-+            this.isUpgrading = isUpgrading;
-+            cache = null;
-+        }
-+
-+        SettingsItem(@NonNull final String packageName, final int userId,
-+                @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
-+            this(packageName, userId, targetPackageName, baseCodePath, STATE_NOT_APPROVED_UNKNOWN,
-+                    false, false);
-+        }
-+
-+        private String getTargetPackageName() {
-+            return targetPackageName;
-+        }
-+
-+        private String getBaseCodePath() {
-+            return baseCodePath;
-+        }
-+
-+        private void setBaseCodePath(@NonNull final String path) {
-+            if (!baseCodePath.equals(path)) {
-+                baseCodePath = path;
-+                invalidateCache();
-+            }
-+        }
-+
-+        private int getState() {
-+            return state;
-+        }
-+
-+        private void setState(final int state) {
-+            if (this.state != state) {
-+                this.state = state;
-+                invalidateCache();
-+            }
-+        }
-+
-+        private boolean isEnabled() {
-+            return isEnabled;
-+        }
-+
-+        private void setEnabled(final boolean enable) {
-+            if (isEnabled != enable) {
-+                isEnabled = enable;
-+                invalidateCache();
-+            }
-+        }
-+
-+        private boolean isUpgrading() {
-+            return isUpgrading;
-+        }
-+
-+        private void setUpgrading(final boolean upgrading) {
-+            if (isUpgrading != upgrading) {
-+                isUpgrading = upgrading;
-+                invalidateCache();
-+            }
-+        }
-+
-+        private OverlayInfo getOverlayInfo() {
-+            if (isUpgrading) {
-+                return null;
-+            }
-+            if (cache == null) {
-+                cache = new OverlayInfo(packageName, targetPackageName, baseCodePath,
-+                        state, userId);
-+            }
-+            return cache;
-+        }
-+
-+        private void invalidateCache() {
-+            cache = null;
-+        }
-+    }
-+
-+    private SettingsItem select(@NonNull final String packageName, final int userId) {
-+        for (final SettingsItem item : mItems) {
-+            if (item.userId == userId && item.packageName.equals(packageName)) {
-+                return item;
-+            }
-+        }
-+        return null;
-+    }
-+
-+    private List<SettingsItem> selectWhereUser(final int userId) {
-+        final ArrayList<SettingsItem> items = new ArrayList<>();
-+        for (final SettingsItem item : mItems) {
-+            if (item.userId == userId) {
-+                items.add(item);
-+            }
-+        }
-+        return items;
-+    }
-+
-+    private List<SettingsItem> selectWhereTarget(@NonNull final String targetPackageName,
-+            final int userId) {
-+        final ArrayList<SettingsItem> items = new ArrayList<>();
-+        for (final SettingsItem item : mItems) {
-+            if (item.userId == userId && item.getTargetPackageName().equals(targetPackageName)) {
-+                items.add(item);
-+            }
-+        }
-+        return items;
-+    }
-+
-+    private void assertNotNull(@Nullable final Object o) {
-+        if (o == null) {
-+            throw new AndroidRuntimeException("object must not be null");
-+        }
-+    }
-+
-+    void addChangeListener(@NonNull final ChangeListener listener) {
-+        mListeners.add(listener);
-+    }
-+
-+    void removeChangeListener(@NonNull final ChangeListener listener) {
-+        mListeners.remove(listener);
-+    }
-+
-+    private void notifySettingsChanged() {
-+        for (final ChangeListener listener : mListeners) {
-+            listener.onSettingsChanged();
-+        }
-+    }
-+
-+    private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
-+        if (DEBUG) {
-+            assertNotNull(oi);
-+        }
-+        for (final ChangeListener listener : mListeners) {
-+            listener.onOverlayAdded(oi);
-+        }
-+    }
-+
-+    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
-+        if (DEBUG) {
-+            assertNotNull(oi);
-+        }
-+        for (final ChangeListener listener : mListeners) {
-+            listener.onOverlayRemoved(oi);
-+        }
-+    }
-+
-+    private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
-+            @NonNull final OverlayInfo oldOi) {
-+        if (DEBUG) {
-+            assertNotNull(oi);
-+            assertNotNull(oldOi);
-+        }
-+        for (final ChangeListener listener : mListeners) {
-+            listener.onOverlayChanged(oi, oldOi);
-+        }
-+    }
-+
-+    private void notifyOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
-+        if (DEBUG) {
-+            assertNotNull(oi);
-+        }
-+        for (final ChangeListener listener : mListeners) {
-+            listener.onOverlayPriorityChanged(oi);
-+        }
-+    }
-+
-+    interface ChangeListener {
-+        void onSettingsChanged();
-+        void onOverlayAdded(@NonNull OverlayInfo oi);
-+        void onOverlayRemoved(@NonNull OverlayInfo oi);
-+        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
-+        void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
-+    }
-+
-+    static final class BadKeyException extends RuntimeException {
-+        public BadKeyException(@NonNull final String packageName, final int userId) {
-+            super("Bad key packageName=" + packageName + " userId=" + userId);
-+        }
-+    }
-+}
-diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-new file mode 100644
-index 0000000..d6f5373
---- /dev/null
-+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-@@ -0,0 +1,179 @@
-+/*
-+ * Copyright (C) 2016 The Android Open Source Project
-+ *
-+ * Licensed under the Apache License, Version 2.0 (the "License");
-+ * you may not use this file except in compliance with the License.
-+ * You may obtain a copy of the License at
-+ *
-+ *      http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ */
-+
-+package com.android.server.om;
-+
-+import android.annotation.NonNull;
-+import android.annotation.Nullable;
-+import android.content.om.IOverlayManager;
-+import android.content.om.OverlayInfo;
-+import android.os.RemoteException;
-+import android.os.ShellCommand;
-+import android.os.UserHandle;
-+
-+import java.io.PrintWriter;
-+import java.util.List;
-+import java.util.Map;
-+
-+/**
-+ * Implementation of 'cmd overlay' commands.
-+ *
-+ * This class provides an interface to the OverlayManagerService via adb.
-+ * Intended only for manual debugging. Execute 'adb exec-out cmd overlay help'
-+ * for a list of available commands.
-+ */
-+final class OverlayManagerShellCommand extends ShellCommand {
-+    private final IOverlayManager mInterface;
-+
-+    OverlayManagerShellCommand(@NonNull final IOverlayManager iom) {
-+        mInterface = iom;
-+    }
-+
-+    @Override
-+    public int onCommand(@Nullable final String cmd) {
-+        if (cmd == null) {
-+            return handleDefaultCommands(cmd);
-+        }
-+        final PrintWriter err = getErrPrintWriter();
-+        try {
-+            switch (cmd) {
-+                case "list":
-+                    return runList();
-+                case "enable":
-+                    return runEnableDisable(true);
-+                case "disable":
-+                    return runEnableDisable(false);
-+                case "set-priority":
-+                    return runSetPriority();
-+                default:
-+                    return handleDefaultCommands(cmd);
-+            }
-+        } catch (IllegalArgumentException e) {
-+            err.println("Error: " + e.getMessage());
-+        } catch (RemoteException e) {
-+            err.println("Remote exception: " + e);
-+        }
-+        return -1;
-+    }
-+
-+    @Override
-+    public void onHelp() {
-+        final PrintWriter out = getOutPrintWriter();
-+        out.println("Overlay manager (overlay) commands:");
-+        out.println("  help");
-+        out.println("    Print this help text.");
-+        out.println("  dump [--verbose] [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
-+        out.println("    Print debugging information about the overlay manager.");
-+        out.println("  list [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
-+        out.println("    Print information about target and overlay packages.");
-+        out.println("    Overlay packages are printed in priority order. With optional");
-+        out.println("    parameters PACKAGEs, limit output to the specified packages");
-+        out.println("    but include more information about each package.");
-+        out.println("  enable [--user USER_ID] PACKAGE");
-+        out.println("    Enable overlay package PACKAGE.");
-+        out.println("  disable [--user USER_ID] PACKAGE");
-+        out.println("    Disable overlay package PACKAGE.");
-+        out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
-+        out.println("    Change the priority of the overlay PACKAGE to be just higher than");
-+        out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
-+        out.println("    'lowest', change priority of PACKAGE to the lowest priority.");
-+        out.println("    If PARENT is the special keyword 'highest', change priority of");
-+        out.println("    PACKAGE to the highest priority.");
-+    }
-+
-+    private int runList() throws RemoteException {
-+        final PrintWriter out = getOutPrintWriter();
-+        final PrintWriter err = getErrPrintWriter();
-+
-+        int userId = UserHandle.USER_SYSTEM;
-+        String opt;
-+        while ((opt = getNextOption()) != null) {
-+            switch (opt) {
-+                case "--user":
-+                    userId = UserHandle.parseUserArg(getNextArgRequired());
-+                    break;
-+                default:
-+                    err.println("Error: Unknown option: " + opt);
-+                    return 1;
-+            }
-+        }
-+
-+        final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
-+        for (final String targetPackageName : allOverlays.keySet()) {
-+            out.println(targetPackageName);
-+            for (final OverlayInfo oi : allOverlays.get(targetPackageName)) {
-+                String status = "---";
-+                if (oi.isApproved()) {
-+                    status = "[ ]";
-+                }
-+                if (oi.isEnabled()) {
-+                    status = "[x]";
-+                }
-+                out.println(String.format("%s %s", status, oi.packageName));
-+            }
-+            out.println();
-+        }
-+        return 0;
-+    }
-+
-+    private int runEnableDisable(final boolean enable) throws RemoteException {
-+        final PrintWriter err = getErrPrintWriter();
-+
-+        int userId = UserHandle.USER_SYSTEM;
-+        String opt;
-+        while ((opt = getNextOption()) != null) {
-+            switch (opt) {
-+                case "--user":
-+                    userId = UserHandle.parseUserArg(getNextArgRequired());
-+                    break;
-+                default:
-+                    err.println("Error: Unknown option: " + opt);
-+                    return 1;
-+            }
-+        }
-+
-+        final String packageName = getNextArgRequired();
-+        return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
-+    }
-+
-+    private int runSetPriority() throws RemoteException {
-+        final PrintWriter err = getErrPrintWriter();
-+
-+        int userId = UserHandle.USER_SYSTEM;
-+        String opt;
-+        while ((opt = getNextOption()) != null) {
-+            switch (opt) {
-+                case "--user":
-+                    userId = UserHandle.parseUserArg(getNextArgRequired());
-+                    break;
-+                default:
-+                    err.println("Error: Unknown option: " + opt);
-+                    return 1;
-+            }
-+        }
-+
-+        final String packageName = getNextArgRequired();
-+        final String newParentPackageName = getNextArgRequired();
-+
-+        if ("highest".equals(newParentPackageName)) {
-+            return mInterface.setHighestPriority(packageName, userId) ? 0 : 1;
-+        } else if ("lowest".equals(newParentPackageName)) {
-+            return mInterface.setLowestPriority(packageName, userId) ? 0 : 1;
-+        } else {
-+            return mInterface.setPriority(packageName, newParentPackageName, userId) ? 0 : 1;
-+        }
-+    }
-+}
-diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
-index 583cb23..3892f8f 100644
---- a/services/core/java/com/android/server/pm/PackageManagerService.java
-+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
-@@ -21444,6 +21444,47 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
-                 return mSettings.wasPackageEverLaunchedLPr(packageName, userId);
-             }
-         }
-+
-+        @Override
-+        public List<PackageInfo> getOverlayPackages(int userId) {
-+            final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
-+            synchronized (mPackages) {
-+                for (PackageParser.Package p : mPackages.values()) {
-+                    if (p.mOverlayTarget != null) {
-+                        PackageInfo pkg = generatePackageInfo((PackageSetting)p.mExtras, 0, userId);
-+                        if (pkg != null) {
-+                            overlayPackages.add(pkg);
-+                        }
-+                    }
-+                }
-+            }
-+            return overlayPackages;
-+        }
-+
-+        @Override
-+        public List<String> getTargetPackageNames(int userId) {
-+            List<String> targetPackages = new ArrayList<>();
-+            synchronized (mPackages) {
-+                for (PackageParser.Package p : mPackages.values()) {
-+                    if (p.mOverlayTarget == null) {
-+                        targetPackages.add(p.packageName);
-+                    }
-+                }
-+            }
-+            return targetPackages;
-+        }
-+
-+        @Override
-+        public void setResourceDirs(int userId, String packageName, String[] resourceDirs) {
-+            // TODO: uncomment when we integrate OMS properly
-+            // synchronized (mPackages) {
-+            //     PackageSetting ps = mSettings.mPackages.get(packageName);
-+            //     if (ps == null) {
-+            //         return;
-+            //     }
-+            //     ps.setResourceDirs(resourceDirs, userId);
-+            // }
-+        }
-     }
-     @Override
--- 
-2.9.3
-
diff --git a/frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch b/frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch
deleted file mode 100644 (file)
index 5104306..0000000
+++ /dev/null
@@ -1,1473 +0,0 @@
-From 2a5bd30d939fd04580f162115ddba6c359290b6f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Thu, 2 Jun 2016 09:35:31 +0200
-Subject: [PATCH 03/38] OMS7-N: Integrate OverlayManagerService into framework
- [3/11]
-
-Hand over ownership of overlays to OverlayManagerService.
-
-Changes to a package's overlays are propagated using the activity life
-cycle. Affected activities will be recreated as needed. This provides a
-well-defined point to modify an application's assets while the
-application is paused.
-
-Consolidate how overlays targeting the system and overlays targeting
-regular applications are handled. Previously, system overlays were
-handled as a special case. Now, everything is handled identically. As a
-side effect, the call to idmap --scan during Zygote boot has become
-obsolete and is removed.
-
-Deprecate and remove use of SCAN_TRUSTED_OVERLAY from
-PackageManagerService. Previously, the flag was used to restrict what
-paths overlays were allowed to be installed in. Now, overlay packages
-are first class packages and it is up to the OverlayManagerService to
-decide whether to use the overlay or not.
-
-Information on what overlays to use is recorded in
-ApplicationInfo.resourceDirs. The PackageManagerService is responsible
-for the creation of ApplicationInfo objects. The OverlayManagerService
-is responsible for informing the PackageManagerService in advance about
-what resourceDirs to use.
-
-When launching an application, the ApplicationInfo is already populated
-with up-to-date information about overlays.
-
-When enabling or disabling an overlay for a running application, the
-OverlayManagerService first notifies the OverlayManagerService about the
-updated resourceDirs. It then tells the ActivityManagerService to push
-the new ApplicationInfo object to the application's ActivityThread.
-Finally the application requests its ResourcesManager to create new
-ResourcesImpl objects based on the updated paths.
-
-Change-Id: If0b1eaa690c38f9c33f7c8dc981314205a73fa9c
----
- cmds/idmap/Android.mk                              |   2 +-
- cmds/idmap/idmap.cpp                               |  55 ---------
- cmds/idmap/idmap.h                                 |   6 -
- core/java/android/app/ActivityManagerNative.java   |  30 +++++
- core/java/android/app/ActivityThread.java          |  45 +++++++
- core/java/android/app/ApplicationThreadNative.java |  21 ++++
- core/java/android/app/IActivityManager.java        |   2 +
- core/java/android/app/IApplicationThread.java      |   2 +
- core/java/android/app/ResourcesManager.java        | 119 ++++++++++++++----
- core/java/android/content/pm/PackageParser.java    |  20 +--
- core/java/android/content/pm/PackageUserState.java |   6 +
- core/jni/android_util_AssetManager.cpp             |  95 ---------------
- include/androidfw/AssetManager.h                   |  15 +--
- libs/androidfw/AssetManager.cpp                    | 104 ----------------
- .../com/android/server/SystemServiceManager.java   |  24 ++--
- .../android/server/am/ActivityManagerService.java  |  51 ++++++++
- .../android/server/om/OverlayManagerService.java   |  61 +++++-----
- .../android/server/pm/PackageManagerService.java   | 134 ++++-----------------
- .../com/android/server/pm/PackageSettingBase.java  |   8 +-
- .../core/java/com/android/server/pm/Settings.java  |   4 +-
- services/java/com/android/server/SystemServer.java |   4 +
- 21 files changed, 335 insertions(+), 473 deletions(-)
-
-diff --git a/cmds/idmap/Android.mk b/cmds/idmap/Android.mk
-index 50ccb07..eb6da18 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 @@ 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\
-@@ -49,11 +47,6 @@ OPTIONS \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\
- \n\
-@@ -97,16 +90,6 @@ 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;
-@@ -167,36 +150,6 @@ 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
-@@ -235,14 +188,6 @@ 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]);
-     }
-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_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_
-diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
-index 50479c8..389f342 100644
---- a/core/java/android/app/ActivityManagerNative.java
-+++ b/core/java/android/app/ActivityManagerNative.java
-@@ -16,6 +16,7 @@
- package android.app;
-+import android.annotation.NonNull;
- import android.annotation.UserIdInt;
- import android.app.ActivityManager.StackInfo;
- import android.app.assist.AssistContent;
-@@ -1226,6 +1227,19 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
-             return true;
-         }
-+        case UPDATE_ASSETS_TRANSACTION: {
-+            data.enforceInterface(IActivityManager.descriptor);
-+            final int userId = data.readInt();
-+            final int N = data.readInt();
-+            final List<String> packageNames = new ArrayList<>();
-+            for (int i = 0; i < N; i++) {
-+                packageNames.add(data.readString());
-+            }
-+            updateAssets(userId, packageNames);
-+            reply.writeNoException();
-+            return true;
-+        }
-+
-         case SET_REQUESTED_ORIENTATION_TRANSACTION: {
-             data.enforceInterface(IActivityManager.descriptor);
-             IBinder token = data.readStrongBinder();
-@@ -4586,6 +4600,22 @@ class ActivityManagerProxy implements IActivityManager
-         data.recycle();
-         reply.recycle();
-     }
-+    public void updateAssets(final int userId, @NonNull final List<String> packageNames)
-+            throws RemoteException
-+    {
-+        final Parcel data = Parcel.obtain();
-+        final Parcel reply = Parcel.obtain();
-+        data.writeInterfaceToken(IActivityManager.descriptor);
-+        data.writeInt(userId);
-+        data.writeInt(packageNames.size());
-+        for (int i = 0; i < packageNames.size(); i++) {
-+            data.writeString(packageNames.get(i));
-+        }
-+        mRemote.transact(UPDATE_ASSETS_TRANSACTION, data, reply, 0);
-+        reply.readException();
-+        data.recycle();
-+        reply.recycle();
-+    }
-     public void setRequestedOrientation(IBinder token, int requestedOrientation)
-             throws RemoteException {
-         Parcel data = Parcel.obtain();
-diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
-index 2d22f26..55fc25d 100644
---- a/core/java/android/app/ActivityThread.java
-+++ b/core/java/android/app/ActivityThread.java
-@@ -897,6 +897,14 @@ public final class ActivityThread {
-             sendMessage(H.CONFIGURATION_CHANGED, config);
-         }
-+        public void scheduleAssetsChanged(@NonNull final String packageName,
-+                @NonNull final ApplicationInfo ai) {
-+            final SomeArgs args = SomeArgs.obtain();
-+            args.arg1 = packageName;
-+            args.arg2 = ai;
-+            sendMessage(H.ASSETS_CHANGED, args);
-+        }
-+
-         public void updateTimeZone() {
-             TimeZone.setDefault(null);
-         }
-@@ -1405,6 +1413,7 @@ public final class ActivityThread {
-         public static final int MULTI_WINDOW_MODE_CHANGED = 152;
-         public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
-         public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
-+        public static final int ASSETS_CHANGED = 155;
-         String codeToString(int code) {
-             if (DEBUG_MESSAGES) {
-@@ -1461,6 +1470,7 @@ public final class ActivityThread {
-                     case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED";
-                     case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
-                     case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
-+                    case ASSETS_CHANGED: return "ASSETS_CHANGED";
-                 }
-             }
-             return Integer.toString(code);
-@@ -1716,6 +1726,10 @@ public final class ActivityThread {
-                     handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
-                             (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
-                     break;
-+                case ASSETS_CHANGED:
-+                    handleAssetsChanged((String)((SomeArgs)msg.obj).arg1,
-+                            (ApplicationInfo)((SomeArgs)msg.obj).arg2);
-+                    break;
-             }
-             Object obj = msg.obj;
-             if (obj instanceof SomeArgs) {
-@@ -4803,6 +4817,37 @@ public final class ActivityThread {
-         }
-     }
-+    final void handleAssetsChanged(@NonNull final String packageToUpdate,
-+            @NonNull final ApplicationInfo ai) {
-+        synchronized (mResourcesManager) {
-+            // Update all affected loaded packages with new overlay package information
-+            final ArrayList<WeakReference<LoadedApk>> loadedPackages = new ArrayList<>();
-+            loadedPackages.addAll(mPackages.values());
-+            loadedPackages.addAll(mResourcePackages.values());
-+            for (final WeakReference<LoadedApk> ref : loadedPackages) {
-+                final LoadedApk apk = ref.get();
-+                if (apk != null) {
-+                    final String packageName = apk.getPackageName();
-+                    if (packageToUpdate.equals(packageName)) {
-+                        apk.updateApplicationInfo(ai, null);
-+                    }
-+                }
-+            }
-+
-+            // Update all affected Resources objects to use new ResourcesImpl
-+            mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs);
-+        }
-+
-+        // Schedule all activities to reload
-+        for (final Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
-+            final Activity activity = entry.getValue().activity;
-+            if (!activity.mFinished) {
-+                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false,
-+                        false);
-+            }
-+        }
-+    }
-+
-     static void freeTextLayoutCachesIfNeeded(int configDiff) {
-         if (configDiff != 0) {
-             // Ask text layout engine to free its caches if there is a locale change
-diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
-index 05d9d7e..47b05ee 100644
---- a/core/java/android/app/ApplicationThreadNative.java
-+++ b/core/java/android/app/ApplicationThreadNative.java
-@@ -16,6 +16,7 @@
- package android.app;
-+import android.annotation.NonNull;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.IIntentReceiver;
-@@ -331,6 +332,15 @@ public abstract class ApplicationThreadNative extends Binder
-             return true;
-         }
-+        case SCHEDULE_ASSETS_CHANGED_TRANSACTION:
-+        {
-+            data.enforceInterface(IApplicationThread.descriptor);
-+            final String packageName = data.readString();
-+            final ApplicationInfo ai = ApplicationInfo.CREATOR.createFromParcel(data);
-+            scheduleAssetsChanged(packageName, ai);
-+            return true;
-+        }
-+
-         case UPDATE_TIME_ZONE_TRANSACTION: {
-             data.enforceInterface(IApplicationThread.descriptor);
-             updateTimeZone();
-@@ -1126,6 +1136,17 @@ class ApplicationThreadProxy implements IApplicationThread {
-         data.recycle();
-     }
-+    public final void scheduleAssetsChanged(@NonNull final String packageName,
-+            @NonNull final ApplicationInfo ai) throws RemoteException {
-+        final Parcel data = Parcel.obtain();
-+        data.writeInterfaceToken(IApplicationThread.descriptor);
-+        data.writeString(packageName);
-+        ai.writeToParcel(data, 0);
-+        mRemote.transact(SCHEDULE_ASSETS_CHANGED_TRANSACTION, data, null,
-+                IBinder.FLAG_ONEWAY);
-+        data.recycle();
-+    }
-+
-     public void updateTimeZone() throws RemoteException {
-         Parcel data = Parcel.obtain();
-         data.writeInterfaceToken(IApplicationThread.descriptor);
-diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
-index 5a4470b..c7522b9 100644
---- a/core/java/android/app/IActivityManager.java
-+++ b/core/java/android/app/IActivityManager.java
-@@ -266,6 +266,7 @@ public interface IActivityManager extends IInterface {
-     public Configuration getConfiguration() throws RemoteException;
-     public void updateConfiguration(Configuration values) throws RemoteException;
-+    public void updateAssets(int userId, List<String> packageNames) throws RemoteException;
-     public void setRequestedOrientation(IBinder token,
-             int requestedOrientation) throws RemoteException;
-     public int getRequestedOrientation(IBinder token) throws RemoteException;
-@@ -1075,4 +1076,5 @@ public interface IActivityManager extends IInterface {
-     int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
-     int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
-     int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380;
-+    int UPDATE_ASSETS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 381;
- }
-diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
-index 3fa88ae..fcc97e3 100644
---- a/core/java/android/app/IApplicationThread.java
-+++ b/core/java/android/app/IApplicationThread.java
-@@ -104,6 +104,7 @@ public interface IApplicationThread extends IInterface {
-     void scheduleExit() throws RemoteException;
-     void scheduleSuicide() throws RemoteException;
-     void scheduleConfigurationChanged(Configuration config) throws RemoteException;
-+    void scheduleAssetsChanged(String packageName, ApplicationInfo ai) throws RemoteException;
-     void updateTimeZone() throws RemoteException;
-     void clearDnsCache() throws RemoteException;
-     void setHttpProxy(String proxy, String port, String exclList,
-@@ -225,4 +226,5 @@ public interface IApplicationThread extends IInterface {
-     int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
-     int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
-     int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60;
-+    int SCHEDULE_ASSETS_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61;
- }
-diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
-index 4916c1c..8cbca31 100644
---- a/core/java/android/app/ResourcesManager.java
-+++ b/core/java/android/app/ResourcesManager.java
-@@ -29,6 +29,7 @@ import android.content.res.ResourcesImpl;
- import android.content.res.ResourcesKey;
- import android.hardware.display.DisplayManagerGlobal;
- import android.os.IBinder;
-+import android.os.Process;
- import android.os.Trace;
- import android.util.ArrayMap;
- import android.util.DisplayMetrics;
-@@ -52,6 +53,8 @@ public class ResourcesManager {
-     static final String TAG = "ResourcesManager";
-     private static final boolean DEBUG = false;
-+    private static final String FRAMEWORK_RESOURCES_PATH = "/system/framework/framework-res.apk";
-+
-     private static ResourcesManager sResourcesManager;
-     /**
-@@ -916,44 +919,108 @@ public class ResourcesManager {
-                 }
-             }
--            // Bail early if there is no work to do.
--            if (updatedResourceKeys.isEmpty()) {
--                return;
-+            redirectResourcesToNewImplLocked(updatedResourceKeys);
-+        }
-+    }
-+
-+    final void applyNewResourceDirsLocked(@NonNull final String baseCodePath,
-+            @NonNull final String[] newResourceDirs) {
-+        try {
-+            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
-+                    "ResourcesManager#applyNewResourceDirsLocked");
-+
-+            ApplicationPackageManager.configurationChanged();
-+
-+            if (Process.myUid() == Process.SYSTEM_UID) {
-+                // Resources.getSystem Resources are created on request and aren't tracked by
-+                // mResourceReferences.
-+                //
-+                // If overlays targeting "android" are to be used, we must create the system
-+                // resources regardless of whether they already exist, since otherwise the
-+                // information on what overlays to use would be lost. This is wasteful for most
-+                // applications, so limit this operation to the system user only. (This means
-+                // Resources.getSystem() will *not* use overlays for applications.)
-+                if (FRAMEWORK_RESOURCES_PATH.equals(baseCodePath)) {
-+                    final ResourcesKey key = new ResourcesKey(
-+                            FRAMEWORK_RESOURCES_PATH,
-+                            null,
-+                            newResourceDirs,
-+                            null,
-+                            Display.DEFAULT_DISPLAY,
-+                            null,
-+                            null);
-+                    final ResourcesImpl impl = createResourcesImpl(key);
-+                    Resources.getSystem().setImpl(impl);
-+                }
-             }
--            // Update any references to ResourcesImpl that require reloading.
--            final int resourcesCount = mResourceReferences.size();
--            for (int i = 0; i < resourcesCount; i++) {
--                final Resources r = mResourceReferences.get(i).get();
-+
-+            final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
-+            final int implCount = mResourceImpls.size();
-+            for (int i = 0; i < implCount; i++) {
-+                final ResourcesImpl impl = mResourceImpls.valueAt(i).get();
-+                final ResourcesKey key = mResourceImpls.keyAt(i);
-+                if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
-+
-+                    updatedResourceKeys.put(impl, new ResourcesKey(
-+                            key.mResDir,
-+                            key.mSplitResDirs,
-+                            newResourceDirs,
-+                            key.mLibDirs,
-+                            key.mDisplayId,
-+                            key.mOverrideConfiguration,
-+                            key.mCompatInfo));
-+                }
-+            }
-+
-+            invalidatePath("/");
-+
-+            redirectResourcesToNewImplLocked(updatedResourceKeys);
-+        } finally {
-+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-+        }
-+    }
-+
-+    private void redirectResourcesToNewImplLocked(
-+            @NonNull final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys) {
-+
-+        // Bail early if there is no work to do.
-+        if (updatedResourceKeys.isEmpty()) {
-+            return;
-+        }
-+
-+        // Update any references to ResourcesImpl that require reloading.
-+        final int resourcesCount = mResourceReferences.size();
-+        for (int i = 0; i < resourcesCount; i++) {
-+            final Resources r = mResourceReferences.get(i).get();
-+            if (r != null) {
-+                final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
-+                if (key != null) {
-+                    final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
-+                    if (impl == null) {
-+                        throw new Resources.NotFoundException("failed to load");
-+                    }
-+                    r.setImpl(impl);
-+                }
-+            }
-+        }
-+
-+        // Update any references to ResourcesImpl that require reloading for each Activity.
-+        for (final ActivityResources activityResources : mActivityResourceReferences.values()) {
-+            final int resCount = activityResources.activityResources.size();
-+            for (int i = 0; i < resCount; i++) {
-+                final Resources r = activityResources.activityResources.get(i).get();
-                 if (r != null) {
-                     final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
-                     if (key != null) {
-                         final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
-                         if (impl == null) {
--                            throw new Resources.NotFoundException("failed to load " + libAsset);
-+                            throw new Resources.NotFoundException("failed to load");
-                         }
-                         r.setImpl(impl);
-                     }
-                 }
-             }
--
--            // Update any references to ResourcesImpl that require reloading for each Activity.
--            for (ActivityResources activityResources : mActivityResourceReferences.values()) {
--                final int resCount = activityResources.activityResources.size();
--                for (int i = 0; i < resCount; i++) {
--                    final Resources r = activityResources.activityResources.get(i).get();
--                    if (r != null) {
--                        final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
--                        if (key != null) {
--                            final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
--                            if (impl == null) {
--                                throw new Resources.NotFoundException("failed to load " + libAsset);
--                            }
--                            r.setImpl(impl);
--                        }
--                    }
--                }
--            }
-         }
-     }
- }
-diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
-index f2e3333..8d42d2c 100644
---- a/core/java/android/content/pm/PackageParser.java
-+++ b/core/java/android/content/pm/PackageParser.java
-@@ -668,10 +668,9 @@ public class PackageParser {
-     public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
-     public final static int PARSE_IS_PRIVILEGED = 1<<7;
-     public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
--    public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
--    public final static int PARSE_ENFORCE_CODE = 1<<10;
--    public final static int PARSE_IS_EPHEMERAL = 1<<11;
--    public final static int PARSE_FORCE_SDK = 1<<12;
-+    public final static int PARSE_ENFORCE_CODE = 1<<9;
-+    public final static int PARSE_IS_EPHEMERAL = 1<<10;
-+    public final static int PARSE_FORCE_SDK = 1<<11;
-     private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
-@@ -1806,9 +1805,6 @@ 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) {
-@@ -1816,14 +1812,7 @@ 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)) {
-                 if (!parseKeySets(pkg, res, parser, outError)) {
-                     return null;
-@@ -4913,8 +4902,6 @@ public class PackageParser {
-         public String mRequiredAccountType;
-         public String mOverlayTarget;
--        public int mOverlayPriority;
--        public boolean mTrustedOverlay;
-         /**
-          * Data used to feed the KeySetManagerService
-@@ -5455,6 +5442,7 @@ public class PackageParser {
-             ai.enabled = false;
-         }
-         ai.enabledSetting = state.enabled;
-+        ai.resourceDirs = state.resourceDirs;
-         if (state.protectedComponents != null) {
-             ai.protect = state.protectedComponents.size() > 0;
-         }
-diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
-index e64e4c4..4b276fb 100644
---- a/core/java/android/content/pm/PackageUserState.java
-+++ b/core/java/android/content/pm/PackageUserState.java
-@@ -31,6 +31,8 @@ import android.util.ArraySet;
- import com.android.internal.util.ArrayUtils;
-+import java.util.Arrays;
-+
- /**
-  * Per-user state information about a package.
-  * @hide
-@@ -53,6 +55,8 @@ public class PackageUserState {
-     public ArraySet<String> protectedComponents;
-     public ArraySet<String> visibleComponents;
-+    public String[] resourceDirs;
-+
-     public PackageUserState() {
-         installed = true;
-         hidden = false;
-@@ -76,6 +80,8 @@ public class PackageUserState {
-         appLinkGeneration = o.appLinkGeneration;
-         disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
-         enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
-+        resourceDirs =
-+            o.resourceDirs == null ? null : Arrays.copyOf(o.resourceDirs, o.resourceDirs.length);
-         protectedComponents = o.protectedComponents != null
-                 ? new ArraySet<String>(o.protectedComponents) : null;
-         visibleComponents = o.visibleComponents != null
-diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
-index 1a7294f..6c5a88f 100644
---- a/core/jni/android_util_AssetManager.cpp
-+++ b/core/jni/android_util_AssetManager.cpp
-@@ -129,85 +129,6 @@ 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(const char* overlay_dir)
--{
--    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[7];
--                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
--                // /vendor/overlay
--
--               if (stat(overlay_dir, &st) == 0) {
--                   argv[argc++] = overlay_dir;
--                }
--
--                // Finally, invoke idmap (if any overlay directory exists)
--                if (argc > 5) {
--                    execv(AssetManager::IDMAP_BIN, (char* const*)argv);
--                    ALOGE("failed to execl 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
-@@ -2078,22 +1999,6 @@ static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jo
- static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
- {
--    if (isSystem) {
--        // Load frameworks-res.apk's overlay through regionalization environment
--        if (Environment::isSupported()) {
--            Environment* environment = new Environment();
--            if (environment != NULL) {
--                const char* overlay_dir = environment->getOverlayDir();
--                if (overlay_dir != NULL && strcmp(overlay_dir, "") != 0) {
--                    ALOGD("Regionalization - getOverlayDir:%s", overlay_dir);
--                    verifySystemIdmaps(overlay_dir);
--                }
--                delete environment;
--            }
--        }
--
--        verifySystemIdmaps(AssetManager::OVERLAY_DIR);
--    }
-     AssetManager* am = new AssetManager();
-     if (am == NULL) {
-         jniThrowException(env, "java/lang/OutOfMemoryError", "");
-diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
-index 914ac3d..651765b 100644
---- a/include/androidfw/AssetManager.h
-+++ b/include/androidfw/AssetManager.h
-@@ -238,12 +238,10 @@ public:
- 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;
-     };
-@@ -288,9 +286,6 @@ 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);
-@@ -305,9 +300,6 @@ private:
-         
-         bool isUpToDate();
--        void addOverlay(const asset_path& ap);
--        bool getOverlay(size_t idx, asset_path* out) const;
--        
-     protected:
-         ~SharedZip();
-@@ -322,8 +314,6 @@ private:
-         Asset* mResourceTableAsset;
-         ResTable* mResourceTable;
--        Vector<asset_path> mOverlays;
--
-         static Mutex gLock;
-         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
-     };
-@@ -356,9 +346,6 @@ private:
-         static String8 getPathName(const char* path);
-         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/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
-index edc625b..924b230 100644
---- a/libs/androidfw/AssetManager.cpp
-+++ b/libs/androidfw/AssetManager.cpp
-@@ -214,15 +214,6 @@ 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);
-     }
-@@ -606,11 +597,6 @@ 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;
-@@ -652,14 +638,6 @@ 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);
-             }
-@@ -772,58 +750,6 @@ 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);
-@@ -1962,20 +1888,6 @@ 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) {
-@@ -2101,22 +2013,6 @@ 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.
-  *
-diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
-index 90f507c..904c967 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;
-@@ -104,22 +105,25 @@ public class SystemServiceManager {
-                         + ": 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 e31b409..2822dc9 100644
---- a/services/core/java/com/android/server/am/ActivityManagerService.java
-+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
-@@ -19297,6 +19297,57 @@ public final class ActivityManagerService extends ActivityManagerNative
-     }
-     /**
-+     * @hide
-+     */
-+    @Override
-+    public void updateAssets(final int userId, @NonNull final List<String> packageNames) {
-+        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateAssets()");
-+
-+        synchronized(this) {
-+            final long origId = Binder.clearCallingIdentity();
-+            try {
-+                updateAssetsLocked(userId, packageNames);
-+            } finally {
-+                Binder.restoreCallingIdentity(origId);
-+            }
-+        }
-+    }
-+
-+    void updateAssetsLocked(final int userId, @NonNull final List<String> packagesToUpdate) {
-+        final IPackageManager pm = AppGlobals.getPackageManager();
-+        final Map<String, ApplicationInfo> cache = new ArrayMap<>();
-+
-+        final boolean updateFrameworkRes = packagesToUpdate.contains("android");
-+        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
-+            final ProcessRecord app = mLruProcesses.get(i);
-+            if (app.userId != userId || app.thread == null) {
-+                continue;
-+            }
-+
-+            for (final String packageName : app.pkgList.keySet()) {
-+                if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
-+                    try {
-+                        final ApplicationInfo ai;
-+                        if (cache.containsKey(packageName)) {
-+                            ai = cache.get(packageName);
-+                        } else {
-+                            ai = pm.getApplicationInfo(packageName, 0, userId);
-+                            cache.put(packageName, ai);
-+                        }
-+
-+                        if (ai != null) {
-+                            app.thread.scheduleAssetsChanged(packageName, ai);
-+                        }
-+                    } catch (RemoteException e) {
-+                        Slog.w(TAG, String.format("Failed to update %s assets for %s",
-+                                    packageName, app));
-+                    }
-+                }
-+            }
-+        }
-+    }
-+
-+    /**
-      * Decide based on the configuration whether we should shouw the ANR,
-      * crash, etc dialogs.  The idea is that if there is no affordence to
-      * press the on-screen buttons, or the user experience would be more
-diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
-index ec148dd..761ef52 100644
---- a/services/core/java/com/android/server/om/OverlayManagerService.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
-@@ -676,37 +676,36 @@ public final class OverlayManagerService extends SystemService {
-     }
-     private void updateAssets(final int userId, List<String> targetPackageNames) {
--        // TODO: uncomment 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, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
--        // synchronized (mLock) {
--        //     final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
--        //     for (final String packageName : targetPackageNames) {
--        //         final List<String> paths = new ArrayList<>();
--        //         paths.addAll(frameworkPaths);
--        //         if (!"android".equals(packageName)) {
--        //             paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
--        //         }
--        //         allPaths.put(packageName,
--        //             paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
--        //     }
--        // }
--
--        // for (String packageName : targetPackageNames) {
--        //     pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
--        // }
--
--        // final IActivityManager am = ActivityManagerNative.getDefault();
--        // try {
--        //     am.updateAssets(userId, targetPackageNames);
--        // } catch (RemoteException e) {
--        //     // Intentionally left empty.
--        // }
-+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
-+        final boolean updateFrameworkRes = targetPackageNames.contains("android");
-+        if (updateFrameworkRes) {
-+            targetPackageNames = pm.getTargetPackageNames(userId);
-+        }
-+
-+        final Map<String, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
-+        synchronized (mLock) {
-+            final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
-+            for (final String packageName : targetPackageNames) {
-+                final List<String> paths = new ArrayList<>();
-+                paths.addAll(frameworkPaths);
-+                if (!"android".equals(packageName)) {
-+                    paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
-+                }
-+                allPaths.put(packageName,
-+                    paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
-+            }
-+        }
-+
-+        for (String packageName : targetPackageNames) {
-+            pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
-+        }
-+
-+        final IActivityManager am = ActivityManagerNative.getDefault();
-+        try {
-+            am.updateAssets(userId, targetPackageNames);
-+        } 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 3892f8f..f700522 100644
---- a/services/core/java/com/android/server/pm/PackageManagerService.java
-+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
-@@ -399,17 +399,16 @@ public class PackageManagerService extends IPackageManager.Stub {
-     static final int SCAN_UPDATE_TIME = 1<<6;
-     static final int SCAN_DEFER_DEX = 1<<7;
-     static final int SCAN_BOOTING = 1<<8;
--    static final int SCAN_TRUSTED_OVERLAY = 1<<9;
--    static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
--    static final int SCAN_REPLACING = 1<<11;
--    static final int SCAN_REQUIRE_KNOWN = 1<<12;
--    static final int SCAN_MOVE = 1<<13;
--    static final int SCAN_INITIAL = 1<<14;
--    static final int SCAN_CHECK_ONLY = 1<<15;
--    static final int SCAN_DONT_KILL_APP = 1<<17;
--    static final int SCAN_IGNORE_FROZEN = 1<<18;
--
--    static final int REMOVE_CHATTY = 1<<16;
-+    static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<9;
-+    static final int SCAN_REPLACING = 1<<10;
-+    static final int SCAN_REQUIRE_KNOWN = 1<<11;
-+    static final int SCAN_MOVE = 1<<12;
-+    static final int SCAN_INITIAL = 1<<13;
-+    static final int SCAN_CHECK_ONLY = 1<<14;
-+    static final int SCAN_DONT_KILL_APP = 1<<15;
-+    static final int SCAN_IGNORE_FROZEN = 1<<16;
-+
-+    static final int REMOVE_CHATTY = 1<<17;
-     private static final int[] EMPTY_INT_ARRAY = new int[0];
-@@ -600,10 +599,6 @@ public class PackageManagerService extends IPackageManager.Stub {
-     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>>();
--
-     /**
-      * Tracks new system packages [received in an OTA] that we expect to
-      * find updated user-installed versions. Keys are package name, values
-@@ -2342,8 +2337,8 @@ public class PackageManagerService extends IPackageManager.Stub {
-             File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
-             scanDirTracedLI(vendorOverlayDir, mDefParseFlags
-                     | PackageParser.PARSE_IS_SYSTEM
--                    | PackageParser.PARSE_IS_SYSTEM_DIR
--                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
-+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
-+                    scanFlags, 0);
-             // Find base frameworks (resource packages without code).
-             scanDirTracedLI(frameworkDir, mDefParseFlags
-@@ -2400,7 +2395,7 @@ public class PackageManagerService extends IPackageManager.Stub {
-                     // Collect overlay in <Package>/system/vendor
-                     scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
-                             PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
--                            scanFlags | SCAN_TRUSTED_OVERLAY, 0);
-+                            scanFlags, 0);
-                 }
-             }
-@@ -6723,60 +6718,6 @@ 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");
-         try {
-@@ -6964,10 +6905,6 @@ public class PackageManagerService extends IPackageManager.Stub {
-         pp.setOnlyPowerOffAlarmApps(mOnlyPowerOffAlarm);
-         pp.setDisplayMetrics(mMetrics);
--        if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
--            parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
--        }
--
-         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
-         final PackageParser.Package pkg;
-         try {
-@@ -8200,7 +8137,6 @@ public class PackageManagerService extends IPackageManager.Stub {
-             pkg.applicationInfo.privateFlags &=
-                     ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
-         }
--        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
-         if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
-             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-@@ -8795,7 +8731,6 @@ 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
-@@ -9142,36 +9077,10 @@ public class PackageManagerService extends IPackageManager.Stub {
-             }
-             pkgSetting.setTimeStamp(scanFileTime);
--
--            // 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");
--        }
-         return pkg;
-     }
-@@ -16618,7 +16527,7 @@ public class PackageManagerService extends IPackageManager.Stub {
-                     false /*hidden*/, false /*suspended*/, null, null, null,
-                     false /*blockUninstall*/,
-                     ps.readUserState(nextUserId).domainVerificationStatus, 0,
--                    null, null);
-+                    null, null, null);
-         }
-     }
-@@ -21476,14 +21385,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
-         @Override
-         public void setResourceDirs(int userId, String packageName, String[] resourceDirs) {
--            // TODO: uncomment when we integrate OMS properly
--            // synchronized (mPackages) {
--            //     PackageSetting ps = mSettings.mPackages.get(packageName);
--            //     if (ps == null) {
--            //         return;
--            //     }
--            //     ps.setResourceDirs(resourceDirs, userId);
--            // }
-+            synchronized (mPackages) {
-+                final PackageSetting ps = mSettings.mPackages.get(packageName);
-+                if (ps == null) {
-+                    return;
-+                }
-+                ps.setResourceDirs(resourceDirs, userId);
-+            }
-         }
-     }
-diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
-index 75427a8..18c79cd 100644
---- a/services/core/java/com/android/server/pm/PackageSettingBase.java
-+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
-@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
- import static android.content.pm.PackageManager.COMPONENT_VISIBLE_STATUS;
-+import android.annotation.NonNull;
- import android.content.pm.IntentFilterVerificationInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.PackageUserState;
-@@ -379,7 +380,7 @@ abstract class PackageSettingBase extends SettingBase {
-             boolean notLaunched, boolean hidden, boolean suspended,
-             String lastDisableAppCaller, ArraySet<String> enabledComponents,
-             ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
--            int linkGeneration,
-+            int linkGeneration, String[] resourceDirs,
-             ArraySet<String> protectedComponents, ArraySet<String> visibleComponents) {
-         PackageUserState state = modifyUserState(userId);
-         state.ceDataInode = ceDataInode;
-@@ -395,6 +396,7 @@ abstract class PackageSettingBase extends SettingBase {
-         state.blockUninstall = blockUninstall;
-         state.domainVerificationStatus = domainVerifState;
-         state.appLinkGeneration = linkGeneration;
-+        state.resourceDirs = resourceDirs;
-         state.protectedComponents = protectedComponents;
-         state.visibleComponents = visibleComponents;
-     }
-@@ -455,6 +457,10 @@ abstract class PackageSettingBase extends SettingBase {
-         modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
-     }
-+    void setResourceDirs(@NonNull final String[] resourceDirs, final int userId) {
-+        modifyUserState(userId).resourceDirs = resourceDirs;
-+    }
-+
-     boolean enableComponentLPw(String componentClassName, int userId) {
-         PackageUserState state = modifyUserStateComponents(userId, false, true);
-         boolean changed = state.disabledComponents != null
-diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
-index 285b5bb..2b36e0e 100755
---- a/services/core/java/com/android/server/pm/Settings.java
-+++ b/services/core/java/com/android/server/pm/Settings.java
-@@ -813,6 +813,7 @@ final class Settings {
-                                     false, // blockUninstall
-                                     INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
-                                     null,
-+                                    null,
-                                     null
-                                     );
-                             writePackageRestrictionsLPr(user.id);
-@@ -1617,6 +1618,7 @@ final class Settings {
-                                 false, // blockUninstall
-                                 INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
-                                 null,
-+                                null,
-                                 null
-                                 );
-                     }
-@@ -1726,7 +1728,7 @@ final class Settings {
-                     ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
-                             hidden, suspended, enabledCaller, enabledComponents, disabledComponents,
--                            blockUninstall, verifState, linkGeneration,
-+                            blockUninstall, verifState, linkGeneration, null,
-                             protectedComponents, visibleComponents);
-                 } else if (tagName.equals("preferred-activities")) {
-                     readPreferredActivitiesLPw(parser, userId);
-diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
-index 3e16338..010aaa1 100644
---- a/services/java/com/android/server/SystemServer.java
-+++ b/services/java/com/android/server/SystemServer.java
-@@ -84,6 +84,7 @@ 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.RegionalizationService;
- import com.android.server.os.SchedulingPolicyService;
- import com.android.server.pm.BackgroundDexOptService;
-@@ -530,6 +531,9 @@ public final class SystemServer {
-         // Set up the Application instance for the system process and get started.
-         mActivityManagerService.setSystemProcess();
-+        // Manages Overlay packages
-+        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
-+
-         // The sensor service needs access to package manager service, app ops
-         // service, and permissions service, therefore we start it after them.
-         startSensorService();
--- 
-2.9.3
-
diff --git a/frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch b/frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch
deleted file mode 100644 (file)
index 5ce4094..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 06912868733feadee85507d9f40ede2468a9a496 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Mon, 25 Apr 2016 16:29:22 +0200
-Subject: [PATCH 04/38] OMS7-N: Set EXTRA_REPLACING correctly in
- ACTION_PACKAGE_ADDED [4/11]
-
-When broadcasting ACTION_PACKAGE_ADDED the recipients of the Intent are
-split into two groups: the first group hasn't seen the new package
-before and the Intent should have EXTRA_REPLACING set to false; and vice
-versa for the second group.
-
-The package manager schedules these Intent broadcasts on a background
-thread by posting Runnable objects to a handler. Each Runnable holds
-references to objects used to construct the Intents, one of which is a
-Bundle used to create the Intent extras.
-
-If the same Bundle object is used for both recipient groups, any
-modification to the object made for one group will unintentionally
-propagate to the other. To prevent this a separate Bundle is now created
-for each group.
-
-Prior to this patch, the following scenario would fail:
-
-  1. Install a package P for user owner
-  2. Create and switch to a secondary user
-  3. Install a new version of package P (for all users)
-
-In step 3, the secondary user was expected to receive
-ACTION_PACKAGE_ADDED with EXTRA_REPLACING set to false, but instead it
-was set to true. The bug was initially introduced in commit bd0e9e49.
-
-Change-Id: Icf869013d5d652de4bf0f6df4529b7a68d35a25c
----
- services/core/java/com/android/server/pm/PackageManagerService.java | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
-index f700522..7277f6a 100644
---- a/services/core/java/com/android/server/pm/PackageManagerService.java
-+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
-@@ -1714,6 +1714,7 @@ public class PackageManagerService extends IPackageManager.Stub {
-                 // Send added for users that don't see the package for the first time
-                 if (update) {
-+                    extras = new Bundle(extras);
-                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
-                 }
-                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
--- 
-2.9.3
-
diff --git a/frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch b/frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch
deleted file mode 100644 (file)
index 31ebb89..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From ee6f42041d3c77be1151d82898ee5626633cf9fa Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Mon, 29 Feb 2016 14:12:35 +0100
-Subject: [PATCH 05/38] OMS7-N: idmap: suppress print for padded resources
- [5/11]
-
-Change-Id: I565ccf515068b96927e4317cc9c06543415bb324
----
- cmds/idmap/inspect.cpp | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
-index 924090f..cb52a39 100644
---- a/cmds/idmap/inspect.cpp
-+++ b/cmds/idmap/inspect.cpp
-@@ -289,7 +289,9 @@ namespace {
-                 if (err != NO_ERROR) {
-                     return err;
-                 }
--                print("", "entry", data32, "%s/%s", type.string(), name.string());
-+                if (data32 != ResTable_type::NO_ENTRY) {
-+                    print("", "entry", data32, "%s/%s", type.string(), name.string());
-+                }
-             }
-         }
--- 
-2.9.3
-
diff --git a/frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch b/frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch
deleted file mode 100644 (file)
index 9eb37d8..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From a2ce720b5bfca010dc28ab9cd79e9a8d94f981b3 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Thu, 2 Jun 2016 09:34:36 +0200
-Subject: [PATCH 06/38] OMS7-N: Fix memory leak during idmap creation [6/11]
-
-Plug a memory leak in AssetManager::createIdmap.
-
-Change-Id: Ieed805c596df931e2167ebb47c1b2907d6bf67f4
----
- libs/androidfw/AssetManager.cpp | 38 +++++++++++++++++++++++++-------------
- 1 file changed, 25 insertions(+), 13 deletions(-)
-
-diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
-index 924b230..c501e8b 100644
---- a/libs/androidfw/AssetManager.cpp
-+++ b/libs/androidfw/AssetManager.cpp
-@@ -291,22 +291,34 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk
- {
-     AutoMutex _l(mLock);
-     const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
--    ResTable tables[2];
--
--    for (int i = 0; i < 2; ++i) {
--        asset_path ap;
--        ap.type = kFileTypeRegular;
--        ap.path = paths[i];
--        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
--        if (ass == NULL) {
--            ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
--            return false;
-+    Asset* assets[2] = {NULL, NULL};
-+    bool ret = false;
-+    {
-+        ResTable tables[2];
-+
-+        for (int i = 0; i < 2; ++i) {
-+            asset_path ap;
-+            ap.type = kFileTypeRegular;
-+            ap.path = paths[i];
-+            assets[i] = openNonAssetInPathLocked("resources.arsc",
-+                    Asset::ACCESS_BUFFER, ap);
-+            if (assets[i] == NULL) {
-+                ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
-+                goto exit;
-+            }
-+            if (tables[i].add(assets[i]) != NO_ERROR) {
-+                ALOGW("failed to add %s to resource table", paths[i].string());
-+                goto exit;
-+            }
-         }
--        tables[i].add(ass);
-+        ret = tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
-+                targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
-     }
--    return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
--            targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
-+exit:
-+    delete assets[0];
-+    delete assets[1];
-+    return ret;
- }
- bool AssetManager::addDefaultAssets()
--- 
-2.9.3
-
diff --git a/frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch b/frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch
deleted file mode 100644 (file)
index 209f9e3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From b14c245ca8e1b2fa9665ef8cde29eeafaeba282f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Thu, 2 Jun 2016 09:35:09 +0200
-Subject: [PATCH 07/38] OMS7-N: installd: add command 'rmidmap' [7/11]
-
-Add an installd command to remove an idmap file. This is the inverse of
-the 'idmap' command and is intended for clean-up once an idmap file is
-no longer needed because an APK was removed, etc.
-
-This commit depends on a corresponding commit in frameworks/native (with
-the same Change-Id).
-
-Change-Id: I58f55f643da99c0bd69136ee43c1c8c70c352797
----
- services/core/java/com/android/server/pm/Installer.java | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
-index 2e18b1c..7f618b8 100644
---- a/services/core/java/com/android/server/pm/Installer.java
-+++ b/services/core/java/com/android/server/pm/Installer.java
-@@ -170,6 +170,13 @@ public final class Installer extends SystemService {
-         mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
-     }
-+    public void removeIdmap(String overlayApkPath) throws InstallerException {
-+        StringBuilder builder = new StringBuilder("rmidmap");
-+        builder.append(' ');
-+        builder.append(overlayApkPath);
-+        mInstaller.execute(builder.toString());
-+    }
-+
-     public void rmdex(String codePath, String instructionSet) throws InstallerException {
-         assertValidInstructionSet(instructionSet);
-         mInstaller.execute("rmdex", codePath, instructionSet);
--- 
-2.9.3
-
diff --git a/frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch b/frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch
deleted file mode 100644 (file)
index fd22568..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 5e8fc3854ee67ed15983c460b390d0cff1dde775 Mon Sep 17 00:00:00 2001
-From: Josh Guilfoyle <Josh.Guilfoyle@T-Mobile.com>
-Date: Wed, 26 Jan 2011 23:28:43 -0800
-Subject: [PATCH 08/38] OMS7-N: Disable Zygote preloaded drawables [8/11]
-
-With a theme applied, most of these preloaded drawables go unused.  Any
-assets the theme has redirected will need to be loaded with each app
-process regardless.  Worse, preloads make it impossible to do asset
-redirection for constituent parts of a preloaded drawable (for instance,
-individual states of a StateListDrawable cannot be redirected).
-
-Some day it might be nice to revisit this and see if there's a way to
-reintroduce the drawable cache in a way that can be altered at runtime
-without significant complexity or runtime penalty.
-
-Change-Id: I253b1a22482ac664c196533a4c2fcd88ae84b996
----
- core/java/com/android/internal/os/ZygoteInit.java | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
-index 20f84b5..455849e 100644
---- a/core/java/com/android/internal/os/ZygoteInit.java
-+++ b/core/java/com/android/internal/os/ZygoteInit.java
-@@ -108,7 +108,7 @@ public class ZygoteInit {
-     private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
-     /** Controls whether we should preload resources during zygote init. */
--    public static final boolean PRELOAD_RESOURCES = true;
-+    public static final boolean PRELOAD_RESOURCES = false;
-     /**
-      * Registers a server socket for zygote command connections
-@@ -437,6 +437,8 @@ public class ZygoteInit {
-                     Log.i(TAG, "...preloaded " + N + " resource in "
-                             + (SystemClock.uptimeMillis() - startTime) + "ms.");
-                 }
-+            } else {
-+                Log.i(TAG, "Preload resources disabled, skipped.");
-             }
-             mResources.finishPreloading();
-         } catch (RuntimeException e) {
--- 
-2.9.3
-
diff --git a/frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch b/frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch
deleted file mode 100644 (file)
index 16c58d4..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From fc7d694af82449a4d4a3456ffd486a5afa30a2ef Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Sun, 19 Jun 2016 10:37:13 -0400
-Subject: [PATCH 09/38] OMS7-N: Persistence on boot through
- OverlayManagerServiceImpl [9/11]
-
-Overlays should not be enforced by the traditional OverlayManagerService
-by Sony, but instead, it shouldn't be enforced at all to allow third
-party overlays from the community to boot up with the device.
-
-Change-Id: Ic6eeb38b5e7bcec4211405d4504ba37a75738227
----
- .../server/om/OverlayManagerServiceImpl.java       | 31 +++++++++++++++-------
- 1 file changed, 21 insertions(+), 10 deletions(-)
-
-diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-index 2a0d88b..4c61968 100644
---- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-@@ -402,34 +402,45 @@ final class OverlayManagerServiceImpl {
-     private int calculateNewState(@Nullable final PackageInfo targetPackage,
-             @NonNull final PackageInfo overlayPackage, final int userId)
-         throws OverlayManagerSettings.BadKeyException {
-+
-+        // STATE 0 CHECK: Check if the overlay package is disabled by PackageManager
-         if (!overlayPackage.applicationInfo.enabled) {
-             return STATE_NOT_APPROVED_COMPONENT_DISABLED;
-         }
-+        // OVERLAY STATE CHECK: Check the current overlay's activation
-+        boolean stateCheck = mSettings.getEnabled(overlayPackage.packageName, userId);
-+
-+        // STATE 1 CHECK: Check if the overlay's target package is missing from the device
-         if (targetPackage == null) {
-             return STATE_NOT_APPROVED_MISSING_TARGET;
-         }
-+        // STATE 2 CHECK: Check if the overlay has an existing idmap file created. Perhaps
-+        // there were no matching resources between the two packages? (Overlay & Target)
-         if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
-             return STATE_NOT_APPROVED_NO_IDMAP;
-         }
--        final boolean enableIfApproved = mSettings.getEnabled(overlayPackage.packageName, userId);
--
--        if (mPackageManager.signaturesMatching(targetPackage.packageName,
--                    overlayPackage.packageName, userId)) {
--            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
--        }
--
-+        // STATE 6 CHECK: System Overlays, also known as RRO overlay files, work the same
-+        // as OMS, but with enable/disable limitations. A system overlay resides in the
-+        // directory "/vendor/overlay" depending on your device.
-+        //
-+        // Team Substratum: Disable this as this is a security vulnerability and a
-+        // memory-limited partition.
-         if ((overlayPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
--            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-+            return STATE_NOT_APPROVED_COMPONENT_DISABLED;
-         }
-+        // STATE 3 CHECK: If the overlay only modifies resources explicitly granted by the
-+        // target, we approve it.
-+        //
-+        // Team Substratum: Always approve dangerous packages but disabled state
-         if (!mIdmapManager.isDangerous(overlayPackage, userId)) {
--            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-+            return STATE_APPROVED_DISABLED;
-         }
--        return STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
-+        return stateCheck ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
-     }
-     private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
--- 
-2.9.3
-
diff --git a/frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch b/frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch
deleted file mode 100644 (file)
index abf34be..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From c41b5f7552e5ef1f221d1f755b37501037463c66 Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Thu, 27 Oct 2016 07:08:00 +0200
-Subject: [PATCH 10/38] OMS7-N: Do not enforce code policy limiting overlay
- installation [10/11]
-
-Change-Id: Iea317f3771f25dbfcbf4938e88cace12fd97d7eb
----
- services/core/java/com/android/server/pm/PackageManagerService.java | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
-index 7277f6a..46679e5 100644
---- a/services/core/java/com/android/server/pm/PackageManagerService.java
-+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
-@@ -8143,10 +8143,6 @@ public class PackageManagerService extends IPackageManager.Stub {
-             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-         }
--        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
--            enforceCodePolicy(pkg);
--        }
--
-         if (mCustomResolverComponentName != null &&
-                 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
-             setUpCustomResolverActivity(pkg);
--- 
-2.9.3
-
diff --git a/frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch b/frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch
deleted file mode 100644 (file)
index c155b92..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-From 61a04ac0c542521026b925d35faf4244e6ea2810 Mon Sep 17 00:00:00 2001
-From: Jacob McSwain <jacob.a.mcswain@gmail.com>
-Date: Sun, 26 Jun 2016 15:21:52 -0500
-Subject: [PATCH 11/38] OMS7-N: Implement multi-target enable/disable and
- disable-all [11/11]
-
-Just use the enable option like normal, but you can add more arguments
-for more packages. Also add a feature that allows the client to disable
-all of the current user's overlays.
-
-Multiple targets example:
-    om enable android.AkZent com.android.systemui.AkZent
-
-Works the same as:
-    om enable android.AkZent && om enable com.android.systemui.AkZent
-
-Original implementation for M by @USA-RedDragon
-Current and further development by @nicholaschum
-
-Change-Id: I04a595084a87b8260b5c534c4f5f111adbe154d7
----
- core/java/android/content/om/IOverlayManager.aidl  |  10 +-
- .../android/server/om/OverlayManagerService.java   |  48 ++++++----
- .../server/om/OverlayManagerServiceImpl.java       |  12 ++-
- .../android/server/om/OverlayManagerSettings.java  |  31 +++---
- .../server/om/OverlayManagerShellCommand.java      | 104 +++++++++++++++++++--
- 5 files changed, 161 insertions(+), 44 deletions(-)
-
-diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
-index 4f5d960..8e349dc 100644
---- a/core/java/android/content/om/IOverlayManager.aidl
-+++ b/core/java/android/content/om/IOverlayManager.aidl
-@@ -83,10 +83,12 @@ interface IOverlayManager {
-      * @param packageName The name of the overlay package.
-      * @param enable true to enable the overlay, false to disable it.
-      * @param userId The user for which to change the overlay.
-+     * @param shouldWait true to wait to reload resources until refresh is called
-      * @return true if the system successfully registered the request, false
-      *         otherwise.
-      */
--    boolean setEnabled(in String packageName, in boolean enable, in int userId);
-+    boolean setEnabled(in String packageName, in boolean enable, in int userId,
-+                       in boolean shouldWait);
-     /**
-      * Change the priority of the given overlay to be just higher than the
-@@ -126,4 +128,10 @@ interface IOverlayManager {
-      * @param userId The user for which to change the overlay.
-      */
-     boolean setLowestPriority(in String packageName, in int userId);
-+
-+    /**
-+     * Refresh assets
-+     * @param uid the user to refresh assets for
-+     */
-+    void refresh(in int uid);
- }
-diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
-index 761ef52..deb9046 100644
---- a/services/core/java/com/android/server/om/OverlayManagerService.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
-@@ -255,7 +255,7 @@ public final class OverlayManagerService extends SystemService {
-         synchronized (mLock) {
-             targets = mImpl.onSwitchUser(newUserId);
-         }
--        updateAssets(newUserId, targets);
-+        updateSelectedAssets(newUserId, targets);
-     }
-     public List<String> getEnabledOverlayPaths(@NonNull final String packageName,
-@@ -451,7 +451,7 @@ public final class OverlayManagerService extends SystemService {
-         @Override
-         public boolean setEnabled(@Nullable final String packageName, final boolean enable,
--                int userId) throws RemoteException {
-+                int userId, final boolean shouldWait) throws RemoteException {
-             enforceChangeConfigurationPermission("setEnabled");
-             userId = handleIncomingUser(userId, "setEnabled");
-             if (packageName == null) {
-@@ -461,7 +461,7 @@ public final class OverlayManagerService extends SystemService {
-             final long ident = Binder.clearCallingIdentity();
-             try {
-                 synchronized (mLock) {
--                    return mImpl.onSetEnabled(packageName, enable, userId);
-+                    return mImpl.onSetEnabled(packageName, enable, userId, shouldWait);
-                 }
-             } finally {
-                 Binder.restoreCallingIdentity(ident);
-@@ -590,6 +590,15 @@ public final class OverlayManagerService extends SystemService {
-                         message);
-             }
-         }
-+
-+        public void refresh(int uid) {
-+            Collection<String> targets;
-+            synchronized (mLock) {
-+                targets = mImpl.onSwitchUser(uid);
-+            }
-+            List targeted = new ArrayList(targets);
-+            updateSelectedAssets(uid, targeted);
-+        }
-     };
-     private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
-@@ -603,45 +612,48 @@ public final class OverlayManagerService extends SystemService {
-         }
-         @Override
--        public void onOverlayAdded(@NonNull final OverlayInfo oi) {
--            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
-+        public void onOverlayAdded(@NonNull final OverlayInfo oi, final boolean shouldWait) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled(), shouldWait);
-         }
-         @Override
--        public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
--            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
-+        public void onOverlayRemoved(@NonNull final OverlayInfo oi, final boolean shouldWait) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled(), shouldWait);
-         }
-         @Override
--        public void onOverlayChanged(@NonNull final OverlayInfo oi,
--                @NonNull final OverlayInfo oldOi) {
--            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
-+        public void onOverlayChanged(@NonNull final OverlayInfo oi, @NonNull OverlayInfo oldOi,
-+                final boolean shouldWait) {
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi,
-+                    oi.isEnabled() != oldOi.isEnabled(), shouldWait);
-         }
-         @Override
-         public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
--            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
-+            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled(), false);
-         }
-         private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
--                final boolean doUpdate) {
--            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
-+                final boolean doUpdate, final boolean shouldWait) {
-+            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate, shouldWait));
-         }
-         private final class BroadcastRunnable extends Thread {
-             private final String mAction;
-             private final OverlayInfo mOverlayInfo;
-             private final boolean mDoUpdate;
-+            private final boolean shouldWait;
--            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
--                    final boolean doUpdate) {
-+            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi, 
-+                    final boolean doUpdate, final boolean shouldWait) {
-                 mAction = action;
-                 mOverlayInfo = oi;
-                 mDoUpdate = doUpdate;
-+                this.shouldWait = shouldWait;
-             }
-             public void run() {
--                if (mDoUpdate) {
-+                if (mDoUpdate && !shouldWait) {
-                     updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
-                 }
-                 sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
-@@ -672,10 +684,10 @@ public final class OverlayManagerService extends SystemService {
-     private void updateAssets(final int userId, final String targetPackageName) {
-         final List<String> list = new ArrayList<>();
-         list.add(targetPackageName);
--        updateAssets(userId, list);
-+        updateSelectedAssets(userId, list);
-     }
--    private void updateAssets(final int userId, List<String> targetPackageNames) {
-+    private void updateSelectedAssets(final int userId, List<String> targetPackageNames) {
-         final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
-         final boolean updateFrameworkRes = targetPackageNames.contains("android");
-         if (updateFrameworkRes) {
-diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-index 4c61968..c515640 100644
---- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
-@@ -324,7 +324,7 @@ final class OverlayManagerServiceImpl {
-     }
-     boolean onSetEnabled(@NonNull final String packageName, final boolean enable,
--            final int userId) {
-+            final int userId, final boolean shouldWait) {
-         if (DEBUG) {
-             Slog.d(TAG, String.format("onSetEnabled packageName=%s enable=%s userId=%d",
-                         packageName, enable, userId));
-@@ -340,7 +340,7 @@ final class OverlayManagerServiceImpl {
-             final PackageInfo targetPackage =
-                 mPackageManager.getPackageInfo(oi.targetPackageName, userId);
-             mSettings.setEnabled(packageName, userId, enable);
--            updateState(targetPackage, overlayPackage, userId);
-+            updateState(targetPackage, overlayPackage, userId, shouldWait);
-             return true;
-         } catch (OverlayManagerSettings.BadKeyException e) {
-             return false;
-@@ -379,6 +379,12 @@ final class OverlayManagerServiceImpl {
-     private void updateState(@Nullable final PackageInfo targetPackage,
-             @NonNull final PackageInfo overlayPackage, final int userId)
-         throws OverlayManagerSettings.BadKeyException {
-+        updateState(targetPackage, overlayPackage, userId, false);
-+    }
-+
-+    private void updateState(@Nullable final PackageInfo targetPackage,
-+            @NonNull final PackageInfo overlayPackage, final int userId,
-+            final boolean shouldWait) throws OverlayManagerSettings.BadKeyException {
-         if (targetPackage != null) {
-             mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
-         }
-@@ -395,7 +401,7 @@ final class OverlayManagerServiceImpl {
-                             OverlayInfo.stateToString(currentState),
-                             OverlayInfo.stateToString(newState)));
-             }
--            mSettings.setState(overlayPackage.packageName, userId, newState);
-+            mSettings.setState(overlayPackage.packageName, userId, newState, shouldWait);
-         }
-     }
-diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
-index af0bb64..935ea02 100644
---- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
-@@ -76,7 +76,7 @@ final class OverlayManagerSettings {
-         final OverlayInfo oi = item.getOverlayInfo();
-         mItems.remove(item);
-         if (oi != null) {
--            notifyOverlayRemoved(oi);
-+            notifyOverlayRemoved(oi, false);
-         }
-     }
-@@ -135,7 +135,7 @@ final class OverlayManagerSettings {
-             final OverlayInfo oi = item.getOverlayInfo();
-             item.setUpgrading(true);
-             item.setState(STATE_NOT_APPROVED_UNKNOWN);
--            notifyOverlayRemoved(oi);
-+            notifyOverlayRemoved(oi, false);
-         } else {
-             item.setUpgrading(false);
-         }
-@@ -172,8 +172,8 @@ final class OverlayManagerSettings {
-         return item.getState();
-     }
--    void setState(@NonNull final String packageName, final int userId, final int state)
--            throws BadKeyException {
-+    void setState(@NonNull final String packageName, final int userId, final int state,
-+            final boolean shouldWait) throws BadKeyException {
-         final SettingsItem item = select(packageName, userId);
-         if (item == null) {
-             throw new BadKeyException(packageName, userId);
-@@ -182,10 +182,10 @@ final class OverlayManagerSettings {
-         item.setState(state);
-         final OverlayInfo current = item.getOverlayInfo();
-         if (previous.state == STATE_NOT_APPROVED_UNKNOWN) {
--            notifyOverlayAdded(current);
-+            notifyOverlayAdded(current, shouldWait);
-             notifySettingsChanged();
-         } else if (current.state != previous.state) {
--            notifyOverlayChanged(current, previous);
-+            notifyOverlayChanged(current, previous, shouldWait);
-             notifySettingsChanged();
-         }
-     }
-@@ -602,32 +602,32 @@ final class OverlayManagerSettings {
-         }
-     }
--    private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
-+    private void notifyOverlayAdded(@NonNull final OverlayInfo oi, final boolean shouldWait) {
-         if (DEBUG) {
-             assertNotNull(oi);
-         }
-         for (final ChangeListener listener : mListeners) {
--            listener.onOverlayAdded(oi);
-+            listener.onOverlayAdded(oi, shouldWait);
-         }
-     }
--    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
-+    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi, final boolean shouldWait) {
-         if (DEBUG) {
-             assertNotNull(oi);
-         }
-         for (final ChangeListener listener : mListeners) {
--            listener.onOverlayRemoved(oi);
-+            listener.onOverlayRemoved(oi, shouldWait);
-         }
-     }
-     private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
--            @NonNull final OverlayInfo oldOi) {
-+            @NonNull final OverlayInfo oldOi, final boolean shouldWait) {
-         if (DEBUG) {
-             assertNotNull(oi);
-             assertNotNull(oldOi);
-         }
-         for (final ChangeListener listener : mListeners) {
--            listener.onOverlayChanged(oi, oldOi);
-+            listener.onOverlayChanged(oi, oldOi, shouldWait);
-         }
-     }
-@@ -642,9 +642,10 @@ final class OverlayManagerSettings {
-     interface ChangeListener {
-         void onSettingsChanged();
--        void onOverlayAdded(@NonNull OverlayInfo oi);
--        void onOverlayRemoved(@NonNull OverlayInfo oi);
--        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
-+        void onOverlayAdded(@NonNull OverlayInfo oi, boolean shouldWait);
-+        void onOverlayRemoved(@NonNull OverlayInfo oi, boolean shouldWait);
-+        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi,
-+            boolean shouldWait);
-         void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
-     }
-diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-index d6f5373..44004c1 100644
---- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
-@@ -25,8 +25,10 @@ import android.os.ShellCommand;
- import android.os.UserHandle;
- import java.io.PrintWriter;
-+import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
-+import java.util.Map.Entry;
- /**
-  * Implementation of 'cmd overlay' commands.
-@@ -45,7 +47,9 @@ final class OverlayManagerShellCommand extends ShellCommand {
-     @Override
-     public int onCommand(@Nullable final String cmd) {
-         if (cmd == null) {
--            return handleDefaultCommands(cmd);
-+            final PrintWriter out = getOutPrintWriter();
-+            out.println("The overlay manager has already been initialized.");
-+            return -1;
-         }
-         final PrintWriter err = getErrPrintWriter();
-         try {
-@@ -56,6 +60,8 @@ final class OverlayManagerShellCommand extends ShellCommand {
-                     return runEnableDisable(true);
-                 case "disable":
-                     return runEnableDisable(false);
-+                case "disable-all":
-+                      return runDisableAll();
-                 case "set-priority":
-                     return runSetPriority();
-                 default:
-@@ -82,10 +88,12 @@ final class OverlayManagerShellCommand extends ShellCommand {
-         out.println("    Overlay packages are printed in priority order. With optional");
-         out.println("    parameters PACKAGEs, limit output to the specified packages");
-         out.println("    but include more information about each package.");
--        out.println("  enable [--user USER_ID] PACKAGE");
--        out.println("    Enable overlay package PACKAGE.");
--        out.println("  disable [--user USER_ID] PACKAGE");
--        out.println("    Disable overlay package PACKAGE.");
-+        out.println("  enable [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
-+        out.println("    Enable overlay package PACKAGE or subsequent counts of PACKAGE.");
-+        out.println("  disable [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
-+        out.println("    Disable overlay package PACKAGE or subsequent counts of PACKAGE.");
-+        out.println("  disable-all [--user USER_ID]");
-+        out.println("    Disable all overlay packages.");
-         out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
-         out.println("    Change the priority of the overlay PACKAGE to be just higher than");
-         out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
-@@ -145,8 +153,90 @@ final class OverlayManagerShellCommand extends ShellCommand {
-             }
-         }
--        final String packageName = getNextArgRequired();
--        return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
-+        int argc = 0;
-+        String packageName = getNextArgRequired();
-+        ArrayList<String> packages = new ArrayList<>();
-+        if (packageName == null) {
-+            System.err.println("Error: no packages specified");
-+            return 1;
-+        }
-+        while (packageName != null) {
-+            argc++;
-+            packages.add(packageName);
-+            packageName = getNextArg();
-+        }
-+        if (argc > 1) {
-+            for (String pkg : packages) {
-+                boolean ret = mInterface.setEnabled(pkg, enable, userId, false);
-+                if (!ret) {
-+                    System.err.println("Error: Failed to " + ((enable) ? "enable ": "disable ") + pkg);
-+                }
-+            }
-+            return 0;
-+        } else if (argc == 1) {
-+            return mInterface.setEnabled(packages.get(0), enable, userId, false) ? 0 : 1;
-+        } else {
-+            System.err.println("Error: A fatal exception has occurred.");
-+            return 1;
-+        }
-+    }
-+
-+    private int runDisableAll() {
-+        int userId = UserHandle.USER_OWNER;
-+        String opt;
-+        while ((opt = getNextOption()) != null) {
-+            switch (opt) {
-+                case "--user":
-+                    userId = UserHandle.parseUserArg(getNextArgRequired());
-+                      break;
-+                default:
-+                    System.err.println("Error: Unknown option: " + opt);
-+                    return 1;
-+            }
-+        }
-+
-+        try {
-+            Map<String, List<OverlayInfo>> targetsAndOverlays = mInterface.getAllOverlays(userId);
-+            int iterator = 0;
-+            int overlaySize = targetsAndOverlays.entrySet().size();
-+            for (Entry<String, List<OverlayInfo>> targetEntry : targetsAndOverlays.entrySet()) {
-+                int iterator_nested = 0;
-+                int targetSize_nested = targetEntry.getValue().size();
-+                iterator++;
-+                for (OverlayInfo oi : targetEntry.getValue()) {
-+                    if (iterator_nested < targetSize_nested) {
-+                        if (oi.isEnabled()) {
-+                            boolean worked = mInterface.setEnabled(oi.packageName, false, userId, true);
-+                            if (!worked) {
-+                                System.err.println("Failed to disable " + oi.packageName);
-+                            }
-+                        }
-+                    } else {
-+                        if (iterator == overlaySize) {
-+                            if (oi.isEnabled()) {
-+                                boolean worked = mInterface.setEnabled(oi.packageName, false, userId, false);
-+                                if (!worked) {
-+                                    System.err.println("Failed to disable " + oi.packageName);
-+                                }
-+                            }
-+                        } else {
-+                            if (oi.isEnabled()) {
-+                                boolean worked = mInterface.setEnabled(oi.packageName, false, userId, true);
-+                                if (!worked) {
-+                                    System.err.println("Failed to disable " + oi.packageName);
-+                                }
-+                            }
-+                        }
-+                    }
-+                    iterator_nested++;
-+                }
-+            }
-+            mInterface.refresh(userId);
-+        } catch (RemoteException re) {
-+            System.err.println(re.toString());
-+            System.err.println("Error: A fatal exception has occurred.");
-+        }
-+        return 0;
-     }
-     private int runSetPriority() throws RemoteException {
--- 
-2.9.3
-
diff --git a/frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch b/frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch
deleted file mode 100644 (file)
index 618f62d..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-From 68105cc059781ce4d0948cfe6d34511da24079d2 Mon Sep 17 00:00:00 2001
-From: Dave Kover <dkover@cyngn.com>
-Date: Fri, 9 Dec 2016 10:47:17 -0700
-Subject: [PATCH 12/38] Themes: Expose resolver hardcoded colors
-
-commit dbbd5e70cc65002df41561474b03362022dd6716
-Author: Dave Kover <dkover@cyngn.com>
-Date:   Wed Feb 18 16:11:14 2015 -0800
-
-    Themes: Expose resolver hardcoded colors
-
-    Expose background colors of the resolver list.
-
-    Change-Id: I3a0a460c5ffe0f5057b3b9ec92faa7a3e09c9e01
-
-commit 0343eb126f3901a3857791137f74fa805bb9d75c
-Author: Thyrus11 <thyrus11@gmail.com>
-Date:   Sat Feb 21 07:19:42 2015 +0100
-
-    Themes: Make resolver list fully themeable
-
-    Follow-up on commit cc9e3b8fcba95b911d1cda36f7770c410058aa8b.
-
-    Change-Id: I3f006a1157db9d0b151a4fe8edf50e7edc7a0b9f
-
-commit c7d973809488b801e8c708d740009f1233bb762e
-Author: Nicholas Chum <nicholaschum@gmail.com>
-Date:   Sun Nov 8 05:27:28 2015 -0500
-
-    Themes: Allow Resolver List BG to be fully themed
-
-    We are able to trace the activity of the new resolver/chooser through
-    different
-    methods, thus leading us to the Java file:
-    \com\android\internal\app\ChooserActivity.java
-    Here we see that the exposed "chooser_service_row_background_color" is
-    available, but not the rest of the activity, so we look into R.layout's,
-    and we
-    find chooser_grid to be the only one containing hardcoded
-    "@color/white" values (as this is framework, we assume this is also
-    known as
-    "@android:color/white" to themers).
-
-    Expose all "@color/white" values from this file to resolver_list_bg.
-
-    Change-Id: I286d92b5d1f672c8adb3c0af1951793521536d90
-
-Change-Id: Iec7951147bbbc99aee6b06ae50c1acc7b9c01a7f
----
- core/res/res/layout/chooser_grid.xml                 |  6 +++---
- .../res/layout/resolver_different_item_header.xml    |  2 +-
- core/res/res/layout/resolver_list.xml                |  8 ++++----
- core/res/res/layout/resolver_list_with_default.xml   |  6 +++---
- core/res/res/values/projekt_colors.xml               | 20 ++++++++++++++++++++
- 5 files changed, 31 insertions(+), 11 deletions(-)
- create mode 100644 core/res/res/values/projekt_colors.xml
-
-diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
-index d8dd447..78c2e05 100644
---- a/core/res/res/layout/chooser_grid.xml
-+++ b/core/res/res/layout/chooser_grid.xml
-@@ -31,7 +31,7 @@
-             android:layout_alwaysShow="true"
-             android:elevation="8dp"
-             android:paddingStart="16dp"
--            android:background="@color/white" >
-+            android:background="@color/resolver_list_bg" >
-         <TextView android:id="@+id/profile_button"
-                   android:layout_width="wrap_content"
-                   android:layout_height="48dp"
-@@ -74,7 +74,7 @@
-             android:id="@+id/resolver_list"
-             android:clipToPadding="false"
-             android:scrollbarStyle="outsideOverlay"
--            android:background="@color/white"
-+            android:background="@color/resolver_list_bg"
-             android:elevation="8dp"
-             android:listSelector="@color/transparent"
-             android:divider="@null"
-@@ -85,7 +85,7 @@
-               android:layout_width="match_parent"
-               android:layout_height="wrap_content"
-               android:layout_alwaysShow="true"
--              android:background="@color/white"
-+              android:background="@color/resolver_list_bg"
-               android:text="@string/noApplications"
-               android:padding="32dp"
-               android:gravity="center"
-diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
-index 5889136..201c8c6 100644
---- a/core/res/res/layout/resolver_different_item_header.xml
-+++ b/core/res/res/layout/resolver_different_item_header.xml
-@@ -29,6 +29,6 @@
-     android:paddingEnd="16dp"
-     android:paddingTop="8dp"
-     android:paddingBottom="8dp"
--    android:background="@color/white"
-+    android:background="@color/resolver_list_bg"
-     android:elevation="8dp"
-     />
-diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
-index c4e8e9c..1b6230a 100644
---- a/core/res/res/layout/resolver_list.xml
-+++ b/core/res/res/layout/resolver_list.xml
-@@ -30,7 +30,7 @@
-         android:layout_height="wrap_content"
-         android:layout_alwaysShow="true"
-         android:elevation="8dp"
--        android:background="@color/white">
-+        android:background="@color/resolver_list_bg">
-         <TextView
-             android:id="@+id/profile_button"
-@@ -69,7 +69,7 @@
-         android:id="@+id/resolver_list"
-         android:clipToPadding="false"
-         android:scrollbarStyle="outsideOverlay"
--        android:background="@color/white"
-+        android:background="@color/resolver_list_bg"
-         android:elevation="8dp"
-         android:nestedScrollingEnabled="true"
-         android:scrollIndicators="top|bottom"
-@@ -78,7 +78,7 @@
-     <TextView android:id="@+id/empty"
-               android:layout_width="match_parent"
-               android:layout_height="wrap_content"
--              android:background="@color/white"
-+              android:background="@color/resolver_list_bg"
-               android:elevation="8dp"
-               android:layout_alwaysShow="true"
-               android:text="@string/noApplications"
-@@ -99,7 +99,7 @@
-         android:orientation="horizontal"
-         android:layoutDirection="locale"
-         android:measureWithLargestChild="true"
--        android:background="@color/white"
-+        android:background="@color/resolver_list_bg"
-         android:paddingTop="8dp"
-         android:paddingBottom="8dp"
-         android:paddingStart="12dp"
-diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
-index 02dc2ed..d3baf68 100644
---- a/core/res/res/layout/resolver_list_with_default.xml
-+++ b/core/res/res/layout/resolver_list_with_default.xml
-@@ -29,7 +29,7 @@
-         android:layout_height="wrap_content"
-         android:layout_alwaysShow="true"
-         android:orientation="vertical"
--        android:background="@color/white"
-+        android:background="@color/resolver_list_bg"
-         android:elevation="8dp">
-         <LinearLayout
-@@ -110,7 +110,7 @@
-             android:paddingBottom="8dp"
-             android:paddingStart="12dp"
-             android:paddingEnd="12dp"
--            android:background="@color/white"
-+            android:background="@color/resolver_list_bg"
-             android:elevation="8dp">
-             <Button
-@@ -150,7 +150,7 @@
-         android:id="@+id/resolver_list"
-         android:clipToPadding="false"
-         android:scrollbarStyle="outsideOverlay"
--        android:background="@color/white"
-+        android:background="@color/resolver_list_bg"
-         android:elevation="8dp"
-         android:nestedScrollingEnabled="true"
-         android:divider="@null" />
-diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..c6dbc1c
---- /dev/null
-+++ b/core/res/res/values/projekt_colors.xml
-@@ -0,0 +1,20 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Projekt Substratum
-+
-+    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>
-+    <color name="resolver_list_bg">@color/white</color>
-+</resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch b/frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch
deleted file mode 100644 (file)
index a5b2fc9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-From 0e81796b338e5009df8049d0ad4c4b2095f4c807 Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Tue, 17 Nov 2015 18:57:11 -0500
-Subject: [PATCH 13/38] Themes: Allow Immersive cling colors to be fully themed
-
-This allows the immersive mode help tooltip to be themed completely by
-removing hardcoded framework calls. Let the themer decide what they want
-the colors to be.
-
-Change-Id: Ia0927fda5e44a3ce8ef699cb018bea9b9e7ace62
----
- core/res/res/layout/immersive_mode_cling.xml | 12 ++++++------
- core/res/res/values/projekt_colors.xml       |  3 +++
- 2 files changed, 9 insertions(+), 6 deletions(-)
-
-diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
-index b08b0f4..6dbde20 100644
---- a/core/res/res/layout/immersive_mode_cling.xml
-+++ b/core/res/res/layout/immersive_mode_cling.xml
-@@ -16,7 +16,7 @@
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-         android:layout_width="match_parent"
-         android:layout_height="wrap_content"
--        android:background="?android:attr/colorAccent"
-+        android:background="@color/immersive_cling_bg_color"
-         android:gravity="center_vertical"
-         android:paddingBottom="24dp">
-@@ -47,7 +47,7 @@
-                 android:paddingTop="8dp"
-                 android:scaleType="center"
-                 android:src="@drawable/ic_expand_more_48dp"
--                android:tint="?android:attr/colorAccent"/>
-+                android:tint="@color/immersive_cling_bg_color"/>
-     </FrameLayout>
-     <TextView
-@@ -59,7 +59,7 @@
-             android:paddingStart="48dp"
-             android:paddingTop="40dp"
-             android:text="@string/immersive_cling_title"
--            android:textColor="@color/primary_text_default_material_light"
-+            android:textColor="@color/immersive_cling_text_color"
-             android:textSize="24sp" />
-     <TextView
-@@ -71,7 +71,7 @@
-             android:paddingStart="48dp"
-             android:paddingTop="12.6dp"
-             android:text="@string/immersive_cling_description"
--            android:textColor="@color/primary_text_default_material_light"
-+            android:textColor="@color/immersive_cling_text_color"
-             android:textSize="16sp" />
-     <Button
-@@ -86,7 +86,7 @@
-             android:paddingEnd="8dp"
-             android:paddingStart="8dp"
-             android:text="@string/immersive_cling_positive"
--            android:textColor="@android:color/white"
-+            android:textColor="@color/immersive_cling_button_text_color"
-             android:textSize="14sp" />
--</RelativeLayout>
-\ No newline at end of file
-+</RelativeLayout>
-diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
-index c6dbc1c..7408ae9 100644
---- a/core/res/res/values/projekt_colors.xml
-+++ b/core/res/res/values/projekt_colors.xml
-@@ -17,4 +17,7 @@
- <resources>
-     <color name="resolver_list_bg">@color/white</color>
-+    <color name="immersive_cling_bg_color">@color/accent_device_default_light</color>
-+    <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
-+    <color name="immersive_cling_button_text_color">@android:color/white</color>
- </resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch b/frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch
deleted file mode 100644 (file)
index 64aa7f6..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 16db866f5fdb07a80c87e733af4952ff2484a4f3 Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Mon, 23 Nov 2015 23:49:15 -0500
-Subject: [PATCH 14/38] Themes: Allow Permission Icons to be fully themed
-
-This removes the forced @android:color/black tint on the permission
-icons during app sideload through PackageInstaller.
-
-These icons are able to be changed through framework XMLs, but this line
-forces a black tint (invisible on dark themes) on the icons. Let's
-remove this.
-
-Change-Id: I31eb5021a6d297997dbba156f98cbf47f2102b6c
----
- core/res/res/layout/app_permission_item.xml | 2 +-
- core/res/res/values/projekt_colors.xml      | 1 +
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
-index 383d771..a80d40e 100644
---- a/core/res/res/layout/app_permission_item.xml
-+++ b/core/res/res/layout/app_permission_item.xml
-@@ -32,7 +32,7 @@
-         android:layout_marginStart="16dp"
-         android:layout_marginEnd="8dp"
-         android:scaleType="fitCenter"
--        android:tint="@android:color/black"/>
-+        android:tint="@color/app_permission_icon_tint"/>
-     <ImageView
-         android:layout_width="wrap_content"
-diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
-index 7408ae9..a7316ab 100644
---- a/core/res/res/values/projekt_colors.xml
-+++ b/core/res/res/values/projekt_colors.xml
-@@ -20,4 +20,5 @@
-     <color name="immersive_cling_bg_color">@color/accent_device_default_light</color>
-     <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
-     <color name="immersive_cling_button_text_color">@android:color/white</color>
-+    <color name="app_permission_icon_tint">@android:color/black</color>
- </resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch b/frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch
deleted file mode 100644 (file)
index 52cfce0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From 91025c7450fc618d35d40d6581172a262d73bd22 Mon Sep 17 00:00:00 2001
-From: Dave Kover <dkover@cyngn.com>
-Date: Thu, 14 Apr 2016 10:19:13 +0700
-Subject: [PATCH 15/38] Themes: Allow Navbar ripple color to be themed
-
-PS1:
-Layers Commit by @setiawanjimmy
-Rewrite of commit by: KreAch3R
-Original commit by: Dave Kover
-Distilled from: https://github.com/CyanogenMod/android_frameworks_base/commit/05ce0a6f5651743add398556d557a5f4c40c2503
-
-Change-Id: I7969e952d7e08f1d12e89291512312421585b70f
----
- packages/SystemUI/res/values/projekt_colors.xml     | 21 +++++++++++++++++++++
- .../systemui/statusbar/policy/KeyButtonRipple.java  |  5 ++++-
- 2 files changed, 25 insertions(+), 1 deletion(-)
- create mode 100644 packages/SystemUI/res/values/projekt_colors.xml
-
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..a0f1df0
---- /dev/null
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -0,0 +1,21 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Projekt Substratum
-+
-+    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>
-+    <!-- Navigation button ripple color -->
-+    <color name="navbutton_ripple_color">#FFFFFFFF</color>
-+</resources>
-diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
-index 57e092a..2579579 100644
---- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
-+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
-@@ -65,16 +65,19 @@ public class KeyButtonRipple extends Drawable {
-     private final HashSet<Animator> mRunningAnimations = new HashSet<>();
-     private final ArrayList<Animator> mTmpArray = new ArrayList<>();
-+    private int mRippleColor;
-+
-     public KeyButtonRipple(Context ctx, View targetView) {
-         mMaxWidth =  ctx.getResources().getDimensionPixelSize(R.dimen.key_button_ripple_max_width);
-         mTargetView = targetView;
-+        mRippleColor = ctx.getResources().getColor(R.color.navbutton_ripple_color);
-     }
-     private Paint getRipplePaint() {
-         if (mRipplePaint == null) {
-             mRipplePaint = new Paint();
-             mRipplePaint.setAntiAlias(true);
--            mRipplePaint.setColor(0xffffffff);
-+            mRipplePaint.setColor(mRippleColor);
-         }
-         return mRipplePaint;
-     }
--- 
-2.9.3
-
diff --git a/frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch b/frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch
deleted file mode 100644 (file)
index c3ad488..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 2220bc8b7603b3223e73cd4303151d56eda5948b Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Sun, 18 Sep 2016 21:33:18 +0700
-Subject: [PATCH 16/38] SystemUI: Expose QS edit item decoration background
- color
-
-PS2:
-More descriptive color name
-
-@nathanchance edit: updated for 7.1 Nougat
-
-Change-Id: I9867ca26e7d9dacad37d2b70180a98fede0fb0e8
----
- packages/SystemUI/res/values/projekt_colors.xml                     | 2 ++
- .../SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java | 6 ++++--
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-index a0f1df0..42f4a15 100644
---- a/packages/SystemUI/res/values/projekt_colors.xml
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -18,4 +18,6 @@
- <resources>
-     <!-- Navigation button ripple color -->
-     <color name="navbutton_ripple_color">#FFFFFFFF</color>
-+    <!-- QS edit page background color -->
-+    <color name="qs_edit_item_decoration_bg">@*android:color/secondary_device_default_settings</color>
- </resources>
-diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
-index 8d7f6ee..c7a1441 100644
---- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
-+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
-@@ -471,11 +471,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
-         private TileItemDecoration(Context context) {
-             TypedArray ta =
-                     context.obtainStyledAttributes(new int[]{android.R.attr.colorSecondary});
--            mDrawable = new ColorDrawable(ta.getColor(0, 0));
-+            mDrawable = new ColorDrawable();
-             ta.recycle();
-         }
--
-         @Override
-         public void onDraw(Canvas c, RecyclerView parent, State state) {
-             super.onDraw(c, parent, state);
-@@ -494,6 +493,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
-                         .getLayoutParams();
-                 final int top = child.getTop() + params.topMargin +
-                         Math.round(ViewCompat.getTranslationY(child));
-+                // Set drawable color
-+                mDrawable.setColor(mContext.getResources().getColor(
-+                        R.color.qs_edit_item_decoration_bg));
-                 // Draw full width, in case there aren't tiles all the way across.
-                 mDrawable.setBounds(0, top, width, bottom);
-                 mDrawable.draw(c);
--- 
-2.9.3
-
diff --git a/frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch b/frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch
deleted file mode 100644 (file)
index 2f79692..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 78783e0ed0a5eb8c3676d152892bf5eebf659317 Mon Sep 17 00:00:00 2001
-From: Simao Gomes Viana <xdevs23@outlook.com>
-Date: Fri, 25 Nov 2016 20:50:29 +0100
-Subject: [PATCH 17/38] Allow custom alpha for notification shade bg color
-
-Change-Id: If621df83d994feae0448a734408ba85ac8329325
----
- .../stack/NotificationStackScrollLayout.java       | 40 +++++++++++++++-------
- 1 file changed, 27 insertions(+), 13 deletions(-)
-
-diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
-index a6fe438..5cf0e0a 100644
---- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
-+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
-@@ -430,19 +430,33 @@ public class NotificationStackScrollLayout extends ViewGroup
-     }
-     private void updateBackgroundDimming() {
--        float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
--        alpha *= mBackgroundFadeAmount;
--        // We need to manually blend in the background color
--        int scrimColor = mScrimController.getScrimBehindColor();
--        // SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
--        float alphaInv = 1 - alpha;
--        int color = Color.argb((int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
--                (int) (mBackgroundFadeAmount * Color.red(mBgColor)
--                        + alphaInv * Color.red(scrimColor)),
--                (int) (mBackgroundFadeAmount * Color.green(mBgColor)
--                        + alphaInv * Color.green(scrimColor)),
--                (int) (mBackgroundFadeAmount * Color.blue(mBgColor)
--                        + alphaInv * Color.blue(scrimColor)));
-+        int color;
-+        if(Color.alpha(mBgColor) == 255) {
-+            float alpha = BACKGROUND_ALPHA_DIMMED +
-+                    (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
-+            alpha *= mBackgroundFadeAmount;
-+            // We need to manually blend in the background color
-+            int scrimColor = mScrimController.getScrimBehindColor();
-+            // SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
-+            float alphaInv = 1 - alpha;
-+            color = Color.argb(
-+                    (int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
-+                    (int) (mBackgroundFadeAmount * Color.red(mBgColor)
-+                            + alphaInv * Color.red(scrimColor)),
-+                    (int) (mBackgroundFadeAmount * Color.green(mBgColor)
-+                            + alphaInv * Color.green(scrimColor)),
-+                    (int) (mBackgroundFadeAmount * Color.blue(mBgColor)
-+                            + alphaInv * Color.blue(scrimColor)));
-+        } else {
-+            int a = Color.alpha(mBgColor) +
-+                Color.alpha(mScrimController.getScrimBehindColor());
-+            if(a > 255) a = 255;
-+            else if(a < 0) /* shouldn't happen */ a = 0;
-+            color = Color.argb(
-+                a,
-+                Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor)
-+            );
-+        }
-         mBackgroundPaint.setColor(color);
-         invalidate();
-     }
--- 
-2.9.3
-
diff --git a/frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch b/frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch
deleted file mode 100644 (file)
index 3854ba4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From c6782421d455174ac3b03e994505947471726194 Mon Sep 17 00:00:00 2001
-From: "Niklas Schnettler (Sh4dowSoul)" <niklas.schnettler@gmail.com>
-Date: Wed, 5 Oct 2016 18:07:43 +0200
-Subject: [PATCH 18/38] Themes: Expose various QuickSettings text colors
-
-Change-Id: Iaea71ca83afbc3d8cc6faea6afac16cabb46cfff
----
- packages/SystemUI/res/layout/qs_customize_panel_content.xml | 3 ++-
- packages/SystemUI/res/layout/status_bar_alarm_group.xml     | 2 +-
- packages/SystemUI/res/values/projekt_colors.xml             | 4 ++++
- 3 files changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
-index 04d0e65..9c23250 100644
---- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
-+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
-@@ -23,7 +23,8 @@
-         android:layout_height="wrap_content"
-         android:layout_marginTop="28dp"
-         android:navigationContentDescription="@*android:string/action_bar_up_description"
--        style="?android:attr/toolbarStyle" />
-+        style="?android:attr/toolbarStyle"
-+        android:titleTextColor="@color/qs_edit_toolbar_text_color"/>
-     <android.support.v7.widget.RecyclerView
-         android:id="@android:id/list"
-diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
-index 1b47d4b..dca8afb 100644
---- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
-+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
-@@ -73,7 +73,7 @@
-         android:paddingTop="3dp"
-         android:drawablePadding="8dp"
-         android:drawableStart="@drawable/ic_access_alarms_small"
--        android:textColor="#64ffffff"
-+        android:textColor="@color/qs_alarm_status_text_color"
-         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-         android:gravity="top"
-         android:background="?android:attr/selectableItemBackgroundBorderless"
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-index 42f4a15..0f89199 100644
---- a/packages/SystemUI/res/values/projekt_colors.xml
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -20,4 +20,8 @@
-     <color name="navbutton_ripple_color">#FFFFFFFF</color>
-     <!-- QS edit page background color -->
-     <color name="qs_edit_item_decoration_bg">@*android:color/secondary_device_default_settings</color>
-+    <!-- QS alarm status text color -->
-+    <color name="qs_alarm_status_text_color">#64ffffff</color>
-+    <!-- QS edit page toolbar text color -->
-+    <color name="qs_edit_toolbar_text_color">#FFFFFF</color>
- </resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch b/frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch
deleted file mode 100644 (file)
index 68fa9b3..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-From 665ebd4404843764b9a98c3fef7a2e6007695d40 Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Sat, 27 Aug 2016 10:56:46 -0400
-Subject: [PATCH 19/38] Notifications: Expose a bool to disable dynamic colors
-
-This commit allows a themer to overlay a boolean value in config.xml to
-disable dynamic colors applied to the app title and app icon of each
-notification.
-
-PS6:
-Separate app title and small icon colors for more flexibility.
-Expose hardcoded sender text name.
-
-Change-Id: I3c7828118991ec4fc616011caf073c81f75428b4
----
- core/java/android/app/Notification.java | 23 ++++++++++++++++++++---
- core/res/res/values/projekt_colors.xml  |  2 ++
- core/res/res/values/projekt_config.xml  | 25 +++++++++++++++++++++++++
- core/res/res/values/projekt_symbols.xml | 25 +++++++++++++++++++++++++
- 4 files changed, 72 insertions(+), 3 deletions(-)
- create mode 100644 core/res/res/values/projekt_config.xml
- create mode 100644 core/res/res/values/projekt_symbols.xml
-
-diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
-index 9f217d4..55029aa 100644
---- a/core/java/android/app/Notification.java
-+++ b/core/java/android/app/Notification.java
-@@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.PackageManager.NameNotFoundException;
- import android.content.res.ColorStateList;
-+import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
-@@ -3884,7 +3885,7 @@ public class Notification implements Parcelable
-         private void processSmallIconColor(Icon smallIcon, RemoteViews contentView) {
-             boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
-             if (colorable) {
--                contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
-+                contentView.setDrawableParameters(R.id.icon, false, -1, resolveIconContrastColor(),
-                         PorterDuff.Mode.SRC_ATOP, -1);
-             }
-@@ -3901,7 +3902,7 @@ public class Notification implements Parcelable
-             if (largeIcon != null && isLegacy()
-                     && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
-                 // resolve color will fall back to the default when legacy
--                contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
-+                contentView.setDrawableParameters(R.id.icon, false, -1, resolveIconContrastColor(),
-                         PorterDuff.Mode.SRC_ATOP, -1);
-             }
-         }
-@@ -3912,7 +3913,23 @@ public class Notification implements Parcelable
-             }
-         }
-+        int getSenderTextColor() {
-+            return mContext.getColor(R.color.sender_text_color);
-+        }
-+
-+        int resolveIconContrastColor() {
-+            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-+                return mContext.getColor(R.color.notification_icon_default_color);
-+            } else {
-+                return resolveContrastColor();
-+            }
-+        }
-+
-         int resolveContrastColor() {
-+            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-+                return mContext.getColor(R.color.notification_text_default_color);
-+            }
-+
-             if (mCachedContrastColorIsFor == mN.color && mCachedContrastColor != COLOR_INVALID) {
-                 return mCachedContrastColor;
-             }
-@@ -4915,7 +4932,7 @@ public class Notification implements Parcelable
-                         0 /* flags */);
-             } else {
-                 sb.append(bidi.unicodeWrap(m.mSender),
--                        makeFontColorSpan(Color.BLACK),
-+                        makeFontColorSpan(mBuilder.getSenderTextColor()),
-                         0 /* flags */);
-             }
-             CharSequence text = m.mText == null ? "" : m.mText;
-diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
-index a7316ab..d17fbba 100644
---- a/core/res/res/values/projekt_colors.xml
-+++ b/core/res/res/values/projekt_colors.xml
-@@ -21,4 +21,6 @@
-     <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
-     <color name="immersive_cling_button_text_color">@android:color/white</color>
-     <color name="app_permission_icon_tint">@android:color/black</color>
-+    <color name="notification_text_default_color">@android:color/notification_default_color</color>
-+    <color name="sender_text_color">@android:color/black</color>
- </resources>
-diff --git a/core/res/res/values/projekt_config.xml b/core/res/res/values/projekt_config.xml
-new file mode 100644
-index 0000000..f6eb90a
---- /dev/null
-+++ b/core/res/res/values/projekt_config.xml
-@@ -0,0 +1,25 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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.
-+-->
-+
-+<!-- These resources are around just to allow their values to be customized
-+     for different hardware and product builds.  Do not translate. -->
-+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-+
-+    <!-- True if the notifications should dynamically tint the app icon and app title -->
-+    <bool name="config_allowNotificationIconTextTinting">true</bool>
-+
-+</resources>
-diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml
-new file mode 100644
-index 0000000..f597a5f
---- /dev/null
-+++ b/core/res/res/values/projekt_symbols.xml
-@@ -0,0 +1,25 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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>
-+
-+  <!-- Notification icon/text dynamic tint -->
-+  <java-symbol type="bool" name="config_allowNotificationIconTextTinting" />
-+  <java-symbol type="color" name="notification_text_default_color" />
-+  <java-symbol type="color" name="sender_text_color" />
-+
-+</resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch b/frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch
deleted file mode 100644 (file)
index 6df4637..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 85f0110784ed2b55e062ca3c35d05480dc78ab8a Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Mon, 14 Nov 2016 14:49:47 +0200
-Subject: [PATCH 20/38] Notification dynamic colors bool compatible with OMS7
-
-OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
-
-// Resources.getSystem Resources are created on request and aren't tracked by
-// mResourceReferences.
-//
-// If overlays targeting "android" are to be used, we must create the system
-// resources regardless of whether they already exist, since otherwise the
-// information on what overlays to use would be lost. This is wasteful for most
-// applications, so limit this operation to the system user only. (This means
-// Resources.getSystem() will *not* use overlays for applications.)
-
-Replaced deprecated Resources.getSystem() with compatible method.
-
-Change-Id: I02efe27de3cc7067552964ffbaf079f9e9b5bc3e
----
- core/java/android/app/Notification.java | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
-index 55029aa..67c2132 100644
---- a/core/java/android/app/Notification.java
-+++ b/core/java/android/app/Notification.java
-@@ -3918,7 +3918,7 @@ public class Notification implements Parcelable
-         }
-         int resolveIconContrastColor() {
--            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-+            if (!mContext.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-                 return mContext.getColor(R.color.notification_icon_default_color);
-             } else {
-                 return resolveContrastColor();
-@@ -3926,7 +3926,7 @@ public class Notification implements Parcelable
-         }
-         int resolveContrastColor() {
--            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-+            if (!mContext.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
-                 return mContext.getColor(R.color.notification_text_default_color);
-             }
--- 
-2.9.3
-
diff --git a/frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch b/frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch
deleted file mode 100644 (file)
index 0014548..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From a5c8355f8999d9c4868bb22018ed8d6d9e25ad48 Mon Sep 17 00:00:00 2001
-From: Daniel Koman <dankoman30@gmail.com>
-Date: Fri, 17 Apr 2015 11:56:28 -0600
-Subject: [PATCH 21/38] Allow prevention of doze notification color inversion
-
-Removed empty newline at the end -- KreAch3R
-Removed slims files for aosp roms -- Bgill55
-
-Change-Id: I2d361c34904f3d168894b8b1741456319fd68456
----
- core/res/res/values/projekt_config.xml                           | 5 +++++
- core/res/res/values/projekt_symbols.xml                          | 3 +++
- packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 4 +++-
- 3 files changed, 11 insertions(+), 1 deletion(-)
-
-diff --git a/core/res/res/values/projekt_config.xml b/core/res/res/values/projekt_config.xml
-index f6eb90a..5234959 100644
---- a/core/res/res/values/projekt_config.xml
-+++ b/core/res/res/values/projekt_config.xml
-@@ -22,4 +22,9 @@
-     <!-- True if the notifications should dynamically tint the app icon and app title -->
-     <bool name="config_allowNotificationIconTextTinting">true</bool>
-+    <!-- Whether doze should invert colors for notifications. If the RRO theme causes
-+    the NORMAL notification background to be dark and the text to be light, this boolean
-+    needs to be set to false, to prevent the doze notifications from being light -->
-+    <bool name="config_invert_colors_on_doze">true</bool>
-+
- </resources>
-diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml
-index f597a5f..16a5728 100644
---- a/core/res/res/values/projekt_symbols.xml
-+++ b/core/res/res/values/projekt_symbols.xml
-@@ -22,4 +22,7 @@
-   <java-symbol type="color" name="notification_text_default_color" />
-   <java-symbol type="color" name="sender_text_color" />
-+  <!-- Doze invert -->
-+  <java-symbol type="bool" name="config_invert_colors_on_doze" />
-+
- </resources>
-diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-index 2c96e31..65fd115 100644
---- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-+++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-@@ -20,6 +20,7 @@ import android.animation.Animator;
- import android.animation.AnimatorListenerAdapter;
- import android.animation.ValueAnimator;
- import android.content.Context;
-+import android.content.res.Resources;
- import android.graphics.ColorMatrix;
- import android.graphics.ColorMatrixColorFilter;
- import android.graphics.Paint;
-@@ -90,7 +91,8 @@ public class ViewInvertHelper {
-     }
-     public void update(boolean invert) {
--        if (invert) {
-+        if (invert && Resources.getSystem().getBoolean(
-+                com.android.internal.R.bool.config_invert_colors_on_doze)) {
-             updateInvertPaint(1f);
-             for (int i = 0; i < mTargets.size(); i++) {
-                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
--- 
-2.9.3
-
diff --git a/frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch b/frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch
deleted file mode 100644 (file)
index 3768431..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 367e7476f68b80c265bedb92a019cb5fd7c8dfc7 Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Mon, 14 Nov 2016 14:44:17 +0200
-Subject: [PATCH 22/38] OMS7 compatible 'Ambient notification inversion'
-
-OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
-
-// Resources.getSystem Resources are created on request and aren't tracked by
-// mResourceReferences.
-//
-// If overlays targeting "android" are to be used, we must create the system
-// resources regardless of whether they already exist, since otherwise the
-// information on what overlays to use would be lost. This is wasteful for most
-// applications, so limit this operation to the system user only. (This means
-// Resources.getSystem() will *not* use overlays for applications.)
-
-Replaced deprecated Resources.getSystem() with compatible method.
-
-Change-Id: I80ad5d037004f0dc63d9eb746c3af05e59a8834e
----
- packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-index 65fd115..605f381 100644
---- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-+++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-@@ -20,7 +20,6 @@ import android.animation.Animator;
- import android.animation.AnimatorListenerAdapter;
- import android.animation.ValueAnimator;
- import android.content.Context;
--import android.content.res.Resources;
- import android.graphics.ColorMatrix;
- import android.graphics.ColorMatrixColorFilter;
- import android.graphics.Paint;
-@@ -37,6 +36,7 @@ public class ViewInvertHelper {
-     private final ColorMatrix mMatrix = new ColorMatrix();
-     private final ColorMatrix mGrayscaleMatrix = new ColorMatrix();
-     private final long mFadeDuration;
-+    private final boolean mThemeInvert;
-     private final ArrayList<View> mTargets = new ArrayList<>();
-     public ViewInvertHelper(View v, long fadeDuration) {
-@@ -45,6 +45,7 @@ public class ViewInvertHelper {
-     }
-     public ViewInvertHelper(Context context, long fadeDuration) {
-         mFadeDuration = fadeDuration;
-+        mThemeInvert = context.getResources().getBoolean(com.android.internal.R.bool.config_invert_colors_on_doze);
-     }
-     private static ArrayList<View> constructArray(View target) {
-@@ -91,8 +92,7 @@ public class ViewInvertHelper {
-     }
-     public void update(boolean invert) {
--        if (invert && Resources.getSystem().getBoolean(
--                com.android.internal.R.bool.config_invert_colors_on_doze)) {
-+        if (invert && mThemeInvert) {
-             updateInvertPaint(1f);
-             for (int i = 0; i < mTargets.size(); i++) {
-                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
--- 
-2.9.3
-
diff --git a/frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch b/frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch
deleted file mode 100644 (file)
index 4550eb4..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-From 415172d6cb86b8608948ebd8d26d5ac8911cb07c Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Mon, 5 Dec 2016 19:00:04 +0700
-Subject: [PATCH 23/38] SystemUI: Use own drawables for QS expand icon
-
-This was using the volume panel drawables used also on volume panel.
-So with this commit themers can give different icon for either QS
-and volume panel expand icon.
-
-Change-Id: Ice8d8a520b9b22ba773cceb885e11c8a4bbf6d5f
----
- .../anim/ic_qs_collapse_chevron_02_animation.xml   | 25 +++++++++
- .../anim/ic_qs_collapse_rectangle_1_animation.xml  | 26 +++++++++
- .../anim/ic_qs_collapse_rectangle_2_animation.xml  | 26 +++++++++
- .../res/anim/ic_qs_expand_chevron_01_animation.xml | 25 +++++++++
- .../anim/ic_qs_expand_rectangle_3_animation.xml    | 26 +++++++++
- .../anim/ic_qs_expand_rectangle_4_animation.xml    | 26 +++++++++
- packages/SystemUI/res/drawable/ic_qs_collapse.xml  | 62 ++++++++++++++++++++++
- .../res/drawable/ic_qs_collapse_animation.xml      | 29 ++++++++++
- packages/SystemUI/res/drawable/ic_qs_expand.xml    | 62 ++++++++++++++++++++++
- .../res/drawable/ic_qs_expand_animation.xml        | 29 ++++++++++
- .../ic_qs_collapse_animation_interpolator_0.xml    | 17 ++++++
- .../ic_qs_expand_animation_interpolator_0.xml      | 17 ++++++
- .../statusbar/phone/ExpandableIndicator.java       |  8 +--
- 13 files changed, 374 insertions(+), 4 deletions(-)
- create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
- create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
- create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
- create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
- create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
- create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
- create mode 100644 packages/SystemUI/res/drawable/ic_qs_collapse.xml
- create mode 100644 packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
- create mode 100644 packages/SystemUI/res/drawable/ic_qs_expand.xml
- create mode 100644 packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
- create mode 100644 packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
- create mode 100644 packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
-
-diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
-new file mode 100644
-index 0000000..443f2a6
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
-@@ -0,0 +1,25 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="250"
-+        android:interpolator="@android:interpolator/fast_out_slow_in"
-+        android:pathData="M 12.0,9.0 c 0.0,0.66667 0.0,5.0 0.0,6.0"
-+        android:propertyXName="translateX"
-+        android:propertyYName="translateY" />
-+
-+</set>
-\ No newline at end of file
-diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
-new file mode 100644
-index 0000000..b73cdca
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
-@@ -0,0 +1,26 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="200"
-+        android:interpolator="@interpolator/ic_qs_collapse_animation_interpolator_0"
-+        android:propertyName="rotation"
-+        android:valueFrom="45.0"
-+        android:valueTo="-45.0"
-+        android:valueType="floatType" />
-+
-+</set>
-diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
-new file mode 100644
-index 0000000..91c83fc
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
-@@ -0,0 +1,26 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="200"
-+        android:interpolator="@interpolator/ic_qs_collapse_animation_interpolator_0"
-+        android:propertyName="rotation"
-+        android:valueFrom="-45.0"
-+        android:valueTo="45.0"
-+        android:valueType="floatType" />
-+
-+</set>
-diff --git a/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
-new file mode 100644
-index 0000000..e43e645
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
-@@ -0,0 +1,25 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="250"
-+        android:interpolator="@android:interpolator/fast_out_slow_in"
-+        android:pathData="M 12.0,15.0 c 0.0,-1.0 0.0,-5.33333 0.0,-6.0"
-+        android:propertyXName="translateX"
-+        android:propertyYName="translateY" />
-+
-+</set>
-\ No newline at end of file
-diff --git a/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
-new file mode 100644
-index 0000000..493bdae
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
-@@ -0,0 +1,26 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="200"
-+        android:interpolator="@interpolator/ic_qs_expand_animation_interpolator_0"
-+        android:propertyName="rotation"
-+        android:valueFrom="45.0"
-+        android:valueTo="-45.0"
-+        android:valueType="floatType" />
-+
-+</set>
-diff --git a/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
-new file mode 100644
-index 0000000..58e485c
---- /dev/null
-+++ b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
-@@ -0,0 +1,26 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<set xmlns:android="http://schemas.android.com/apk/res/android" >
-+
-+    <objectAnimator
-+        android:duration="200"
-+        android:interpolator="@interpolator/ic_qs_expand_animation_interpolator_0"
-+        android:propertyName="rotation"
-+        android:valueFrom="-45.0"
-+        android:valueTo="45.0"
-+        android:valueType="floatType" />
-+
-+</set>
-diff --git a/packages/SystemUI/res/drawable/ic_qs_collapse.xml b/packages/SystemUI/res/drawable/ic_qs_collapse.xml
-new file mode 100644
-index 0000000..bba6b7f
---- /dev/null
-+++ b/packages/SystemUI/res/drawable/ic_qs_collapse.xml
-@@ -0,0 +1,62 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<vector xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:name="ic_qs_collapse"
-+    android:height="24dp"
-+    android:viewportHeight="24"
-+    android:viewportWidth="24"
-+    android:width="24dp" >
-+
-+    <group
-+        android:name="chevron_02"
-+        android:rotation="90"
-+        android:translateX="12"
-+        android:translateY="9" >
-+        <group
-+            android:name="rectangle_2"
-+            android:rotation="-45" >
-+            <group
-+                android:name="rectangle_2_pivot"
-+                android:translateY="4" >
-+                <group
-+                    android:name="rectangle_path_2_position"
-+                    android:translateY="-1" >
-+                    <path
-+                        android:name="rectangle_path_2"
-+                        android:fillColor="#FFFFFFFF"
-+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
-+                </group>
-+            </group>
-+        </group>
-+        <group
-+            android:name="rectangle_1"
-+            android:rotation="45" >
-+            <group
-+                android:name="rectangle_1_pivot"
-+                android:translateY="-4" >
-+                <group
-+                    android:name="rectangle_path_1_position"
-+                    android:translateY="1" >
-+                    <path
-+                        android:name="rectangle_path_1"
-+                        android:fillColor="#FFFFFFFF"
-+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
-+                </group>
-+            </group>
-+        </group>
-+    </group>
-+
-+</vector>
-diff --git a/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml b/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
-new file mode 100644
-index 0000000..8138b2e
---- /dev/null
-+++ b/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
-@@ -0,0 +1,29 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:drawable="@drawable/ic_qs_collapse" >
-+
-+    <target
-+        android:name="chevron_02"
-+        android:animation="@anim/ic_qs_collapse_chevron_02_animation" />
-+    <target
-+        android:name="rectangle_2"
-+        android:animation="@anim/ic_qs_collapse_rectangle_2_animation" />
-+    <target
-+        android:name="rectangle_1"
-+        android:animation="@anim/ic_qs_collapse_rectangle_1_animation" />
-+
-+</animated-vector>
-diff --git a/packages/SystemUI/res/drawable/ic_qs_expand.xml b/packages/SystemUI/res/drawable/ic_qs_expand.xml
-new file mode 100644
-index 0000000..bb22064
---- /dev/null
-+++ b/packages/SystemUI/res/drawable/ic_qs_expand.xml
-@@ -0,0 +1,62 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<vector xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:name="ic_qs_expand"
-+    android:height="24dp"
-+    android:viewportHeight="24"
-+    android:viewportWidth="24"
-+    android:width="24dp" >
-+
-+    <group
-+        android:name="chevron_01"
-+        android:rotation="90"
-+        android:translateX="12"
-+        android:translateY="15" >
-+        <group
-+            android:name="rectangle_3"
-+            android:rotation="45" >
-+            <group
-+                android:name="rectangle_2_pivot_0"
-+                android:translateY="4" >
-+                <group
-+                    android:name="rectangle_path_3_position"
-+                    android:translateY="-1" >
-+                    <path
-+                        android:name="rectangle_path_3"
-+                        android:fillColor="#FFFFFFFF"
-+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
-+                </group>
-+            </group>
-+        </group>
-+        <group
-+            android:name="rectangle_4"
-+            android:rotation="-45" >
-+            <group
-+                android:name="rectangle_1_pivot_0"
-+                android:translateY="-4" >
-+                <group
-+                    android:name="rectangle_path_4_position"
-+                    android:translateY="1" >
-+                    <path
-+                        android:name="rectangle_path_4"
-+                        android:fillColor="#FFFFFFFF"
-+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
-+                </group>
-+            </group>
-+        </group>
-+    </group>
-+
-+</vector>
-diff --git a/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml b/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
-new file mode 100644
-index 0000000..b561ee0
---- /dev/null
-+++ b/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
-@@ -0,0 +1,29 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:drawable="@drawable/ic_qs_expand" >
-+
-+    <target
-+        android:name="chevron_01"
-+        android:animation="@anim/ic_qs_expand_chevron_01_animation" />
-+    <target
-+        android:name="rectangle_3"
-+        android:animation="@anim/ic_qs_expand_rectangle_3_animation" />
-+    <target
-+        android:name="rectangle_4"
-+        android:animation="@anim/ic_qs_expand_rectangle_4_animation" />
-+
-+</animated-vector>
-diff --git a/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
-new file mode 100644
-index 0000000..c3930e4
---- /dev/null
-+++ b/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
-@@ -0,0 +1,17 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
-diff --git a/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
-new file mode 100644
-index 0000000..c3930e4
---- /dev/null
-+++ b/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
-@@ -0,0 +1,17 @@
-+<!--
-+     Copyright (C) 2015 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.
-+-->
-+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-+    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
-diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
-index a295cfa..0f04c28 100644
---- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
-+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
-@@ -57,11 +57,11 @@ public class ExpandableIndicator extends ImageView {
-     private int getDrawableResourceId(boolean expanded) {
-         if (mIsDefaultDirection) {
--            return expanded ? R.drawable.ic_volume_collapse_animation
--                    : R.drawable.ic_volume_expand_animation;
-+            return expanded ? R.drawable.ic_qs_collapse_animation
-+                    : R.drawable.ic_qs_expand_animation;
-         } else {
--            return expanded ? R.drawable.ic_volume_expand_animation
--                    : R.drawable.ic_volume_collapse_animation;
-+            return expanded ? R.drawable.ic_qs_expand_animation
-+                    : R.drawable.ic_qs_collapse_animation;
-         }
-     }
--- 
-2.9.3
-
diff --git a/frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch b/frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch
deleted file mode 100644 (file)
index 88df6a0..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-From 429a491bac8c8e3966f9afa5cc80becdb4677f9e Mon Sep 17 00:00:00 2001
-From: 0xD34D <clark@scheffsblend.com>
-Date: Mon, 9 Jan 2017 07:19:41 +0530
-Subject: [PATCH 24/38] N-Extras: Add dynamic theme BootAnimation support
-
-Extracted from "Themes: Port to CM13 [1/3]"
-http://review.cyanogenmod.org/#/c/113273/14
-
-Change-Id: I394897c10f02695f0416e87e9bf960e840bcb3b7
----
- cmds/bootanimation/BootAnimation.cpp | 13 ++++++++++---
- cmds/bootanimation/BootAnimation.h   |  3 ++-
- 2 files changed, 12 insertions(+), 4 deletions(-)
-
-diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
-index c6b2f63..f374ece 100644
---- a/cmds/bootanimation/BootAnimation.cpp
-+++ b/cmds/bootanimation/BootAnimation.cpp
-@@ -68,6 +68,7 @@ namespace android {
- static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
- static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
- static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
-+static const char THEME_BOOTANIMATION_FILE[] = "/data/system/theme/bootanimation.zip";
- static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
- static const char SYSTEM_TIME_DIR_NAME[] = "time";
- static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
-@@ -317,13 +318,14 @@ status_t BootAnimation::initTexture(SkBitmap *bitmap)
- // Get bootup Animation File
--// Parameter: ImageID: IMG_OEM IMG_SYS IMG_ENC
-+// Parameter: ImageID: IMG_OEM IMG_SYS IMG_ENC IMG_THM
- // Return Value : File path
- const char *BootAnimation::getAnimationFileName(ImageID image)
- {
--    const char *fileName[3] = { OEM_BOOTANIMATION_FILE,
-+    const char *fileName[4] = { OEM_BOOTANIMATION_FILE,
-             SYSTEM_BOOTANIMATION_FILE,
--            SYSTEM_ENCRYPTED_BOOTANIMATION_FILE };
-+            SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,
-+            THEME_BOOTANIMATION_FILE };
-     // Load animations of Carrier through regionalization environment
-     if (Environment::isSupported()) {
-@@ -408,6 +410,9 @@ status_t BootAnimation::readyToRun() {
-     if (encryptedAnimation && (access(getAnimationFileName(IMG_ENC), R_OK) == 0)) {
-         mZipFileName = getAnimationFileName(IMG_ENC);
-     }
-+    else if (access(getAnimationFileName(IMG_THM), R_OK) == 0) {
-+        mZipFileName = getAnimationFileName(IMG_THM);
-+    }
-     else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0) {
-         mZipFileName = getAnimationFileName(IMG_OEM);
-     }
-@@ -421,6 +426,8 @@ status_t BootAnimation::readyToRun() {
-     FILE* fd;
-     if (encryptedAnimation && access(getAnimationFileName(IMG_ENC), R_OK) == 0)
-         fd = fopen(getAnimationFileName(IMG_ENC), "r");
-+    else if (access(getAnimationFileName(IMG_THM), R_OK) == 0)
-+        fd = fopen(getAnimationFileName(IMG_THM), "r");
-     else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0)
-         fd = fopen(getAnimationFileName(IMG_OEM), "r");
-     else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0)
-diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
-index b70cc0e..958a022 100644
---- a/cmds/bootanimation/BootAnimation.h
-+++ b/cmds/bootanimation/BootAnimation.h
-@@ -122,8 +122,9 @@ private:
-      *IMG_OEM: bootanimation file from oem/media
-      *IMG_SYS: bootanimation file from system/media
-      *IMG_ENC: encrypted bootanimation file from system/media
-+     *IMG_THM: bootanimation file from data/system/theme
-      */
--    enum ImageID { IMG_OEM = 0, IMG_SYS = 1, IMG_ENC = 2 };
-+    enum ImageID { IMG_OEM = 0, IMG_SYS = 1, IMG_ENC = 2, IMG_THM = 3 };
-     const char *getAnimationFileName(ImageID image);
-     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
-     status_t initTexture(const Animation::Frame& frame);
--- 
-2.9.3
-
diff --git a/frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch b/frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch
deleted file mode 100644 (file)
index 9eb6494..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-From fd877629e3a2d8bfdafb1ba1371237396ba176e1 Mon Sep 17 00:00:00 2001
-From: 0xD34D <clark@scheffsblend.com>
-Date: Wed, 22 Jun 2016 23:54:23 +0300
-Subject: [PATCH 25/38] N-Extras: Add dynamic theme fonts support
-
-Due to the nature of the removal of assetSeq in OMS7+, we now use the
-more controllable font scale updating code to update the fonts on
-demand.
-
-Extracted from Themes: Port to CM13 [1/3]
-http://review.cyanogenmod.org/#/c/113273/14
-
-Squashed:
-
-Small adjustment to Font commit
-Author camcory
-https://github.com/SubstratumResources/platform_frameworks_base/commit/a13f088dff70bc52f2053f32acff47a7a377a807
-
-Themes: Ensure themed fonts always have fallbacks
-Author 0xD34D
-https://github.com/CyanogenMod/android_frameworks_base/commit/18b301874e2a658eb01f97defd70da038521f450
-
-Themes: Let garbage collector free up native instances
-Author 0xD34D
-https://github.com/CyanogenMod/android_frameworks_base/commit/b7108ea9ce7ad2226aa6340046d24e069c6e8e21
-
-Themes: Make parse() method in FontListParser public
-Author 0xD34D
-https://github.com/CyanogenMod/android_frameworks_base/commit/b3ae4609f2754fd156e34dfbf39551041e976031
-
-Fonts: add sans-serif fallback fonts first
-Author 0xD34D
-https://github.com/CyanogenMod/android_frameworks_base/commit/f1d7b86dd267ed5b59e51339edc4553d37561a39
-
-Themes: Add config change flag for font change
-Author 0xD34D
-https://github.com/CyanogenMod/android_frameworks_base/commit/2ec1a33b70d3c013daa956696b68167a5eeef70d
-
-Themes: don't recreateDefaults on typeface when locale changes
-Author romanbb
-https://github.com/CyanogenMod/android_frameworks_base/commit/e05ffea4ea55a4eb6b40436a864a570509eb33ac
-
-Change-Id: I1f61bd269b42ab6145482a51d25fe5b1b5308f94
----
- core/java/android/app/ActivityThread.java          |   7 +-
- core/java/android/content/pm/ActivityInfo.java     |   5 +
- core/java/android/content/res/Configuration.java   |   5 +-
- core/java/android/os/Process.java                  |   7 +-
- .../com/android/internal/os/ZygoteConnection.java  |  10 ++
- graphics/java/android/graphics/FontListParser.java |  48 ++++--
- graphics/java/android/graphics/Typeface.java       | 174 +++++++++++++++++++--
- .../android/server/am/ActivityManagerService.java  |  11 +-
- 8 files changed, 240 insertions(+), 27 deletions(-)
-
-diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
-index 55fc25d..44a900b 100644
---- a/core/java/android/app/ActivityThread.java
-+++ b/core/java/android/app/ActivityThread.java
-@@ -48,6 +48,7 @@ import android.database.sqlite.SQLiteDebug;
- import android.database.sqlite.SQLiteDebug.DbStats;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
-+import android.graphics.Typeface;
- import android.hardware.display.DisplayManagerGlobal;
- import android.net.ConnectivityManager;
- import android.net.IConnectivityManager;
-@@ -4852,8 +4853,12 @@ public final class ActivityThread {
-         if (configDiff != 0) {
-             // Ask text layout engine to free its caches if there is a locale change
-             boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
--            if (hasLocaleConfigChange) {
-+            boolean hasFontConfigChange = ((configDiff & ActivityInfo.CONFIG_THEME_FONT) != 0);
-+            if (hasLocaleConfigChange || hasFontConfigChange) {
-                 Canvas.freeTextLayoutCaches();
-+                if (hasFontConfigChange) {
-+                    Typeface.recreateDefaults();
-+                }
-                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
-             }
-         }
-diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
-index 5a09c00..42febcf 100644
---- a/core/java/android/content/pm/ActivityInfo.java
-+++ b/core/java/android/content/pm/ActivityInfo.java
-@@ -624,6 +624,11 @@ public class ActivityInfo extends ComponentInfo
-      */
-     public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
-     /**
-+     * Bit in {@link #configChanges} that indicates a font change occurred
-+     * @hide
-+     */
-+    public static final int CONFIG_THEME_FONT = 0x200000;
-+    /**
-      * Bit in {@link #configChanges} that indicates that the activity
-      * can itself handle changes to the font scaling factor.  Set from the
-      * {@link android.R.attr#configChanges} attribute.  This is
-diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
-index b2d518c..2f7c3ec 100644
---- a/core/java/android/content/res/Configuration.java
-+++ b/core/java/android/content/res/Configuration.java
-@@ -955,6 +955,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
-         int changed = 0;
-         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
-             changed |= ActivityInfo.CONFIG_FONT_SCALE;
-+            changed |= ActivityInfo.CONFIG_THEME_FONT;
-             fontScale = delta.fontScale;
-         }
-         if (delta.mcc != 0 && mcc != delta.mcc) {
-@@ -1121,6 +1122,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
-         int changed = 0;
-         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
-             changed |= ActivityInfo.CONFIG_FONT_SCALE;
-+            changed |= ActivityInfo.CONFIG_THEME_FONT;
-         }
-         if (delta.mcc != 0 && mcc != delta.mcc) {
-             changed |= ActivityInfo.CONFIG_MCC;
-@@ -1211,7 +1213,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
-      */
-     public static boolean needNewResources(@Config int configChanges,
-             @Config int interestingChanges) {
--        return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
-+        return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE|
-+                    ActivityInfo.CONFIG_THEME_FONT)) != 0;
-     }
-     /**
-diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
-index e1b7fda..6dcd045 100644
---- a/core/java/android/os/Process.java
-+++ b/core/java/android/os/Process.java
-@@ -516,11 +516,12 @@ public class Process {
-                                   String abi,
-                                   String instructionSet,
-                                   String appDataDir,
-+                                  boolean refreshTheme,
-                                   String[] zygoteArgs) {
-         try {
-             return startViaZygote(processClass, niceName, uid, gid, gids,
-                     debugFlags, mountExternal, targetSdkVersion, seInfo,
--                    abi, instructionSet, appDataDir, zygoteArgs);
-+                    abi, instructionSet, appDataDir, refreshTheme, zygoteArgs);
-         } catch (ZygoteStartFailedEx ex) {
-             Log.e(LOG_TAG,
-                     "Starting VM process through Zygote failed");
-@@ -648,6 +649,7 @@ public class Process {
-                                   String abi,
-                                   String instructionSet,
-                                   String appDataDir,
-+                                  boolean refreshTheme,
-                                   String[] extraArgs)
-                                   throws ZygoteStartFailedEx {
-         synchronized(Process.class) {
-@@ -689,6 +691,9 @@ public class Process {
-             } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
-                 argsForZygote.add("--mount-external-write");
-             }
-+            if (refreshTheme) {
-+                argsForZygote.add("--refresh_theme");
-+            }
-             argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
-             //TODO optionally enable debuger
-diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
-index 85d84bb..81257f0 100644
---- a/core/java/com/android/internal/os/ZygoteConnection.java
-+++ b/core/java/com/android/internal/os/ZygoteConnection.java
-@@ -22,6 +22,7 @@ import static android.system.OsConstants.STDERR_FILENO;
- import static android.system.OsConstants.STDIN_FILENO;
- import static android.system.OsConstants.STDOUT_FILENO;
-+import android.graphics.Typeface;
- import android.net.Credentials;
- import android.net.LocalSocket;
- import android.os.Process;
-@@ -194,6 +195,10 @@ class ZygoteConnection {
-                 Os.fcntlInt(childPipeFd, F_SETFD, 0);
-             }
-+            if (parsedArgs.refreshTheme) {
-+                Typeface.recreateDefaults();
-+            }
-+
-             /**
-              * In order to avoid leaking descriptors to the Zygote child,
-              * the native code must close the two Zygote socket descriptors
-@@ -373,6 +378,9 @@ class ZygoteConnection {
-          */
-         String appDataDir;
-+        /** from --refresh_theme */
-+        boolean refreshTheme;
-+
-         /**
-          * Constructs instance and parses args
-          * @param args zygote command-line args
-@@ -531,6 +539,8 @@ class ZygoteConnection {
-                     instructionSet = arg.substring(arg.indexOf('=') + 1);
-                 } else if (arg.startsWith("--app-data-dir=")) {
-                     appDataDir = arg.substring(arg.indexOf('=') + 1);
-+                } else if (arg.equals("--refresh_theme")) {
-+                    refreshTheme = true;
-                 } else {
-                     break;
-                 }
-diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
-index 7871aa8..f4590c9 100644
---- a/graphics/java/android/graphics/FontListParser.java
-+++ b/graphics/java/android/graphics/FontListParser.java
-@@ -21,6 +21,9 @@ import android.util.Xml;
- import org.xmlpull.v1.XmlPullParser;
- import org.xmlpull.v1.XmlPullParserException;
-+import java.io.BufferedInputStream;
-+import java.io.File;
-+import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.ArrayList;
-@@ -88,18 +91,41 @@ public class FontListParser {
-     }
-     /* Parse fallback list (no names) */
--    public static Config parse(InputStream in) throws XmlPullParserException, IOException {
-+    public static Config parse(File configFilename, String fontDir)
-+            throws XmlPullParserException, IOException {
-+        FileInputStream in = null;
-+        in = new FileInputStream(configFilename);
-+        return FontListParser.parse(in, fontDir);
-+    }
-+
-+    /* Parse fallback list (no names) */
-+    public static Config parse(InputStream in, String fontDir)
-+            throws XmlPullParserException, IOException {
-+        BufferedInputStream bis = null;
-         try {
-+            // wrap input stream in a BufferedInputStream, if it's not already, for mark support
-+            if (!(in instanceof BufferedInputStream)) {
-+                bis = new BufferedInputStream(in);
-+            } else {
-+                bis = (BufferedInputStream) in;
-+            }
-+            // mark the beginning so we can reset to this position after checking format
-+            bis.mark(in.available());
-+            return parseNormalFormat(bis, fontDir);
-+        } finally {
-+            if (bis != null) bis.close();
-+        }
-+    }
-+
-+    public static Config parseNormalFormat(InputStream in, String dirName)
-+            throws XmlPullParserException, IOException {
-             XmlPullParser parser = Xml.newPullParser();
-             parser.setInput(in, null);
-             parser.nextTag();
--            return readFamilies(parser);
--        } finally {
--            in.close();
--        }
-+            return readFamilies(parser, dirName);
-     }
--    private static Config readFamilies(XmlPullParser parser)
-+    private static Config readFamilies(XmlPullParser parser, String dirPath)
-             throws XmlPullParserException, IOException {
-         Config config = new Config();
-         parser.require(XmlPullParser.START_TAG, null, "familyset");
-@@ -107,7 +133,7 @@ public class FontListParser {
-             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
-             String tag = parser.getName();
-             if (tag.equals("family")) {
--                config.families.add(readFamily(parser));
-+                config.families.add(readFamily(parser, dirPath));
-             } else if (tag.equals("alias")) {
-                 config.aliases.add(readAlias(parser));
-             } else {
-@@ -117,7 +143,7 @@ public class FontListParser {
-         return config;
-     }
--    private static Family readFamily(XmlPullParser parser)
-+    private static Family readFamily(XmlPullParser parser, String dirPath)
-             throws XmlPullParserException, IOException {
-         String name = parser.getAttributeValue(null, "name");
-         String lang = parser.getAttributeValue(null, "lang");
-@@ -127,7 +153,7 @@ public class FontListParser {
-             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
-             String tag = parser.getName();
-             if (tag.equals("font")) {
--                fonts.add(readFont(parser));
-+                fonts.add(readFont(parser, dirPath));
-             } else {
-                 skip(parser);
-             }
-@@ -139,7 +165,7 @@ public class FontListParser {
-     private static final Pattern FILENAME_WHITESPACE_PATTERN =
-             Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
--    private static Font readFont(XmlPullParser parser)
-+    private static Font readFont(XmlPullParser parser, String dirPath)
-             throws XmlPullParserException, IOException {
-         String indexStr = parser.getAttributeValue(null, "index");
-         int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
-@@ -160,7 +186,7 @@ public class FontListParser {
-                 skip(parser);
-             }
-         }
--        String fullFilename = "/system/fonts/" +
-+        String fullFilename = dirPath + File.separatorChar +
-                 FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
-         return new Font(fullFilename, index, axes, weight, isItalic);
-     }
-diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
-index 2886f0d..990c9bd 100644
---- a/graphics/java/android/graphics/Typeface.java
-+++ b/graphics/java/android/graphics/Typeface.java
-@@ -17,6 +17,7 @@
- package android.graphics;
- import android.content.res.AssetManager;
-+import android.graphics.FontListParser.Family;
- import android.util.Log;
- import android.util.LongSparseArray;
- import android.util.LruCache;
-@@ -75,6 +76,8 @@ public class Typeface {
-     static final String FONTS_CONFIG = "fonts.xml";
-+    static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
-+
-     /**
-      * @hide
-      */
-@@ -88,6 +91,13 @@ public class Typeface {
-     private int mStyle = 0;
-+    // Typefaces that we can garbage collect when changing fonts, and so we don't break public APIs
-+    private static Typeface DEFAULT_INTERNAL;
-+    private static Typeface DEFAULT_BOLD_INTERNAL;
-+    private static Typeface SANS_SERIF_INTERNAL;
-+    private static Typeface SERIF_INTERNAL;
-+    private static Typeface MONOSPACE_INTERNAL;
-+
-     private static void setDefault(Typeface t) {
-         sDefaultTypeface = t;
-         nativeSetDefault(t.native_instance);
-@@ -263,7 +273,10 @@ public class Typeface {
-         for (int i = 0; i < families.length; i++) {
-             ptrArray[i] = families[i].mNativePtr;
-         }
--        return new Typeface(nativeCreateFromArray(ptrArray));
-+
-+
-+        Typeface typeface = new Typeface(nativeCreateFromArray(ptrArray));
-+        return typeface;
-     }
-     /**
-@@ -318,6 +331,73 @@ public class Typeface {
-         return fontFamily;
-     }
-+    /**
-+     * Adds the family from src with the name familyName as a fallback font in dst
-+     * @param src Source font config
-+     * @param dst Destination font config
-+     * @param familyName Name of family to add as a fallback
-+     */
-+    private static void addFallbackFontsForFamilyName(FontListParser.Config src,
-+            FontListParser.Config dst, String familyName) {
-+        for (Family srcFamily : src.families) {
-+            if (familyName.equals(srcFamily.name)) {
-+                // set the name to null so that it will be added as a fallback
-+                srcFamily.name = null;
-+                dst.families.add(srcFamily);
-+                return;
-+            }
-+        }
-+    }
-+
-+    /**
-+     * Adds any font families in src that do not exist in dst
-+     * @param src Source font config
-+     * @param dst Destination font config
-+     */
-+    private static void addMissingFontFamilies(FontListParser.Config src,
-+            FontListParser.Config dst) {
-+        final int N = dst.families.size();
-+        // add missing families
-+        for (Family srcFamily : src.families) {
-+            boolean addFamily = true;
-+            for (int i = 0; i < N && addFamily; i++) {
-+                final Family dstFamily = dst.families.get(i);
-+                final String dstFamilyName = dstFamily.name;
-+                if (dstFamilyName != null && dstFamilyName.equals(srcFamily.name)) {
-+                    addFamily = false;
-+                    break;
-+                }
-+            }
-+            if (addFamily) {
-+                dst.families.add(srcFamily);
-+            }
-+        }
-+    }
-+
-+    /**
-+     * Adds any aliases in src that do not exist in dst
-+     * @param src Source font config
-+     * @param dst Destination font config
-+     */
-+    private static void addMissingFontAliases(FontListParser.Config src,
-+            FontListParser.Config dst) {
-+        final int N = dst.aliases.size();
-+        // add missing aliases
-+        for (FontListParser.Alias alias : src.aliases) {
-+            boolean addAlias = true;
-+            for (int i = 0; i < N && addAlias; i++) {
-+                final String dstAliasName = dst.aliases.get(i).name;
-+                if (dstAliasName != null && dstAliasName.equals(alias.name)) {
-+                    addAlias = false;
-+                    break;
-+                }
-+            }
-+            if (addAlias) {
-+                dst.aliases.add(alias);
-+            }
-+        }
-+    }
-+
-     /*
-      * (non-Javadoc)
-      *
-@@ -326,10 +406,36 @@ public class Typeface {
-     private static void init() {
-         // Load font config and initialize Minikin state
-         File systemFontConfigLocation = getSystemFontConfigLocation();
--        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
-+        File themeFontConfigLocation = getThemeFontConfigLocation();
-+
-+        File systemConfigFile = new File(systemFontConfigLocation, FONTS_CONFIG);
-+        File themeConfigFile = new File(themeFontConfigLocation, FONTS_CONFIG);
-+        File configFile = null;
-+        File fontDir;
-+
-+        if (themeConfigFile.exists()) {
-+            configFile = themeConfigFile;
-+            fontDir = getThemeFontDirLocation();
-+        } else {
-+            configFile = systemConfigFile;
-+            fontDir = getSystemFontDirLocation();
-+        }
-+
-         try {
--            FileInputStream fontsIn = new FileInputStream(configFilename);
--            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
-+            FontListParser.Config fontConfig = FontListParser.parse(configFile,
-+                    fontDir.getAbsolutePath());
-+            FontListParser.Config systemFontConfig = null;
-+
-+            // If the fonts are coming from a theme, we will need to make sure that we include
-+            // any font families from the system fonts that the theme did not include.
-+            // NOTE: All the system font families without names ALWAYS get added.
-+            if (configFile == themeConfigFile) {
-+                systemFontConfig = FontListParser.parse(systemConfigFile,
-+                        getSystemFontDirLocation().getAbsolutePath());
-+                addFallbackFontsForFamilyName(systemFontConfig, fontConfig, SANS_SERIF_FAMILY_NAME);
-+                addMissingFontFamilies(systemFontConfig, fontConfig);
-+                addMissingFontAliases(systemFontConfig, fontConfig);
-+            }
-             Map<String, ByteBuffer> bufferForPath = new HashMap<String, ByteBuffer>();
-@@ -342,6 +448,7 @@ public class Typeface {
-                     familyList.add(makeFamilyFromParsed(f, bufferForPath));
-                 }
-             }
-+
-             sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
-             setDefault(Typeface.createFromFamilies(sFallbackFonts));
-@@ -377,22 +484,53 @@ public class Typeface {
-             Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
-             // TODO: normal in non-Minikin case, remove or make error when Minikin-only
-         } catch (FileNotFoundException e) {
--            Log.e(TAG, "Error opening " + configFilename, e);
-+            Log.e(TAG, "Error opening " + configFile, e);
-         } catch (IOException e) {
--            Log.e(TAG, "Error reading " + configFilename, e);
-+            Log.e(TAG, "Error reading " + configFile, e);
-         } catch (XmlPullParserException e) {
--            Log.e(TAG, "XML parse exception for " + configFilename, e);
-+            Log.e(TAG, "XML parse exception for " + configFile, e);
-         }
-     }
-+    /**
-+     * Clears caches in java and skia.
-+     * Skia will then reparse font config
-+     * @hide
-+     */
-+    public static void recreateDefaults() {
-+        sTypefaceCache.clear();
-+        sSystemFontMap.clear();
-+        init();
-+
-+        DEFAULT_INTERNAL = create((String) null, 0);
-+        DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
-+        SANS_SERIF_INTERNAL = create("sans-serif", 0);
-+        SERIF_INTERNAL = create("serif", 0);
-+        MONOSPACE_INTERNAL = create("monospace", 0);
-+
-+        DEFAULT.native_instance = DEFAULT_INTERNAL.native_instance;
-+        DEFAULT_BOLD.native_instance = DEFAULT_BOLD_INTERNAL.native_instance;
-+        SANS_SERIF.native_instance = SANS_SERIF_INTERNAL.native_instance;
-+        SERIF.native_instance = SERIF_INTERNAL.native_instance;
-+        MONOSPACE.native_instance = MONOSPACE_INTERNAL.native_instance;
-+        sDefaults[2] = create((String) null, Typeface.ITALIC);
-+        sDefaults[3] = create((String) null, Typeface.BOLD_ITALIC);
-+    }
-+
-     static {
-         init();
-         // Set up defaults and typefaces exposed in public API
--        DEFAULT         = create((String) null, 0);
--        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
--        SANS_SERIF      = create("sans-serif", 0);
--        SERIF           = create("serif", 0);
--        MONOSPACE       = create("monospace", 0);
-+        DEFAULT_INTERNAL         = create((String) null, 0);
-+        DEFAULT_BOLD_INTERNAL    = create((String) null, Typeface.BOLD);
-+        SANS_SERIF_INTERNAL      = create("sans-serif", 0);
-+        SERIF_INTERNAL           = create("serif", 0);
-+        MONOSPACE_INTERNAL       = create("monospace", 0);
-+
-+        DEFAULT         = new Typeface(DEFAULT_INTERNAL.native_instance);
-+        DEFAULT_BOLD    = new Typeface(DEFAULT_BOLD_INTERNAL.native_instance);
-+        SANS_SERIF      = new Typeface(SANS_SERIF_INTERNAL.native_instance);
-+        SERIF           = new Typeface(SERIF_INTERNAL.native_instance);
-+        MONOSPACE       = new Typeface(MONOSPACE_INTERNAL.native_instance);
-         sDefaults = new Typeface[] {
-             DEFAULT,
-@@ -407,6 +545,18 @@ public class Typeface {
-         return new File("/system/etc/");
-     }
-+    private static File getSystemFontDirLocation() {
-+        return new File("/system/fonts/");
-+    }
-+
-+    private static File getThemeFontConfigLocation() {
-+        return new File("/data/system/theme/fonts/");
-+    }
-+
-+    private static File getThemeFontDirLocation() {
-+        return new File("/data/system/theme/fonts/");
-+    }
-+
-     @Override
-     protected void finalize() throws Throwable {
-         try {
-diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
-index 2822dc9..ab010d4 100644
---- a/services/core/java/com/android/server/am/ActivityManagerService.java
-+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
-@@ -512,6 +512,8 @@ public final class ActivityManagerService extends ActivityManagerNative
-     // as one line, but close enough for now.
-     static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
-+    static final String PROP_REFRESH_THEME = "sys.refresh_theme";
-+
-     // Access modes for handleIncomingUser.
-     static final int ALLOW_NON_FULL = 0;
-     static final int ALLOW_NON_FULL_IN_PROFILE = 1;
-@@ -3947,6 +3949,13 @@ public final class ActivityManagerService extends ActivityManagerNative
-                 mNativeDebuggingApp = null;
-             }
-+            //Check if zygote should refresh its fonts
-+            boolean refreshTheme = false;
-+            if (SystemProperties.getBoolean(PROP_REFRESH_THEME, false)) {
-+                SystemProperties.set(PROP_REFRESH_THEME, "false");
-+                refreshTheme = true;
-+            }
-+
-             String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
-             if (requiredAbi == null) {
-                 requiredAbi = Build.SUPPORTED_ABIS[0];
-@@ -3971,7 +3980,7 @@ public final class ActivityManagerService extends ActivityManagerNative
-             Process.ProcessStartResult startResult = Process.start(entryPoint,
-                     app.processName, uid, uid, gids, debugFlags, mountExternal,
-                     app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
--                    app.info.dataDir, entryPointArgs);
-+                    app.info.dataDir, refreshTheme, entryPointArgs);
-             checkTime(startTime, "startProcess: returned from zygote!");
-             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
--- 
-2.9.3
-
diff --git a/frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch b/frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch
deleted file mode 100644 (file)
index d0bc5f5..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-From f3f83a64481e2abdf561f7c42d7f2e7d5f32012b Mon Sep 17 00:00:00 2001
-From: Nicholas Chum <nicholaschum@gmail.com>
-Date: Sun, 17 Jul 2016 17:56:40 -0400
-Subject: [PATCH 26/38] N-Extras: AudioService: Allow system effect sounds to
- be themed
-
-This commit checks whether there is a preexisting file in the themed
-directory "/data/system/theme/audio/ui/" and if so, change the base
-file paths for the sound. If the file does not exist in the theme
-directory, then use the default sounds.
-
-At the current moment, this will require a soft reboot to work.
-
-Change-Id: I7666c2bd259443ccec442bf6059786bea3dc069e
----
- .../com/android/server/audio/AudioService.java     | 26 +++++++++++++++++-----
- 1 file changed, 21 insertions(+), 5 deletions(-)
-
-diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
-index cd766af..2e3d5a6 100644
---- a/services/core/java/com/android/server/audio/AudioService.java
-+++ b/services/core/java/com/android/server/audio/AudioService.java
-@@ -123,6 +123,7 @@ import com.android.server.pm.UserManagerService;
- import org.xmlpull.v1.XmlPullParserException;
-+import java.io.File;
- import java.io.FileDescriptor;
- import java.io.IOException;
- import java.io.PrintWriter;
-@@ -281,6 +282,7 @@ public class AudioService extends IAudioService.Stub {
-     /* Sound effect file names  */
-     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
-+    private static final String SOUND_EFFECTS_THEMED_PATH = "/data/system/theme/audio/ui/";
-     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
-     /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
-@@ -4679,9 +4681,16 @@ public class AudioService extends IAudioService.Stub {
-                         continue;
-                     }
-                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
--                        String filePath = Environment.getRootDirectory()
--                                + SOUND_EFFECTS_PATH
--                                + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
-+                        String filePath = "";
-+                        File theme_file = new File(SOUND_EFFECTS_THEMED_PATH +
-+                            SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]));
-+                        if (theme_file.exists()) {
-+                            filePath = theme_file.getAbsolutePath();
-+                        } else {
-+                            filePath = Environment.getRootDirectory()
-+                                    + SOUND_EFFECTS_PATH
-+                                    + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
-+                        }
-                         int sampleId = mSoundPool.load(filePath, 0);
-                         if (sampleId <= 0) {
-                             Log.w(TAG, "Soundpool could not load file: "+filePath);
-@@ -4787,8 +4796,15 @@ public class AudioService extends IAudioService.Stub {
-                 } else {
-                     MediaPlayer mediaPlayer = new MediaPlayer();
-                     try {
--                        String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
--                                    SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
-+                        String filePath = "";
-+                        File theme_file = new File(SOUND_EFFECTS_THEMED_PATH +
-+                                    SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]));
-+                        if (theme_file.exists()) {
-+                            filePath = theme_file.getAbsolutePath();
-+                        } else {
-+                            filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
-+                                        SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
-+                        }
-                         mediaPlayer.setDataSource(filePath);
-                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
-                         mediaPlayer.prepare();
--- 
-2.9.3
-
diff --git a/frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch b/frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch
deleted file mode 100644 (file)
index 8e1dad6..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From 0b5d2c23c6f07c09a0181c76cc83cbb61da4d495 Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Mon, 4 Jul 2016 06:25:15 +0300
-Subject: [PATCH 27/38] OMS7-N: ApplicationsState: add filter for Substratum
- overlays [1/2]
-
-This commit allows the framework to handle the filtering of the
-overlays found for OMS.
-
-Change-Id: I7646115e8f73494d726728fac58cc47aafd69d5d
----
- .../settingslib/applications/ApplicationsState.java     | 17 +++++++++++++++--
- 1 file changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-index f0ec107..6fecd40 100644
---- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-@@ -137,9 +137,11 @@ public class ApplicationsState {
-         // Only the owner can see all apps.
-         mAdminRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
-                 PackageManager.GET_DISABLED_COMPONENTS |
--                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
-+                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
-+                PackageManager.GET_META_DATA;
-         mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
--                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
-+                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
-+                PackageManager.GET_META_DATA;
-         /**
-          * This is a trick to prevent the foreground thread from being delayed.
-@@ -1312,6 +1314,17 @@ public class ApplicationsState {
-         }
-     };
-+    public static final AppFilter FILTER_SUBSTRATUM = new AppFilter() {
-+        public void init() {
-+        }
-+
-+        @Override
-+        public boolean filterApp(AppEntry entry) {
-+            return !((entry.info.metaData != null) &&
-+                    (entry.info.metaData.getString("Substratum_Parent") != null));
-+        }
-+    };
-+
-     public static final AppFilter FILTER_WORK = new AppFilter() {
-         private int mCurrentUser;
--- 
-2.9.3
-
diff --git a/frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch b/frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch
deleted file mode 100644 (file)
index 8734985..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From db55a4020f8942389b3862ddb7442c5f50d62f15 Mon Sep 17 00:00:00 2001
-From: Kuba Schenk <abukcz@gmail.com>
-Date: Thu, 1 Dec 2016 21:48:26 +0100
-Subject: [PATCH 28/38] OMS7-N: ApplicationsState: add filter for Substratum
- icon overlays [1/2]
-
-This commit allows the framework to handle the filtering of the icon overlays found for OMS.
-
-Base this off the work from @KreAch3R
-
-Change-Id: I594c993977733e67f566ac65df50ad2e1bbdbdd3
-(cherry picked from commit 4d682464550f71e72e491934c78b8a42fdfc0348)
----
- .../android/settingslib/applications/ApplicationsState.java   | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
-diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-index 6fecd40..d3a6e21 100644
---- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
-@@ -1325,6 +1325,17 @@ public class ApplicationsState {
-         }
-     };
-+    public static final AppFilter FILTER_SUBSTRATUM_ICONS = new AppFilter() {
-+        public void init() {
-+        }
-+
-+        @Override
-+        public boolean filterApp(AppEntry entry) {
-+            return !((entry.info.metaData != null) &&
-+                    (entry.info.metaData.getString("Substratum_IconPack") != null));
-+        }
-+    };
-+
-     public static final AppFilter FILTER_WORK = new AppFilter() {
-         private int mCurrentUser;
--- 
-2.9.3
-
diff --git a/frameworks/base/0029-Themes-Expose-QS-battery.patch b/frameworks/base/0029-Themes-Expose-QS-battery.patch
deleted file mode 100644 (file)
index fe79dc3..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From da38273a4dc66c1f259b89430ffcb3c58db0e39c Mon Sep 17 00:00:00 2001
-From: Abdulwahab Isam <abdoi94.iq@gmail.com>
-Date: Fri, 7 Oct 2016 08:30:11 +0300
-Subject: [PATCH 29/38] Themes: Expose QS battery
-
-This is needed for white themes like Belo. Should function the same with dark themes as well.
-
-Change-Id: I65e3f777a2a2605a06260705f92f8617407d9005
----
- packages/SystemUI/res/layout/battery_detail.xml | 6 +++---
- packages/SystemUI/res/values/projekt_colors.xml | 6 ++++++
- 2 files changed, 9 insertions(+), 3 deletions(-)
-
-diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
-index 8abfcf6..af3acdc 100644
---- a/packages/SystemUI/res/layout/battery_detail.xml
-+++ b/packages/SystemUI/res/layout/battery_detail.xml
-@@ -27,7 +27,7 @@
-         android:layout_height="wrap_content"
-         android:paddingStart="16dp"
-         android:textAppearance="?android:attr/textAppearanceSmall"
--        android:textColor="?android:attr/colorAccent" />
-+        android:textColor="@color/qs_battery_text_color" />
-     <com.android.systemui.ResizingSpace
-         android:layout_width="match_parent"
-@@ -40,8 +40,8 @@
-         android:layout_marginStart="16dp"
-         android:layout_marginEnd="24dp"
-         systemui:sideLabels="@array/battery_labels"
--        android:colorAccent="?android:attr/colorAccent"
--        systemui:textColor="#66FFFFFF" />
-+        android:colorAccent="@color/qs_battery_accent"
-+        systemui:textColor="@color/qs_battery_graph_text_color" />
-     <com.android.systemui.ResizingSpace
-         android:layout_width="match_parent"
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-index 0f89199..83b8524 100644
---- a/packages/SystemUI/res/values/projekt_colors.xml
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -24,4 +24,10 @@
-     <color name="qs_alarm_status_text_color">#64ffffff</color>
-     <!-- QS edit page toolbar text color -->
-     <color name="qs_edit_toolbar_text_color">#FFFFFF</color>
-+    <!-- QS battery % text color -->
-+    <color name="qs_battery_text_color">@*android:color/accent_device_default_light</color>
-+    <!-- QS battery graph text color -->
-+    <color name="qs_battery_graph_text_color">#66FFFFFF</color>
-+    <!-- QS battery accent color -->
-+    <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
- </resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch b/frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch
deleted file mode 100644 (file)
index 6756897..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-From 4045dd2c0cbb895e8d430a9388d33b5596a9fd2b Mon Sep 17 00:00:00 2001
-From: bigrushdog <randall.rushing@gmail.com>
-Date: Mon, 19 Dec 2016 04:33:31 -0800
-Subject: [PATCH 30/38] OMS: Introduce MODIFY_OVERLAYS permission for user apps
-
-This permission will grant the app read and write permissions
-to access OverlayManagerService. If caller does not posess
-this permissions, OMS falls back to default permission checks
-
-Change-Id: Ib6b10b516577f338aee31e759bfd16278f902c20
-(cherry picked from commit 8e59c96513c573a4912492c005b076cb2a972332)
----
- core/res/AndroidManifest.xml                       |  6 +++++
- core/res/res/values/strings.xml                    |  5 +++++
- .../android/server/om/OverlayManagerService.java   | 26 +++++++++++++++-------
- 3 files changed, 29 insertions(+), 8 deletions(-)
-
-diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
-index 986be28..abed0df 100644
---- a/core/res/AndroidManifest.xml
-+++ b/core/res/AndroidManifest.xml
-@@ -3160,6 +3160,12 @@
-     <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
-                 android:protectionLevel="signature|privileged" />
-+    <!-- Allows an application to make calls to OverlayManagerService.-->
-+    <permission android:name="android.permission.MODIFY_OVERLAYS"
-+        android:label="@string/permlab_modifyOverlays"
-+        android:description="@string/permdesc_modifyOverlays"
-+        android:protectionLevel="normal" />
-+
-     <application android:process="system"
-                  android:persistent="true"
-                  android:hasCode="false"
-diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
-index 8f5f8cf..8313d5d 100644
---- a/core/res/res/values/strings.xml
-+++ b/core/res/res/values/strings.xml
-@@ -1411,6 +1411,11 @@
-     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-     <string name="permdesc_access_notification_policy">Allows the app to read and write Do Not Disturb configuration.</string>
-+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-+    <string name="permlab_modifyOverlays">modify theme overlays</string>
-+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-+    <string name="permdesc_modifyOverlays">Allows the app to make modifications to theme overlays using OverlayManagerService</string>
-+
-     <!-- Policy administration -->
-     <!-- Title of policy access to limiting the user's password choices -->
-diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
-index deb9046..e205ce1 100644
---- a/services/core/java/com/android/server/om/OverlayManagerService.java
-+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
-@@ -36,6 +36,7 @@ import android.content.om.IOverlayManager;
- import android.content.om.OverlayInfo;
- import android.content.pm.IPackageManager;
- import android.content.pm.PackageInfo;
-+import android.content.pm.PackageManager;
- import android.content.pm.PackageManagerInternal;
- import android.content.pm.UserInfo;
- import android.net.Uri;
-@@ -114,7 +115,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
-  *     the caller runs as, or if the caller holds the
-  *     INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
-  *     caller is granted read-access and additionaly holds the
-- *     CHANGE_CONFIGURATION permission.</li>
-+ *     CHANGE_CONFIGURATION permission. Additionally, read and write access
-+ *     is granted by the MODIFY_OVERLAYS permission.</li>
-  * </ul>
-  *
-  * <p>The AIDL interface works with String package names, int user IDs, and
-@@ -549,19 +551,24 @@ public final class OverlayManagerService extends SystemService {
-         /**
-          * Ensure that the caller has permission to interact with the given userId.
-          * If the calling user is not the same as the provided user, the caller needs
--         * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
-+         * to hold the INTERACT_ACROSS_USERS_FULL permission or MODIFY_OVERLAYS permission (or be system uid or
-          * root).
-          *
-          * @param userId the user to interact with
-          * @param message message for any SecurityException
-          */
-         private int handleIncomingUser(final int userId, @NonNull final String message) {
--            return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
--                    Binder.getCallingUid(), userId, false, true, message, null);
-+            if (getContext().checkCallingOrSelfPermission(
-+                    android.Manifest.permission.MODIFY_OVERLAYS) == PackageManager.PERMISSION_GRANTED) {
-+                return userId;
-+            } else {
-+                return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
-+                        Binder.getCallingUid(), userId, false, true, message, null);
-+            }
-         }
-         /**
--         * Enforce that the caller holds the CHANGE_CONFIGURATION permission (or is
-+         * Enforce that the caller holds the CHANGE_CONFIGURATION permission or MODIFY_OVERLAYS permission (or is
-          * system or root).
-          *
-          * @param message used as message if SecurityException is thrown
-@@ -570,9 +577,12 @@ public final class OverlayManagerService extends SystemService {
-         private void enforceChangeConfigurationPermission(@NonNull final String message) {
-             final int callingUid = Binder.getCallingUid();
--            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
--                getContext().enforceCallingOrSelfPermission(
--                        android.Manifest.permission.CHANGE_CONFIGURATION, message);
-+            if (getContext().checkCallingOrSelfPermission(
-+                    android.Manifest.permission.MODIFY_OVERLAYS) != PackageManager.PERMISSION_GRANTED) {
-+                if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
-+                    getContext().enforceCallingOrSelfPermission(
-+                            android.Manifest.permission.CHANGE_CONFIGURATION, message);
-+                }
-             }
-         }
--- 
-2.9.3
-
diff --git a/frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch b/frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch
deleted file mode 100644 (file)
index 91c2989..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From ee6b990018d29a124adc51e273d1fe0cf5fa66bc Mon Sep 17 00:00:00 2001
-From: daveyannihilation <daveyannihilation@hotmail.com>
-Date: Sun, 1 Jan 2017 01:47:53 -0700
-Subject: [PATCH 31/38] SystemUI: Expose switch bar title
-
-This is needed for the power notifications switchbar in SystemUI Tuner, amongst other things.
-
-Change-Id: I86f04840c2be46519509556b8d0061cefe26f631
----
- packages/SystemUI/res/layout/switch_bar.xml     |  3 +--
- packages/SystemUI/res/values/projekt_styles.xml | 24 ++++++++++++++++++++++++
- 2 files changed, 25 insertions(+), 2 deletions(-)
- create mode 100644 packages/SystemUI/res/values/projekt_styles.xml
-
-diff --git a/packages/SystemUI/res/layout/switch_bar.xml b/packages/SystemUI/res/layout/switch_bar.xml
-index 41cdb78..344c5aa 100644
---- a/packages/SystemUI/res/layout/switch_bar.xml
-+++ b/packages/SystemUI/res/layout/switch_bar.xml
-@@ -33,8 +33,7 @@
-         android:paddingStart="48dp"
-         android:maxLines="2"
-         android:ellipsize="end"
--        android:textAppearance="@android:style/TextAppearance.Material.Title"
--        android:textColor="?android:attr/textColorPrimaryInverse"
-+        android:textAppearance="@style/TextAppearance.SwitchBar"
-         android:textAlignment="viewStart"
-         android:text="@string/switch_bar_on" />
-diff --git a/packages/SystemUI/res/values/projekt_styles.xml b/packages/SystemUI/res/values/projekt_styles.xml
-new file mode 100644
-index 0000000..f49834b
---- /dev/null
-+++ b/packages/SystemUI/res/values/projekt_styles.xml
-@@ -0,0 +1,24 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Projekt Substratum
-+
-+    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>
-+    <!-- Switch bar text appearance -->
-+    <style name="TextAppearance.SwitchBar" parent="@android:style/TextAppearance.Material.Title">
-+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
-+    </style>
-+</resources>
-+
--- 
-2.9.3
-
diff --git a/frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch b/frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch
deleted file mode 100644 (file)
index a682146..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-From b865d57f51ef8545a434dfdfee32055954ce952b Mon Sep 17 00:00:00 2001
-From: Bryan Owens <djbryan3540@gmail.com>
-Date: Fri, 6 Jan 2017 21:12:15 +0800
-Subject: [PATCH 32/38] Themes: Expose manifest styles for themes
-
-Change-Id: Ie3a4fdead4f4fa1c121018b38de1c86a05bbcff2
----
- core/res/AndroidManifest.xml           | 20 ++++++++---------
- core/res/res/values/projekt_styles.xml | 41 ++++++++++++++++++++++++++++++++++
- 2 files changed, 51 insertions(+), 10 deletions(-)
- create mode 100644 core/res/res/values/projekt_styles.xml
-
-diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
-index abed0df..6ac87ca 100644
---- a/core/res/AndroidManifest.xml
-+++ b/core/res/AndroidManifest.xml
-@@ -3212,7 +3212,7 @@
-                 android:label="@string/managed_profile_label">
-         </activity-alias>
-         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-+                android:theme="@style/HeavyWeightSwitcherActivityTheme"
-                 android:label="@string/heavy_weight_switcher_title"
-                 android:finishOnCloseSystemDialogs="true"
-                 android:excludeFromRecents="true"
-@@ -3245,7 +3245,7 @@
-         <activity android:name="android.accounts.ChooseAccountActivity"
-                 android:excludeFromRecents="true"
-                 android:exported="true"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-+                android:theme="@style/ChooseAccountActivityTheme"
-                 android:label="@string/choose_account_label"
-                 android:process=":ui">
-         </activity>
-@@ -3253,14 +3253,14 @@
-         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
-                 android:excludeFromRecents="true"
-                 android:exported="true"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-+                android:theme="@style/ChooseTypeAndAccountActivityTheme"
-                 android:label="@string/choose_account_label"
-                 android:process=":ui">
-         </activity>
-         <activity android:name="android.accounts.ChooseAccountTypeActivity"
-                 android:excludeFromRecents="true"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-+                android:theme="@style/ChooseAccountTypeActivityTheme"
-                 android:label="@string/choose_account_label"
-                 android:process=":ui">
-         </activity>
-@@ -3268,19 +3268,19 @@
-         <activity android:name="android.accounts.CantAddAccountActivity"
-                 android:excludeFromRecents="true"
-                 android:exported="true"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
-+                android:theme="@style/CantAddAccountActivityTheme"
-                 android:process=":ui">
-         </activity>
-         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                 android:excludeFromRecents="true"
-                 android:exported="true"
--                android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
-+                android:theme="@style/GrantCredentialsPermissionActivityTheme"
-                 android:process=":ui">
-         </activity>
-         <activity android:name="android.content.SyncActivityTooManyDeletes"
--               android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-+               android:theme="@style/SyncActivityTooManyDeletesTheme"
-                android:label="@string/sync_too_many_deletes"
-                android:process=":ui">
-         </activity>
-@@ -3300,7 +3300,7 @@
-         </activity>
-         <activity android:name="com.android.internal.app.NetInitiatedActivity"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
-+                android:theme="@style/NetInitiatedActivityTheme"
-                 android:excludeFromRecents="true"
-                 android:process=":ui">
-         </activity>
-@@ -3321,7 +3321,7 @@
-         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
-                 android:excludeFromRecents="true"
-                 android:process=":ui"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
-+                android:theme="@style/ConfirmUserCreationActivityTheme">
-             <intent-filter android:priority="1000">
-                 <action android:name="android.os.action.CREATE_USER" />
-                 <category android:name="android.intent.category.DEFAULT" />
-@@ -3329,7 +3329,7 @@
-         </activity>
-         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
--                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
-+                android:theme="@style/UnlaunchableAppActivityTheme"
-                 android:excludeFromRecents="true"
-                 android:process=":ui">
-         </activity>
-diff --git a/core/res/res/values/projekt_styles.xml b/core/res/res/values/projekt_styles.xml
-new file mode 100644
-index 0000000..e5fe635
---- /dev/null
-+++ b/core/res/res/values/projekt_styles.xml
-@@ -0,0 +1,41 @@
-+<?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>
-+
-+    <!-- Exposed manifest styles -->
-+
-+    <style name="HeavyWeightSwitcherActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
-+
-+    <style name="ChooseAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
-+
-+    <style name="ChooseTypeAndAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
-+
-+    <style name="ChooseAccountTypeActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
-+
-+    <style name="CantAddAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
-+
-+    <style name="GrantCredentialsPermissionActivityTheme" parent="Theme.DeviceDefault.Light.DialogWhenLarge" />
-+
-+    <style name="SyncActivityTooManyDeletesTheme" parent="Theme.DeviceDefault.Light.Dialog" />
-+
-+    <style name="NetInitiatedActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
-+
-+    <style name="ConfirmUserCreationActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
-+
-+    <style name="UnlaunchableAppActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
-+
-+</resources>
--- 
-2.9.3
-
diff --git a/frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch b/frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch
deleted file mode 100644 (file)
index 8be7278..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From a33286e7a15b13bf4d8ac2aa9a779b8b888c9d2a Mon Sep 17 00:00:00 2001
-From: mickybart <mickybart@pygoscelis.org>
-Date: Sat, 19 Nov 2016 19:05:05 -0500
-Subject: [PATCH 33/38] OMS: StrictMode and files under /data/system/theme/
-
-Themes are using /data/system/theme/ to push some files like LowBattery.ogg (audio notification)
-When the device battery trigger the low battery state, the sound is not played due
-to StrictMode and SystemUI is crashing.
-
-So we need that StrictMode authorize files under /system OR /data/system/theme
-
-Logcat of the issue:
-
-E AndroidRuntime: Caused by: android.os.FileUriExposedException: file:///data/system/theme/audio/ui/LowBattery.ogg exposed beyond app through Notification.sound
-E AndroidRuntime:        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
-E AndroidRuntime:        at android.net.Uri.checkFileUriExposed(Uri.java:2346)
-E AndroidRuntime:        at android.app.NotificationManager.notifyAsUser(NotificationManager.java:300)
-
-Change-Id: I154dc4280de8eaf891772a9632283e9f547f5718
----
- core/java/android/net/Uri.java | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
-index 67378bd..4fb189e 100644
---- a/core/java/android/net/Uri.java
-+++ b/core/java/android/net/Uri.java
-@@ -2342,7 +2342,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
-      * @hide
-      */
-     public void checkFileUriExposed(String location) {
--        if ("file".equals(getScheme()) && !getPath().startsWith("/system/")) {
-+        if ("file".equals(getScheme()) && !(getPath().startsWith("/system/")
-+                || getPath().startsWith("/data/system/theme/"))) {
-             StrictMode.onFileUriExposed(this, location);
-         }
-     }
--- 
-2.9.3
-
diff --git a/frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch b/frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch
deleted file mode 100644 (file)
index 30f3445..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 82244aeb8e03cec7e5cbbcd89fef918ea3d151d2 Mon Sep 17 00:00:00 2001
-From: Daniel Koman <dankoman30@gmail.com>
-Date: Wed, 28 Sep 2016 15:28:26 +0200
-Subject: [PATCH 34/38] doze: allow grayscale even if invert boolean is false
-
-for dark themes, we are setting the config boolean for inverting
-    doze notifications to false.  in addition to preventing
-    color inversion, this was also preventing the notification
-    from grayscaling.  as a result, on dark themes (boolean false), we
-    were seeing color icons on doze notifications.  this commit fixes
-    the grayscaling, and brings back the very aesthetically pleasing
-    (imo) grayscale-to-color fade-in for the notifications' app icons.
-
-Change-Id: Ifc5efbccbeb02910684b76793721b10f1d64f870
----
- packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-index 605f381..16d46c0 100644
---- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-+++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
-@@ -92,7 +92,7 @@ public class ViewInvertHelper {
-     }
-     public void update(boolean invert) {
--        if (invert && mThemeInvert) {
-+        if (invert) {
-             updateInvertPaint(1f);
-             for (int i = 0; i < mTargets.size(); i++) {
-                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
-@@ -115,7 +115,9 @@ public class ViewInvertHelper {
-         mMatrix.set(invert);
-         mGrayscaleMatrix.setSaturation(1 - intensity);
-         mMatrix.preConcat(mGrayscaleMatrix);
--        mDarkPaint.setColorFilter(new ColorMatrixColorFilter(mMatrix));
-+        mDarkPaint.setColorFilter(new ColorMatrixColorFilter(
-+                mThemeInvert ? mMatrix : mGrayscaleMatrix));
-+
-     }
-     public void setInverted(boolean invert, boolean fade, long delay) {
--- 
-2.9.3
-
diff --git a/frameworks/base/0035-Expose-external-qs-tile-tint-color.patch b/frameworks/base/0035-Expose-external-qs-tile-tint-color.patch
deleted file mode 100644 (file)
index 7bc7c43..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From a71d0e0ea46b7d910dea2f9c0eafbab2b1e3ef24 Mon Sep 17 00:00:00 2001
-From: Alex Cruz <mazdarider23@gmail.com>
-Date: Tue, 24 Jan 2017 11:14:46 +0100
-Subject: [PATCH 35/38] Expose external qs tile tint color
-
-This should allow themers to get around issues like this (see pic below)
-
-https://i.imgur.com/cG2OzRT.jpg
-
-Change-Id: If6dbf9ab29f8007d85a3c45524b1cf4ba1b032fb
----
- packages/SystemUI/res/values/projekt_colors.xml                         | 2 ++
- .../SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java | 2 +-
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-index 83b8524..e31d124 100644
---- a/packages/SystemUI/res/values/projekt_colors.xml
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -30,4 +30,6 @@
-     <color name="qs_battery_graph_text_color">#66FFFFFF</color>
-     <!-- QS battery accent color -->
-     <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
-+    <!-- External QS tile tint color -->
-+    <color name="external_qs_tile_tint_color">@android:color/white</color>
- </resources>
-diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-index 0cd6490..6fabc61 100644
---- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-@@ -177,7 +177,7 @@ public class TileQueryHelper {
-                     continue;
-                 }
-                 icon.mutate();
--                icon.setTint(mContext.getColor(android.R.color.white));
-+                icon.setTint(mContext.getColor(R.color.external_qs_tile_tint_color));
-                 CharSequence label = info.serviceInfo.loadLabel(pm);
-                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
-             }
--- 
-2.9.3
-
diff --git a/frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch b/frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch
deleted file mode 100644 (file)
index c3b926f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From cd5423a1a675a6ac3986ac9960a6c9db8a386b0b Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Thu, 2 Feb 2017 01:52:27 +0200
-Subject: [PATCH 36/38] graphics: ADB "N" icon compatible with OMS7
-
-It's the same problem as the booleans again. This time, it affected the adb "N" icon in the statusbar.
-This commit should fix this.
-
-After: http://i.imgur.com/RPh6WKK.jpg
-
-Previous commits on the same matter:
-OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
-
-// Resources.getSystem Resources are created on request and aren't tracked by
-// mResourceReferences.
-//
-// If overlays targeting "android" are to be used, we must create the system
-// resources regardless of whether they already exist, since otherwise the
-// information on what overlays to use would be lost. This is wasteful for most
-// applications, so limit this operation to the system user only. (This means
-// Resources.getSystem() will *not* use overlays for applications.)
-
-Replaced deprecated Resources.getSystem() with compatible method.
-
-Change-Id: Ibab2ce1571360a9e03043d1bf3144c89e54e1947
----
- graphics/java/android/graphics/drawable/Icon.java | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
-index 2b950d3..fb26bee 100644
---- a/graphics/java/android/graphics/drawable/Icon.java
-+++ b/graphics/java/android/graphics/drawable/Icon.java
-@@ -294,7 +294,7 @@ public final class Icon implements Parcelable {
-                         resPackage = context.getPackageName();
-                     }
-                     if ("android".equals(resPackage)) {
--                        mObj1 = Resources.getSystem();
-+                        mObj1 = context.getResources();
-                     } else {
-                         final PackageManager pm = context.getPackageManager();
-                         try {
--- 
-2.9.3
-
diff --git a/frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch b/frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch
deleted file mode 100644 (file)
index 347da96..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From 1a4d5be7f78b87480be19243ae88e543a1b9db58 Mon Sep 17 00:00:00 2001
-From: Alex Cruz <mazdarider23@gmail.com>
-Date: Sat, 4 Feb 2017 14:13:26 +0100
-Subject: [PATCH 37/38] Set external QS tiles tint mode to SRC_ATOP
-
-While the external qs tile tint color was exposed, we had the same problem
-we had with the external icons in Settings which is if a themer set the color
-to transparent, they were SOL.
-
-This mirrors what @iskandar1023 did in the commit below
-http://review.projektsubstratum.com/#/c/286/
-
-Before - https://i.imgur.com/trpefmZ.png
-After - https://i.imgur.com/ugAqrju.png
-
-Change-Id: I6d577573dd494d61a3e87abebd919b02a481db56
----
- .../SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-index 6fabc61..dbdb614 100644
---- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
-@@ -23,6 +23,7 @@ import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.content.pm.ResolveInfo;
-+import android.graphics.PorterDuff.Mode;
- import android.graphics.drawable.Drawable;
- import android.os.AsyncTask;
- import android.os.Handler;
-@@ -178,6 +179,7 @@ public class TileQueryHelper {
-                 }
-                 icon.mutate();
-                 icon.setTint(mContext.getColor(R.color.external_qs_tile_tint_color));
-+                icon.setTintMode(Mode.SRC_ATOP);
-                 CharSequence label = info.serviceInfo.loadLabel(pm);
-                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
-             }
--- 
-2.9.3
-
diff --git a/frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch b/frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch
deleted file mode 100644 (file)
index 9abb843..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From c06669d9a78ed88300a59d9cb1e6f9555086e569 Mon Sep 17 00:00:00 2001
-From: Branden M <wasabi.dev@gmail.com>
-Date: Wed, 1 Feb 2017 22:22:45 -0600
-Subject: [PATCH 38/38] Themes: Expose Keyguard affordance circle background
-
-Change-Id: Id4a078cdbc944fa0c0736103045a0382d49ecb80
----
- packages/SystemUI/res/values/projekt_colors.xml                         | 2 ++
- .../src/com/android/systemui/statusbar/KeyguardAffordanceView.java      | 2 +-
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
-index e31d124..e8f8e50 100644
---- a/packages/SystemUI/res/values/projekt_colors.xml
-+++ b/packages/SystemUI/res/values/projekt_colors.xml
-@@ -32,4 +32,6 @@
-     <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
-     <!-- External QS tile tint color -->
-     <color name="external_qs_tile_tint_color">@android:color/white</color>
-+    <!-- Keyguard affordance circle background -->
-+    <color name="keyguard_affordance_circle_background">@android:color/white</color>
- </resources>
-diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
-index b94df1d..3d661b7 100644
---- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
-+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
-@@ -131,7 +131,7 @@ public class KeyguardAffordanceView extends ImageView implements Palette.Palette
-         super(context, attrs, defStyleAttr, defStyleRes);
-         mCirclePaint = new Paint();
-         mCirclePaint.setAntiAlias(true);
--        mCircleColor = 0xffffffff;
-+        mCircleColor = mContext.getResources().getColor(R.color.keyguard_affordance_circle_background);
-         mCirclePaint.setColor(mCircleColor);
-         mNormalColor = 0xffffffff;
--- 
-2.9.3
-
diff --git a/frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch b/frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch
deleted file mode 100644 (file)
index ec1ad89..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From 70dc365c2877d443aebb7da11f061fa3d69dd2a4 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Tue, 15 Dec 2015 14:02:30 +0100
-Subject: [PATCH] OMS-N: installd: add command 'rmidmap'
-
-Add an installd command to remove an idmap file. This is the inverse of
-the 'idmap' command and is intended for clean-up once an idmap file is
-no longer needed because an APK was removed, etc.
-
-This commit depends on a corresponding commit in frameworks/base
-(with the same Change-Id).
-
-Bug: 31052947
-
-Change-Id: Iae19a519803f0c172b02a32faa283ef36f43863c
----
- cmds/installd/commands.cpp | 16 ++++++++++++++++
- cmds/installd/commands.h   |  1 +
- cmds/installd/installd.cpp |  6 ++++++
- 3 files changed, 23 insertions(+)
-
-diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
-index cadcd1e..0b25da1 100644
---- a/cmds/installd/commands.cpp
-+++ b/cmds/installd/commands.cpp
-@@ -2047,6 +2047,22 @@ fail:
-     return -1;
- }
-+int rm_idmap(const char *overlay_apk)
-+{
-+    char idmap_path[PATH_MAX];
-+
-+    if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
-+                idmap_path, sizeof(idmap_path)) == -1) {
-+        ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
-+        return -1;
-+    }
-+    if (unlink(idmap_path) < 0) {
-+        ALOGE("couldn't unlink idmap file %s\n", idmap_path);
-+        return -1;
-+    }
-+    return 0;
-+}
-+
- int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
-         appid_t appid, const char* seinfo) {
-     int res = 0;
-diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
-index ba27517..2da80dd 100644
---- a/cmds/installd/commands.h
-+++ b/cmds/installd/commands.h
-@@ -76,6 +76,7 @@ int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
- int mark_boot_complete(const char *instruction_set);
- int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
- int idmap(const char *target_path, const char *overlay_path, uid_t uid);
-+int rm_idmap(const char *overlay_path);
- int create_oat_dir(const char* oat_dir, const char *instruction_set);
- int rm_package_dir(const char* apk_path);
- int clear_app_profiles(const char* pkgname);
-diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
-index 8f883db..93388ce 100644
---- a/cmds/installd/installd.cpp
-+++ b/cmds/installd/installd.cpp
-@@ -383,6 +383,11 @@ static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-     return idmap(arg[0], arg[1], atoi(arg[2]));
- }
-+static int do_rm_idmap(char **arg, char reply[REPLY_MAX] __unused)
-+{
-+    return rm_idmap(arg[0]);
-+}
-+
- static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
- {
-     /* oat_dir, instruction_set */
-@@ -450,6 +455,7 @@ struct cmdinfo cmds[] = {
-     { "freecache",            2, do_free_cache },
-     { "linklib",              4, do_linklib },
-     { "idmap",                3, do_idmap },
-+    { "rmidmap",              1, do_rm_idmap },
-     { "createoatdir",         2, do_create_oat_dir },
-     { "rmpackagedir",         1, do_rm_package_dir },
-     { "clear_app_profiles",   1, do_clear_app_profiles },
--- 
-2.9.3
-
diff --git a/packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch b/packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch
deleted file mode 100644 (file)
index ac7993f..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-From 136516428b86786251449bf2e008d126d9690691 Mon Sep 17 00:00:00 2001
-From: beanstown106 <nbenis106@gmail.com>
-Date: Fri, 20 Nov 2015 17:27:43 -0500
-Subject: [PATCH] Themes: Expose hardcoded layout and styles colors
-
-Exposed text and background colors for themes to be compatible with themeable
-google dialer. Split PeopleTheme in styles.
-
-Change-Id: I4ca0347470333508e399bfae7ed5291a1a704410
----
- res/layout/confirm_add_detail_activity.xml |  6 +++---
- res/layout/editor_account_header.xml       |  2 +-
- res/values/projekt_colors.xml              | 29 +++++++++++++++++++++++++++++
- res/values/styles.xml                      | 27 ++++++++++++++++-----------
- 4 files changed, 49 insertions(+), 15 deletions(-)
- create mode 100644 res/values/projekt_colors.xml
-
-diff --git a/res/layout/confirm_add_detail_activity.xml b/res/layout/confirm_add_detail_activity.xml
-index 1fa6236..eb54b8a 100644
---- a/res/layout/confirm_add_detail_activity.xml
-+++ b/res/layout/confirm_add_detail_activity.xml
-@@ -55,7 +55,7 @@
-             android:layout_alignRight="@id/photo"
-             android:layout_alignStart="@id/photo"
-             android:layout_alignEnd="@id/photo"
--            android:background="#7F000000" />
-+            android:background="@color/photo_text_bar_bg" />
-         <ImageButton
-             android:id="@+id/open_details_button"
-@@ -92,7 +92,7 @@
-                 android:paddingLeft="8dip"
-                 android:paddingStart="8dip"
-                 android:gravity="center_vertical"
--                android:textColor="@android:color/white"
-+                android:textColor="@color/text_color_white"
-                 android:textSize="16sp"
-                 android:singleLine="true" />
-@@ -105,7 +105,7 @@
-                 android:paddingStart="8dip"
-                 android:gravity="center_vertical"
-                 android:textAppearance="?android:attr/textAppearanceSmall"
--                android:textColor="@android:color/white"
-+                android:textColor="@color/text_color_white"
-                 android:singleLine="true"
-                 android:paddingBottom="4dip"
-                 android:visibility="gone" />
-diff --git a/res/layout/editor_account_header.xml b/res/layout/editor_account_header.xml
-index 59ae3b1..a7d0c62 100644
---- a/res/layout/editor_account_header.xml
-+++ b/res/layout/editor_account_header.xml
-@@ -20,7 +20,7 @@
-     android:layout_height="wrap_content"
-     android:layout_width="match_parent"
-     android:minHeight="48dip"
--    android:background="#EEEEEE"
-+    android:background="@color/editor_account_header_bg"
-     android:orientation="horizontal"
-     android:paddingTop="8dip"
-     android:paddingBottom="8dip"
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..d258c86
---- /dev/null
-+++ b/res/values/projekt_colors.xml
-@@ -0,0 +1,29 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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>
-+    <color name="photo_text_bar_bg">#7F000000</color>
-+    <color name="text_color_white">@android:color/white</color>
-+    <color name="editor_account_header_bg">#EEEEEE</color>
-+    <color name="list_item_name_text_color">#ff212121</color>
-+    <color name="white">@android:color/white</color>
-+    <color name="contacts_action_bar_text_color_hint">#CCCCCC</color>
-+    <color name="contacts_action_bar_text_color">@android:color/black</color>
-+    <color name="section_divider_background_color">#7e7e87</color>
-+    <color name="edit_kind_text_appearance_text_color">#363636</color>
-+    <color name="account_type_name_text_color">#363636</color>
-+</resources>
-diff --git a/res/values/styles.xml b/res/values/styles.xml
-index 95641e3..69d79ea 100644
---- a/res/values/styles.xml
-+++ b/res/values/styles.xml
-@@ -44,7 +44,13 @@
-         <item name="android:actionBarItemBackground">@drawable/item_background_material_borderless_dark</item>
-     </style>
--    <style name="PeopleTheme" parent="@android:style/Theme.Material.Light">
-+    <style name="PeopleTheme1" parent="@android:style/Theme.Material.Light">
-+        <item name="android:colorPrimary">@color/primary_color</item>
-+        <item name="android:colorPrimaryDark">@color/primary_color_dark</item>
-+        <item name="android:colorAccent">@color/primary_color</item>
-+    </style>
-+
-+    <style name="PeopleTheme" parent="@style/PeopleTheme1">
-         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
-         <!-- Style for the tab bar (for the divider between tabs) -->
-         <item name="android:actionBarTabBarStyle">@style/ContactsActionBarTabBarStyle</item>
-@@ -62,9 +68,6 @@
-         <item name="android:icon">@android:color/transparent</item>
-         <item name="android:listViewStyle">@style/ListViewStyle</item>
-         <item name="android:windowBackground">@color/background_primary</item>
--        <item name="android:colorPrimaryDark">@color/primary_color_dark</item>
--        <item name="android:colorPrimary">@color/primary_color</item>
--        <item name="android:colorAccent">@color/primary_color</item>
-         <item name="android:alertDialogTheme">@style/ContactsAlertDialogTheme</item>
-         <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
-         <item name="activated_background">@drawable/list_item_activated_background</item>
-@@ -98,6 +101,8 @@
-         <item name="contact_browser_list_padding_right">0dip</item>
-         <item name="contact_browser_background">@color/background_primary</item>
-         <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
-+        <item name="list_item_name_text_color">@color/list_item_name_text_color</item>
-+        <item name="list_item_name_text_size">16.0sp</item>
-         <!-- Favorites -->
-         <item name="favorites_padding_bottom">0dip</item>
-     </style>
-@@ -129,10 +134,10 @@
-     </style>
-     <style name="ContactPickerSearchTheme" parent="@style/PeopleTheme">
--        <item name="android:textColorPrimary">@android:color/white</item>
-+        <item name="android:textColorPrimary">@color/text_color_white</item>
-         <item name="android:textColorHint">?android:textColorHintInverse</item>
-         <item name="android:colorControlActivated">?android:textColorHintInverse</item>
--        <item name="android:colorControlNormal">@android:color/white</item>
-+        <item name="android:colorControlNormal">@color/white</item>
-     </style>
-     <!-- Text in the action bar at the top of the screen -->
-@@ -174,8 +179,8 @@
-     </style>
-     <style name="ContactsActionBarTheme" parent="@android:style/Theme.Material.Light">
--        <item name="android:textColorHint">#CCCCCC</item>
--        <item name="android:textColor">@android:color/black</item>
-+        <item name="android:textColorHint">@color/contacts_action_bar_text_color_hint</item>
-+        <item name="android:textColor">@color/contacts_action_bar_text_color</item>
-         <item name="android:popupMenuStyle">@android:style/Widget.Holo.Light.PopupMenu</item>
-         <item name="android:dropDownListViewStyle">@style/ListViewDropdownStyle</item>
-     </style>
-@@ -220,7 +225,7 @@
-     </style>
-     <style name="SectionDivider">
--        <item name="android:background">#7e7e87</item>
-+        <item name="android:background">@color/section_divider_background_color</item>
-         <item name="android:layout_height">1dip</item>
-         <item name="android:layout_width">match_parent</item>
-     </style>
-@@ -302,7 +307,7 @@
-         <item name="android:textSize">14sp</item>
-         <item name="android:textStyle">bold</item>
-         <item name="android:textAllCaps">true</item>
--        <item name="android:textColor">#363636</item>
-+        <item name="android:textColor">@color/edit_kind_text_appearance_text_color</item>
-         <item name="android:fontFamily">sans-serif</item>
-     </style>
-@@ -342,7 +347,7 @@
-     <style name="AccountTypeNameStyle">
-         <item name="android:textSize">10sp</item>
--        <item name="android:textColor">#363636</item>
-+        <item name="android:textColor">@color/account_type_name_text_color</item>
-         <item name="android:fontFamily">sans-serif</item>
-     </style>
- </resources>
--- 
-2.9.3
-
diff --git a/packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch b/packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch
deleted file mode 100644 (file)
index f1febe4..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From 1f53add2077b2573b7d6b4d761b48f8505bb3701 Mon Sep 17 00:00:00 2001
-From: bgill55 <bricam55@gmail.com>
-Date: Sat, 24 Jan 2015 18:12:39 -0700
-Subject: [PATCH] Themes: Expose hardcoded contact tile text colors
-
-Naming conventions in line with @daveyannihilation's commit
-https://github.com/daveyannihilation/Theme-Ready-Google-Contacts/commit/dedf7925f52bec3896b138fa3d9f3754218abb2d
-
-Change-Id: I85aa4349ece8a9821d9443523b13f2234edd4af7
----
- res/layout/contact_tile_frequent.xml              |  2 +-
- res/layout/contact_tile_starred.xml               |  2 +-
- res/layout/contact_tile_starred_quick_contact.xml |  2 +-
- res/values/projekt_colors.xml                     | 22 ++++++++++++++++++++++
- 4 files changed, 25 insertions(+), 3 deletions(-)
- create mode 100644 res/values/projekt_colors.xml
-
-diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
-index b1e83ce..8c718fb 100644
---- a/res/layout/contact_tile_frequent.xml
-+++ b/res/layout/contact_tile_frequent.xml
-@@ -38,7 +38,7 @@
-             android:id="@+id/contact_tile_name"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
--            android:textColor="@android:color/black"
-+            android:textColor="@color/frequent_contact_text_color"
-             android:textSize="@dimen/contact_browser_list_item_text_size"
-             android:singleLine="true"
-             android:fadingEdge="horizontal"
-diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
-index 777cc05..88aa1e8 100644
---- a/res/layout/contact_tile_starred.xml
-+++ b/res/layout/contact_tile_starred.xml
-@@ -43,7 +43,7 @@
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:paddingTop="7dp"
--            android:textColor="#202020"
-+            android:textColor="@color/contact_tile_text_color"
-             android:textSize="@dimen/contact_browser_list_item_text_size"
-             android:singleLine="true"
-             android:fadingEdge="horizontal"
-diff --git a/res/layout/contact_tile_starred_quick_contact.xml b/res/layout/contact_tile_starred_quick_contact.xml
-index ecbe583..2134ffc 100644
---- a/res/layout/contact_tile_starred_quick_contact.xml
-+++ b/res/layout/contact_tile_starred_quick_contact.xml
-@@ -47,7 +47,7 @@
-                 android:id="@+id/contact_tile_name"
-                 android:layout_width="wrap_content"
-                 android:layout_height="wrap_content"
--                android:textColor="@android:color/white"
-+                android:textColor="@color/starred_quick_contact_name_text_color"
-                 android:textSize="16sp"
-                 android:singleLine="true"
-                 android:fadingEdge="horizontal"
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..a5d6bd3
---- /dev/null
-+++ b/res/values/projekt_colors.xml
-@@ -0,0 +1,22 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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>
-+    <color name="frequent_contact_text_color">@android:color/black</color>
-+    <color name="contact_tile_text_color">#ff202020</color>
-+    <color name="starred_quick_contact_name_text_color">@android:color/white</color>
-+</resources>
--- 
-2.9.3
-
diff --git a/packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch b/packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch
deleted file mode 100644 (file)
index 4418b9a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From 1ff4ff6484428cd4b80aacaf1a619c3e3ea78667 Mon Sep 17 00:00:00 2001
-From: Bryan Owens <djbryan3540@gmail.com>
-Date: Tue, 29 Dec 2015 22:25:10 -0600
-Subject: [PATCH 1/2] Themes: Expose hard coded background in java
-
-Change-Id: I30bade7c82f29767c6659c8a75bb402d245e49f1
----
- res/values/projekt_colors.xml                         | 19 +++++++++++++++++++
- .../android/calculator2/CalculatorPadViewPager.java   |  2 +-
- 2 files changed, 20 insertions(+), 1 deletion(-)
- create mode 100644 res/values/projekt_colors.xml
-
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..9e15ffc
---- /dev/null
-+++ b/res/values/projekt_colors.xml
-@@ -0,0 +1,19 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+     Copyright (C) 2016 Projekt Substratum
-+
-+     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>
-+    <color name="pad_view_pager_background">#ff000000</color>
-+</resources>
-diff --git a/src/com/android/calculator2/CalculatorPadViewPager.java b/src/com/android/calculator2/CalculatorPadViewPager.java
-index d4520c5..5b02e4b 100644
---- a/src/com/android/calculator2/CalculatorPadViewPager.java
-+++ b/src/com/android/calculator2/CalculatorPadViewPager.java
-@@ -92,7 +92,7 @@ public class CalculatorPadViewPager extends ViewPager {
-         super(context, attrs);
-         setAdapter(mStaticPagerAdapter);
--        setBackgroundColor(Color.BLACK);
-+        setBackgroundColor(context.getColor(R.color.pad_view_pager_background));
-         setPageMargin(getResources().getDimensionPixelSize(R.dimen.pad_page_margin));
-         setPageTransformer(false, mPageTransformer);
-         addOnPageChangeListener(mOnPageChangeListener);
--- 
-2.9.3
-
diff --git a/packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch b/packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch
deleted file mode 100644 (file)
index b2a3277..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From b6b4eaf6df434964f0c3147d4363664096a5c947 Mon Sep 17 00:00:00 2001
-From: Abdulwahab Isam <abdoi94.iq@gmail.com>
-Date: Mon, 19 Sep 2016 18:42:06 +0300
-Subject: [PATCH 2/2] Themes: Expose all elevations
-
-Change-Id: I7d161c1fce17ac3b8a468e1597a3a1632433224b
----
- res/layout/display.xml     | 2 +-
- res/values-port/styles.xml | 2 +-
- res/values/dimens.xml      | 5 +++++
- 3 files changed, 7 insertions(+), 2 deletions(-)
- create mode 100644 res/values/dimens.xml
-
-diff --git a/res/layout/display.xml b/res/layout/display.xml
-index 638f0d2..043b531 100644
---- a/res/layout/display.xml
-+++ b/res/layout/display.xml
-@@ -21,7 +21,7 @@
-     android:layout_width="match_parent"
-     android:layout_height="wrap_content"
-     android:background="@color/display_background_color"
--    android:elevation="4dip">
-+    android:elevation="@dimen/display_elevation">
-     <Toolbar
-         android:id="@+id/toolbar"
-diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
-index a6d2013..9e7e1df 100644
---- a/res/values-port/styles.xml
-+++ b/res/values-port/styles.xml
-@@ -65,7 +65,7 @@
-     </style>
-     <style name="PadLayoutStyle.Advanced">
--        <item name="android:elevation">4dip</item>
-+        <item name="android:elevation">@dimen/pad_elevation</item>
-         <item name="android:paddingTop">12dip</item>
-         <item name="android:paddingBottom">20dip</item>
-         <item name="android:paddingStart">20dip</item>
-diff --git a/res/values/dimens.xml b/res/values/dimens.xml
-new file mode 100644
-index 0000000..065de72
---- /dev/null
-+++ b/res/values/dimens.xml
-@@ -0,0 +1,5 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<resources>
-+    <dimen name="display_elevation">4.0dip</dimen>
-+    <dimen name="pad_elevation">4.0dip</dimen>
-+</resources>
--- 
-2.9.3
-
diff --git a/packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch b/packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch
deleted file mode 100644 (file)
index 5896c2d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From e1c858c77863d951ceab42213cb0df56d36b2ef6 Mon Sep 17 00:00:00 2001
-From: Thyrus11 <thyrus11@gmail.com>
-Date: Sat, 21 Feb 2015 10:41:01 +0100
-Subject: [PATCH] Themes: Make dialpad seperator line theme-able
-
-Using an existing value in colors is defined
-(dialpad_seperator_line_color) in AOSP, but overwritten in layout
-
-Changed the original commit's color name due to layout was #e3e3e3 and
-dialpad_seperator_line_color is #dadada
-
-Change-Id: Ia4b610185bac6c34e0f6bd1b00a6f0c0480d5ee0
----
- res/layout/dialpad_view_unthemed.xml |  4 ++--
- res/values/projekt_colors.xml        | 20 ++++++++++++++++++++
- 2 files changed, 22 insertions(+), 2 deletions(-)
- create mode 100644 res/values/projekt_colors.xml
-
-diff --git a/res/layout/dialpad_view_unthemed.xml b/res/layout/dialpad_view_unthemed.xml
-index 7bc4536..3fcf0da 100644
---- a/res/layout/dialpad_view_unthemed.xml
-+++ b/res/layout/dialpad_view_unthemed.xml
-@@ -56,7 +56,7 @@
-         <View
-             android:layout_width="match_parent"
-             android:layout_height="1dp"
--            android:background="#e3e3e3" />
-+            android:background="@color/dialpad_separator_color" />
-     </LinearLayout>
-@@ -148,7 +148,7 @@
-     <View
-         android:layout_width="match_parent"
-         android:layout_height="1dp"
--        android:background="#e3e3e3" />
-+        android:background="@color/dialpad_separator_color" />
-     <Space
-         android:layout_width="match_parent"
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..468ca5c
---- /dev/null
-+++ b/res/values/projekt_colors.xml
-@@ -0,0 +1,20 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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>
-+    <color name="dialpad_separator_color">#e3e3e3</color>
-+</resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch b/packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch
deleted file mode 100644 (file)
index 282a0e7..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-From 121e37c0c3fe7cc8ac35793777e247ccb812de6b Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Sun, 18 Sep 2016 10:12:05 +0700
-Subject: [PATCH 01/15] Settings: Expose dashboard category and tile color
-
-Change-Id: Ia9c83eb9b8360923ed52e03641b4179681a80330
----
- res/drawable/dashboard_category_title_bg.xml | 21 +++++++++++++++++++++
- res/drawable/dashboard_tile_bg.xml           | 21 +++++++++++++++++++++
- res/drawable/selectable_card.xml             |  4 ++--
- res/layout/dashboard_category.xml            |  2 +-
- res/values/projekt_colors.xml                | 21 +++++++++++++++++++++
- 5 files changed, 66 insertions(+), 3 deletions(-)
- create mode 100644 res/drawable/dashboard_category_title_bg.xml
- create mode 100644 res/drawable/dashboard_tile_bg.xml
- create mode 100644 res/values/projekt_colors.xml
-
-diff --git a/res/drawable/dashboard_category_title_bg.xml b/res/drawable/dashboard_category_title_bg.xml
-new file mode 100644
-index 0000000..0e9604d
---- /dev/null
-+++ b/res/drawable/dashboard_category_title_bg.xml
-@@ -0,0 +1,21 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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.
-+-->
-+
-+<shape xmlns:android="http://schemas.android.com/apk/res/android"
-+       android:shape="rectangle">
-+   <solid android:color="@color/dashboard_category_title_background" />
-+</shape>
-diff --git a/res/drawable/dashboard_tile_bg.xml b/res/drawable/dashboard_tile_bg.xml
-new file mode 100644
-index 0000000..61d113d
---- /dev/null
-+++ b/res/drawable/dashboard_tile_bg.xml
-@@ -0,0 +1,21 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Project Substratum
-+
-+    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.
-+-->
-+
-+<shape xmlns:android="http://schemas.android.com/apk/res/android"
-+       android:shape="rectangle">
-+   <solid android:color="@color/selectable_card_background" />
-+</shape>
-diff --git a/res/drawable/selectable_card.xml b/res/drawable/selectable_card.xml
-index df9ddb1..74018b2 100644
---- a/res/drawable/selectable_card.xml
-+++ b/res/drawable/selectable_card.xml
-@@ -18,5 +18,5 @@
- <ripple
-     xmlns:android="http://schemas.android.com/apk/res/android"
-     android:color="?android:attr/colorControlHighlight">
--    <item android:drawable="@color/card_background"/>
--</ripple>
-\ No newline at end of file
-+    <item android:drawable="@drawable/dashboard_tile_bg"/>
-+</ripple>
-diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
-index 2e5dd5c..7836644 100644
---- a/res/layout/dashboard_category.xml
-+++ b/res/layout/dashboard_category.xml
-@@ -20,7 +20,7 @@
-     android:layout_height="@dimen/dashboard_category_height"
-     android:orientation="vertical"
-     android:paddingBottom="8dip"
--    android:background="@color/card_background">
-+    android:background="@drawable/dashboard_category_title_bg">
-     <TextView android:id="@android:id/title"
-         android:layout_width="match_parent"
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-new file mode 100644
-index 0000000..60419bd
---- /dev/null
-+++ b/res/values/projekt_colors.xml
-@@ -0,0 +1,21 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2016 Projekt Substratum
-+
-+    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>
-+    <!-- Dashboard category and tile background -->
-+    <color name="dashboard_category_title_background">@color/card_background</color>
-+    <color name="selectable_card_background">@color/card_background</color>
-+</resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch b/packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch
deleted file mode 100644 (file)
index 8a0c90c..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-From fde00a322179ec03d9232001da19a3284e65b807 Mon Sep 17 00:00:00 2001
-From: daveyannihilation <daveyannihilation@hotmail.com>
-Date: Tue, 20 Sep 2016 23:35:04 +0800
-Subject: [PATCH 02/15] Settings: Expose condition card colors
-
-PS2 Change to the actual colors in fwb that these attrs call to.
-
-@nathanchance edit: updated for Nougat 7.1
-
-Change-Id: I8de2e2a4f79a28c0fe1f025b4d23937931fe293a
----
- res/layout/condition_card.xml | 18 +++++++++---------
- res/values/projekt_colors.xml |  9 +++++++++
- 2 files changed, 18 insertions(+), 9 deletions(-)
-
-diff --git a/res/layout/condition_card.xml b/res/layout/condition_card.xml
-index 7c9e46d..88277c2 100644
---- a/res/layout/condition_card.xml
-+++ b/res/layout/condition_card.xml
-@@ -1,6 +1,6 @@
- <?xml version="1.0" encoding="utf-8"?>
- <!--
--     Copyright (C) 2015 The Android Open Source Project
-+     Copyright (C) 2016 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.
-@@ -25,7 +25,7 @@
-         android:layout_width="match_parent"
-         android:layout_height="wrap_content"
-         android:orientation="vertical"
--        android:background="?android:attr/colorAccent"
-+        android:background="@color/condition_card_background_color"
-         android:elevation="2dp"
-         android:clickable="true"
-         android:focusable="true">
-@@ -44,7 +44,7 @@
-                 android:layout_height="wrap_content"
-                 android:layout_marginStart="16dp"
-                 android:layout_marginEnd="32dp"
--                android:tint="?android:attr/textColorPrimaryInverse" />
-+                android:tint="@color/condition_card_icon_color" />
-             <TextView
-                 android:id="@android:id/title"
-@@ -52,14 +52,14 @@
-                 android:layout_height="wrap_content"
-                 android:layout_weight="1"
-                 android:textAppearance="?android:attr/textAppearanceMedium"
--                android:textColor="?android:attr/textColorPrimaryInverse" />
-+                android:textColor="@color/condition_card_title_text_color" />
-             <ImageView
-                 android:id="@+id/expand_indicator"
-                 android:layout_width="wrap_content"
-                 android:layout_height="match_parent"
-                 android:padding="16dp"
--                android:tint="?android:attr/textColorPrimaryInverse"/>
-+                android:tint="@color/condition_card_expander_color" />
-         </LinearLayout>
-@@ -81,14 +81,14 @@
-                 android:paddingBottom="16dp"
-                 android:textAppearance="?android:attr/textAppearanceListItemSecondary"
-                 android:alpha=".7"
--                android:textColor="?android:attr/textColorPrimaryInverse" />
-+                android:textColor="@color/condition_card_summary_text_color" />
-             <!-- TODO: Better background -->
-             <View
-                 android:id="@+id/divider"
-                 android:layout_width="match_parent"
-                 android:layout_height=".25dp"
--                android:background="@android:color/white" />
-+                android:background="@color/condition_card_divider_color" />
-             <com.android.internal.widget.ButtonBarLayout
-                 android:id="@+id/buttonBar"
-@@ -107,7 +107,7 @@
-                     android:paddingStart="0dp"
-                     android:alpha=".8"
-                     android:textAlignment="viewStart"
--                    android:textColor="?android:attr/textColorPrimaryInverse"
-+                    android:textColor="@color/condition_card_first_button_text_color"
-                     style="?android:attr/buttonBarButtonStyle" />
-                 <Button
-@@ -117,7 +117,7 @@
-                     android:layout_weight="1"
-                     android:alpha=".8"
-                     android:textAlignment="viewStart"
--                    android:textColor="?android:attr/textColorPrimaryInverse"
-+                    android:textColor="@color/condition_card_second_button_text_color"
-                     style="?android:attr/buttonBarButtonStyle" />
-             </com.android.internal.widget.ButtonBarLayout>
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index 60419bd..9340830 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -18,4 +18,13 @@
-     <!-- Dashboard category and tile background -->
-     <color name="dashboard_category_title_background">@color/card_background</color>
-     <color name="selectable_card_background">@color/card_background</color>
-+    <!-- Condition card colors -->
-+    <color name="condition_card_background_color">@*android:color/accent_device_default_light</color>
-+    <color name="condition_card_icon_color">@*android:color/primary_text_default_material_dark</color>
-+    <color name="condition_card_title_text_color">@*android:color/primary_text_default_material_dark</color>
-+    <color name="condition_card_expander_color">@*android:color/primary_text_default_material_dark</color>
-+    <color name="condition_card_summary_text_color">@*android:color/primary_text_default_material_dark</color>
-+    <color name="condition_card_divider_color">@android:color/white</color>
-+    <color name="condition_card_first_button_text_color">@*android:color/primary_text_default_material_dark</color>
-+    <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
- </resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch b/packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch
deleted file mode 100644 (file)
index 52d06de..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-From 81f82e54029690d530fc32b31a2a2e77d80bbf18 Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Tue, 3 Nov 2015 23:57:22 +0200
-Subject: [PATCH 03/15] Settings: Expose storage summary text
-
-This commit simply exposes the storage summary text hardcodes to allow
-themers to theme them without issue.
-
-@nathanchance edit: updated for Nougat 7.1
-
-Change-Id: I10c124b6a1516a1be7ac234c1dd7dbe2cbe05bb2
----
- res/layout/storage_summary.xml                                    | 2 +-
- res/values/projekt_colors.xml                                     | 2 ++
- src/com/android/settings/deviceinfo/StorageSummaryPreference.java | 8 +++++++-
- src/com/android/settings/deviceinfo/StorageVolumePreference.java  | 8 +++++++-
- 4 files changed, 17 insertions(+), 3 deletions(-)
-
-diff --git a/res/layout/storage_summary.xml b/res/layout/storage_summary.xml
-index 7bc51df..c01d2da 100644
---- a/res/layout/storage_summary.xml
-+++ b/res/layout/storage_summary.xml
-@@ -33,7 +33,7 @@
-         android:singleLine="true"
-         android:textAlignment="viewStart"
-         android:textAppearance="@android:style/TextAppearance.Material.Subhead"
--        android:textColor="?android:attr/colorAccent"
-+        android:textColor="@color/storage_summary_title_color"
-         android:textSize="36sp"
-         android:ellipsize="marquee"
-         android:fadingEdge="horizontal" />
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index 9340830..fb0d99e 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -27,4 +27,6 @@
-     <color name="condition_card_divider_color">@android:color/white</color>
-     <color name="condition_card_first_button_text_color">@*android:color/primary_text_default_material_dark</color>
-     <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
-+    <!-- Storage Summary Title -->
-+    <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
- </resources>
-diff --git a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
-index e1cf774..2741798 100644
---- a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
-+++ b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
-@@ -21,6 +21,7 @@ import android.graphics.Color;
- import android.support.v7.preference.Preference;
- import android.support.v7.preference.PreferenceViewHolder;
- import android.view.View;
-+import android.util.TypedValue;
- import android.widget.ProgressBar;
- import android.widget.TextView;
-@@ -28,12 +29,17 @@ import com.android.settings.R;
- public class StorageSummaryPreference extends Preference {
-     private int mPercent = -1;
-+    private int mSecondaryColor;
-     public StorageSummaryPreference(Context context) {
-         super(context);
-         setLayoutResource(R.layout.storage_summary);
-         setEnabled(false);
-+
-+        TypedValue typedValue = new TypedValue();
-+        context.getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
-+        mSecondaryColor = context.getResources().getColor(typedValue.resourceId);
-     }
-     public void setPercent(int percent) {
-@@ -52,7 +58,7 @@ public class StorageSummaryPreference extends Preference {
-         }
-         final TextView summary = (TextView) view.findViewById(android.R.id.summary);
--        summary.setTextColor(Color.parseColor("#8a000000"));
-+        summary.setTextColor(mSecondaryColor);
-         super.onBindViewHolder(view);
-     }
-diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-index 6389075..9d3c7dc 100644
---- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-+++ b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-@@ -27,6 +27,7 @@ import android.support.v7.preference.PreferenceViewHolder;
- import android.text.format.Formatter;
- import android.view.View;
- import android.view.View.OnClickListener;
-+import android.util.TypedValue;
- import android.widget.ImageView;
- import android.widget.ProgressBar;
-@@ -44,6 +45,7 @@ public class StorageVolumePreference extends Preference {
-     private final VolumeInfo mVolume;
-     private int mColor;
-+    private int mSecondaryColor;
-     private int mUsedPercent = -1;
-     // TODO: ideally, VolumeInfo should have a total physical size.
-@@ -54,6 +56,10 @@ public class StorageVolumePreference extends Preference {
-         mVolume = volume;
-         mColor = color;
-+        TypedValue typedValue = new TypedValue();
-+        context.getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
-+        mSecondaryColor = context.getResources().getColor(typedValue.resourceId);
-+
-         setLayoutResource(R.layout.storage_volume);
-         setKey(volume.getId());
-@@ -107,7 +113,7 @@ public class StorageVolumePreference extends Preference {
-     public void onBindViewHolder(PreferenceViewHolder view) {
-         final ImageView unmount = (ImageView) view.findViewById(R.id.unmount);
-         if (unmount != null) {
--            unmount.setImageTintList(ColorStateList.valueOf(Color.parseColor("#8a000000")));
-+            unmount.setImageTintList(ColorStateList.valueOf(mSecondaryColor));
-             unmount.setOnClickListener(mUnmountListener);
-         }
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch b/packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch
deleted file mode 100644 (file)
index c742a8f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From f4e4000d09321bf4425201b039d5c2054d2fadad Mon Sep 17 00:00:00 2001
-From: daveyannihilation <daveyannihilation@hotmail.com>
-Date: Fri, 25 Nov 2016 15:20:04 -0700
-Subject: [PATCH 04/15] Settings: Expose gesture settings switchbar
-
-In Settings > Gestures, there is a hardcoded white background above each switch. Link to a colors.xml value instead.
-
-Commit written by @nathanchance, idea by @daveyannihilation
-
-Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
-Change-Id: I9857c10ee4e54d27ca1287c80a7d8e420adc9a61
----
- res/layout/gesture_preference.xml | 2 +-
- res/values/projekt_colors.xml     | 3 +++
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/res/layout/gesture_preference.xml b/res/layout/gesture_preference.xml
-index ccbc42a..9fcd14f 100644
---- a/res/layout/gesture_preference.xml
-+++ b/res/layout/gesture_preference.xml
-@@ -31,7 +31,7 @@
-         android:paddingBottom="16dp"
-         android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-         android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
--        android:background="@android:color/white">
-+        android:background="@color/gestures_switchbar_color">
-         <TextView
-             android:id="@android:id/title"
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index fb0d99e..00252332 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -29,4 +29,7 @@
-     <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
-     <!-- Storage Summary Title -->
-     <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
-+    <!-- Gesture settings switchbar background -->
-+    <color name="gestures_switchbar_color">@android:color/white</color>
-+
- </resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch b/packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch
deleted file mode 100644 (file)
index 360da46..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-From d4beb2fe4bbf5105446f23735674a48a0bff5b59 Mon Sep 17 00:00:00 2001
-From: SpiritCroc <spiritcroc@gmail.com>
-Date: Thu, 8 Dec 2016 20:40:16 +0100
-Subject: [PATCH 05/15] Settings: Expose storage icon colors
-
-Change-Id: I97ce427f0683791670f1bbf82eaef66152fe4961
----
- res/values/projekt_colors.xml                      |  9 +++++-
- .../settings/deviceinfo/StorageSettings.java       | 32 ++++++++++++++--------
- .../deviceinfo/StorageVolumePreference.java        |  2 +-
- 3 files changed, 29 insertions(+), 14 deletions(-)
-
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index 00252332..bb6099b 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -31,5 +31,12 @@
-     <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
-     <!-- Gesture settings switchbar background -->
-     <color name="gestures_switchbar_color">@android:color/white</color>
--
-+    <!-- Storage icons -->
-+    <color name="storage_public">#ff9e9e9e</color>
-+    <color name="storage_warning">#fff4511e</color>
-+    <color name="storage_private_1">#ff26a69a</color>
-+    <color name="storage_private_2">#ffab47bc</color>
-+    <color name="storage_private_3">#fff2a600</color>
-+    <color name="storage_private_4">#ffec407a</color>
-+    <color name="storage_private_5">#ffc0ca33</color>
- </resources>
-diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
-index 7757efc..b01013b 100644
---- a/src/com/android/settings/deviceinfo/StorageSettings.java
-+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
-@@ -24,6 +24,7 @@ import android.app.Fragment;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
-+import android.content.res.Resources ;
- import android.graphics.Color;
- import android.graphics.drawable.Drawable;
- import android.os.AsyncTask;
-@@ -73,16 +74,22 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
-     private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
-     private static final String TAG_DISK_INIT = "disk_init";
--    static final int COLOR_PUBLIC = Color.parseColor("#ff9e9e9e");
--    static final int COLOR_WARNING = Color.parseColor("#fff4511e");
-+    static int getColorPublic(Resources resources) {
-+        return resources.getColor(R.color.storage_public);
-+    }
-+    static int getColorWarning(Resources resources) {
-+        return resources.getColor(R.color.storage_warning);
-+    }
--    static final int[] COLOR_PRIVATE = new int[] {
--            Color.parseColor("#ff26a69a"),
--            Color.parseColor("#ffab47bc"),
--            Color.parseColor("#fff2a600"),
--            Color.parseColor("#ffec407a"),
--            Color.parseColor("#ffc0ca33"),
--    };
-+    static int[] getColorPrivate(Resources resources) {
-+        return new int[] {
-+                resources.getColor(R.color.storage_private_1),
-+                resources.getColor(R.color.storage_private_2),
-+                resources.getColor(R.color.storage_private_3),
-+                resources.getColor(R.color.storage_private_4),
-+                resources.getColor(R.color.storage_private_5),
-+        };
-+    }
-     private StorageManager mStorageManager;
-@@ -165,10 +172,11 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
-         final List<VolumeInfo> volumes = mStorageManager.getVolumes();
-         Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
-+        int[] colorPrivate = getColorPrivate(getResources());
-         for (VolumeInfo vol : volumes) {
-             if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
-                 final long volumeTotalBytes = getTotalSize(vol);
--                final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
-+                final int color = colorPrivate[privateCount++ % colorPrivate.length];
-                 mInternalCategory.addPreference(
-                         new StorageVolumePreference(context, vol, color, volumeTotalBytes));
-                 if (vol.isMountedReadable()) {
-@@ -178,7 +186,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
-                 }
-             } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
-                 mExternalCategory.addPreference(
--                        new StorageVolumePreference(context, vol, COLOR_PUBLIC, 0));
-+                        new StorageVolumePreference(context, vol, getColorPublic(getResources()), 0));
-             }
-         }
-@@ -190,7 +198,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
-                 // TODO: add actual storage type to record
-                 final Drawable icon = context.getDrawable(R.drawable.ic_sim_sd);
-                 icon.mutate();
--                icon.setTint(COLOR_PUBLIC);
-+                icon.setTint(getColorPublic(getResources()));
-                 final Preference pref = new Preference(context);
-                 pref.setKey(rec.getFsUuid());
-diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-index 9d3c7dc..8a2780a 100644
---- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-+++ b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
-@@ -89,7 +89,7 @@ public class StorageVolumePreference extends Preference {
-             }
-             if (freeBytes < mStorageManager.getStorageLowBytes(path)) {
--                mColor = StorageSettings.COLOR_WARNING;
-+                mColor = StorageSettings.getColorWarning(context.getResources());
-                 icon = context.getDrawable(R.drawable.ic_warning_24dp);
-             }
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch b/packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch
deleted file mode 100644 (file)
index 93b9c32..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From c52f89f21eade3f277963374f3c5cf34cad3bdd7 Mon Sep 17 00:00:00 2001
-From: SpiritCroc <spiritcroc@gmail.com>
-Date: Fri, 9 Dec 2016 12:47:54 +0100
-Subject: [PATCH 06/15] Settings: Expose LinearColorBar default colors
-
-Change-Id: I8e63f10f9e4079d1a03eaece18e8343102f4a755
----
- res/values/projekt_colors.xml                             |  5 +++++
- src/com/android/settings/applications/LinearColorBar.java | 10 +++++++---
- 2 files changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index bb6099b..e1977f9 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -39,4 +39,9 @@
-     <color name="storage_private_3">#fff2a600</color>
-     <color name="storage_private_4">#ffec407a</color>
-     <color name="storage_private_5">#ffc0ca33</color>
-+
-+    <!-- Linear color bar -->
-+    <color name="linear_color_bar_left">@*android:color/accent_device_default_light</color>
-+    <color name="linear_color_bar_middle">@*android:color/accent_device_default_light</color>
-+    <color name="linear_color_bar_right">#ffced7db</color>
- </resources>
-diff --git a/src/com/android/settings/applications/LinearColorBar.java b/src/com/android/settings/applications/LinearColorBar.java
-index b637671..b0b8b82 100644
---- a/src/com/android/settings/applications/LinearColorBar.java
-+++ b/src/com/android/settings/applications/LinearColorBar.java
-@@ -15,6 +15,7 @@ import android.util.DisplayMetrics;
- import android.view.MotionEvent;
- import android.widget.LinearLayout;
- import com.android.settings.Utils;
-+import com.android.settings.R;
- public class LinearColorBar extends LinearLayout {
-@@ -28,7 +29,7 @@ public class LinearColorBar extends LinearLayout {
-     private int mLeftColor;
-     private int mMiddleColor;
--    private int mRightColor = RIGHT_COLOR;
-+    private int mRightColor;
-     private boolean mShowIndicator = true;
-     private boolean mShowingGreen;
-@@ -70,7 +71,10 @@ public class LinearColorBar extends LinearLayout {
-                 ? 2 : 1;
-         mEdgeGradientPaint.setStrokeWidth(mLineWidth);
-         mEdgeGradientPaint.setAntiAlias(true);
--        mLeftColor = mMiddleColor = Utils.getColorAccent(context);
-+
-+        mLeftColor = context.getResources().getColor(R.color.linear_color_bar_left);
-+        mMiddleColor = context.getResources().getColor(R.color.linear_color_bar_middle);
-+        mRightColor = context.getResources().getColor(R.color.linear_color_bar_right);
-     }
-     public void setOnRegionTappedListener(OnRegionTappedListener listener) {
-@@ -271,4 +275,4 @@ public class LinearColorBar extends LinearLayout {
-             canvas.drawRect(mRect, mPaint);
-         }
-     }
--}
-\ No newline at end of file
-+}
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch b/packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch
deleted file mode 100644 (file)
index 8a03910..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-From 952537ca209dd20a4bc98ea192aa78032a665b10 Mon Sep 17 00:00:00 2001
-From: George G <kreach3r@users.noreply.github.com>
-Date: Mon, 4 Jul 2016 12:07:11 +0300
-Subject: [PATCH 07/15] OMS7-N: Apps: show/hide Substratum overlays [2/2]
-
-Default behavior is "hidden" substratum overlays,
-as they pollute the screen, and you can't notice the
-actual apps.
-So we follow the current trend set by Android with
-"show system" and make it "show overlays" on default.
-
-Change-Id: I1cd4d4d3acd767a87fe402c325a872a4c04e0438
----
- res/menu/manage_apps.xml                           |  8 +++++++
- res/values/projekt_strings.xml                     | 23 ++++++++++++++++++
- .../settings/applications/ManageApplications.java  | 27 +++++++++++++++++++++-
- 3 files changed, 57 insertions(+), 1 deletion(-)
- create mode 100644 res/values/projekt_strings.xml
-
-diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
-index 02ee2bb..67f09e5 100644
---- a/res/menu/manage_apps.xml
-+++ b/res/menu/manage_apps.xml
-@@ -30,6 +30,14 @@
-         android:title="@string/menu_hide_system"
-         android:showAsAction="never" />
-     <item
-+        android:id="@+id/show_substratum"
-+        android:title="@string/menu_show_substratum"
-+        android:showAsAction="never" />
-+    <item
-+        android:id="@+id/hide_substratum"
-+        android:title="@string/menu_hide_substratum"
-+        android:showAsAction="never" />
-+    <item
-         android:id="@+id/sort_order_alpha"
-         android:title="@string/sort_order_alpha"
-         android:showAsAction="never" />
-diff --git a/res/values/projekt_strings.xml b/res/values/projekt_strings.xml
-new file mode 100644
-index 0000000..177e78c
---- /dev/null
-+++ b/res/values/projekt_strings.xml
-@@ -0,0 +1,23 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!-- Copyright (c) 2016 Project Substratum
-+
-+     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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-+
-+   <!-- Manage applications: show substratum overlays -->
-+   <string name="filter_substratum_apps">Substratum overlays</string>
-+   <string name="menu_show_substratum">Show overlays</string>
-+   <string name="menu_hide_substratum">Hide overlays</string>
-+
-+</resources>
-diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
-index 8b1dd27..070754a 100644
---- a/src/com/android/settings/applications/ManageApplications.java
-+++ b/src/com/android/settings/applications/ManageApplications.java
-@@ -107,6 +107,7 @@ public class ManageApplications extends InstrumentedFragment
-     private static final String EXTRA_SORT_ORDER = "sortOrder";
-     private static final String EXTRA_SHOW_SYSTEM = "showSystem";
-+    private static final String EXTRA_SHOW_SUBSTRATUM = "showSubstratum";
-     private static final String EXTRA_HAS_ENTRIES = "hasEntries";
-     private static final String EXTRA_HAS_BRIDGE = "hasBridge";
-@@ -138,6 +139,7 @@ public class ManageApplications extends InstrumentedFragment
-     public static final int FILTER_APPS_USAGE_ACCESS = 13;
-     public static final int FILTER_APPS_WITH_OVERLAY = 14;
-     public static final int FILTER_APPS_WRITE_SETTINGS = 15;
-+    public static final int FILTER_APPS_SUBSTRATUM = 16;
-     // This is the string labels for the filter modes above, the order must be kept in sync.
-     public static final int[] FILTER_LABELS = new int[]{
-@@ -187,6 +189,9 @@ public class ManageApplications extends InstrumentedFragment
-     // whether showing system apps.
-     private boolean mShowSystem;
-+    // whether showing substratum overlays.
-+    private boolean mShowSubstratum;
-+
-     private ApplicationsState mApplicationsState;
-     public int mListType;
-@@ -276,6 +281,7 @@ public class ManageApplications extends InstrumentedFragment
-         if (savedInstanceState != null) {
-             mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
-             mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
-+            mShowSubstratum = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
-         }
-         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
-@@ -440,6 +446,7 @@ public class ManageApplications extends InstrumentedFragment
-         mResetAppsHelper.onSaveInstanceState(outState);
-         outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
-         outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
-+        outState.putBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
-         outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
-         outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
-     }
-@@ -558,6 +565,11 @@ public class ManageApplications extends InstrumentedFragment
-                 && mListType != LIST_TYPE_HIGH_POWER);
-         mOptionsMenu.findItem(R.id.hide_system).setVisible(mShowSystem
-                 && mListType != LIST_TYPE_HIGH_POWER);
-+
-+        mOptionsMenu.findItem(R.id.show_substratum).setVisible(!mShowSubstratum
-+                && mListType != LIST_TYPE_HIGH_POWER);
-+        mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
-+                && mListType != LIST_TYPE_HIGH_POWER);
-     }
-     @Override
-@@ -577,6 +589,11 @@ public class ManageApplications extends InstrumentedFragment
-                 mShowSystem = !mShowSystem;
-                 mApplications.rebuild(false);
-                 break;
-+            case R.id.show_substratum:
-+            case R.id.hide_substratum:
-+                mShowSubstratum = !mShowSubstratum;
-+                mApplications.rebuild(false);
-+                break;
-             case R.id.reset_app_preferences:
-                 mResetAppsHelper.buildResetDialog();
-                 return true;
-@@ -865,9 +882,17 @@ public class ManageApplications extends InstrumentedFragment
-             if (mOverrideFilter != null) {
-                 filterObj = mOverrideFilter;
-             }
--            if (!mManageApplications.mShowSystem) {
-+            if (!mManageApplications.mShowSystem && !mManageApplications.mShowSubstratum) {
-                 filterObj = new CompoundFilter(filterObj,
-                         ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
-+                filterObj = new CompoundFilter(filterObj,
-+                        ApplicationsState.FILTER_SUBSTRATUM);
-+            } else if (!mManageApplications.mShowSystem) {
-+                filterObj = new CompoundFilter(filterObj,
-+                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
-+            } else if (!mManageApplications.mShowSubstratum) {
-+                filterObj = new CompoundFilter(filterObj,
-+                        ApplicationsState.FILTER_SUBSTRATUM);
-             }
-             switch (mLastSortMode) {
-                 case R.id.sort_order_size:
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch b/packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch
deleted file mode 100644 (file)
index d6f0870..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-From 3fcc8bc49ffb6dc7d35e4ba460e932857bff721b Mon Sep 17 00:00:00 2001
-From: Kuba Schenk <abukcz@gmail.com>
-Date: Thu, 1 Dec 2016 22:00:31 +0100
-Subject: [PATCH 08/15] OMS7-N: Apps: show/hide Substratum icon overlays [2/2]
-
-Default behavior is "hidden" substratum icon overlays,
-as they pollute the screen, and you can't notice the
-actual apps.
-So we follow the current trend set by Android with
-"show system" and make it "show icon overlays" on default.
-
-Change-Id: Ib6dd011f821f21bee6da1979615f2eb4658c9f52
-(cherry picked from commit a01b70568db202255fbf7f62d87c3e89e91f933d)
----
- res/menu/manage_apps.xml                           |  8 ++++++
- res/values/projekt_strings.xml                     |  5 ++++
- .../settings/applications/ManageApplications.java  | 33 ++++++++++++++++------
- 3 files changed, 37 insertions(+), 9 deletions(-)
-
-diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
-index 67f09e5..267cff8 100644
---- a/res/menu/manage_apps.xml
-+++ b/res/menu/manage_apps.xml
-@@ -38,6 +38,14 @@
-         android:title="@string/menu_hide_substratum"
-         android:showAsAction="never" />
-     <item
-+        android:id="@+id/show_substratum_icons"
-+        android:title="@string/menu_show_substratum_icons"
-+        android:showAsAction="never" />
-+    <item
-+        android:id="@+id/hide_substratum_icons"
-+        android:title="@string/menu_hide_substratum_icons"
-+        android:showAsAction="never" />
-+    <item
-         android:id="@+id/sort_order_alpha"
-         android:title="@string/sort_order_alpha"
-         android:showAsAction="never" />
-diff --git a/res/values/projekt_strings.xml b/res/values/projekt_strings.xml
-index 177e78c..4c45544 100644
---- a/res/values/projekt_strings.xml
-+++ b/res/values/projekt_strings.xml
-@@ -20,4 +20,9 @@
-    <string name="menu_show_substratum">Show overlays</string>
-    <string name="menu_hide_substratum">Hide overlays</string>
-+   <!-- Manage applications: show substratum icon overlays -->
-+   <string name="filter_substratum_icons">Substratum icon overlays</string>
-+   <string name="menu_show_substratum_icons">Show icon overlays</string>
-+   <string name="menu_hide_substratum_icons">Hide icon overlays</string>
-+
- </resources>
-diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
-index 070754a..5d3b353 100644
---- a/src/com/android/settings/applications/ManageApplications.java
-+++ b/src/com/android/settings/applications/ManageApplications.java
-@@ -108,6 +108,7 @@ public class ManageApplications extends InstrumentedFragment
-     private static final String EXTRA_SORT_ORDER = "sortOrder";
-     private static final String EXTRA_SHOW_SYSTEM = "showSystem";
-     private static final String EXTRA_SHOW_SUBSTRATUM = "showSubstratum";
-+    private static final String EXTRA_SHOW_SUBSTRATUM_ICONS = "showSubstratumIcons";
-     private static final String EXTRA_HAS_ENTRIES = "hasEntries";
-     private static final String EXTRA_HAS_BRIDGE = "hasBridge";
-@@ -139,7 +140,8 @@ public class ManageApplications extends InstrumentedFragment
-     public static final int FILTER_APPS_USAGE_ACCESS = 13;
-     public static final int FILTER_APPS_WITH_OVERLAY = 14;
-     public static final int FILTER_APPS_WRITE_SETTINGS = 15;
--    public static final int FILTER_APPS_SUBSTRATUM = 16;
-+    public static final int FILTER_APPS_SUBSTRATUM_ICONS = 16;
-+    public static final int FILTER_APPS_SUBSTRATUM = 17;
-     // This is the string labels for the filter modes above, the order must be kept in sync.
-     public static final int[] FILTER_LABELS = new int[]{
-@@ -191,6 +193,7 @@ public class ManageApplications extends InstrumentedFragment
-     // whether showing substratum overlays.
-     private boolean mShowSubstratum;
-+    private boolean mShowSubstratumIcons;
-     private ApplicationsState mApplicationsState;
-@@ -282,6 +285,8 @@ public class ManageApplications extends InstrumentedFragment
-             mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
-             mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
-             mShowSubstratum = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
-+            mShowSubstratumIcons = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM_ICONS,
-+                                                                 mShowSubstratumIcons);
-         }
-         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
-@@ -447,6 +452,7 @@ public class ManageApplications extends InstrumentedFragment
-         outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
-         outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
-         outState.putBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
-+        outState.putBoolean(EXTRA_SHOW_SUBSTRATUM_ICONS, mShowSubstratumIcons);
-         outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
-         outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
-     }
-@@ -570,6 +576,10 @@ public class ManageApplications extends InstrumentedFragment
-                 && mListType != LIST_TYPE_HIGH_POWER);
-         mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
-                 && mListType != LIST_TYPE_HIGH_POWER);
-+        mOptionsMenu.findItem(R.id.show_substratum_icons).setVisible(!mShowSubstratumIcons
-+                && mListType != LIST_TYPE_HIGH_POWER);
-+        mOptionsMenu.findItem(R.id.hide_substratum_icons).setVisible(mShowSubstratumIcons
-+                && mListType != LIST_TYPE_HIGH_POWER);
-     }
-     @Override
-@@ -594,6 +604,11 @@ public class ManageApplications extends InstrumentedFragment
-                 mShowSubstratum = !mShowSubstratum;
-                 mApplications.rebuild(false);
-                 break;
-+            case R.id.show_substratum_icons:
-+            case R.id.hide_substratum_icons:
-+                mShowSubstratumIcons = !mShowSubstratumIcons;
-+                mApplications.rebuild(false);
-+                break;
-             case R.id.reset_app_preferences:
-                 mResetAppsHelper.buildResetDialog();
-                 return true;
-@@ -882,17 +897,17 @@ public class ManageApplications extends InstrumentedFragment
-             if (mOverrideFilter != null) {
-                 filterObj = mOverrideFilter;
-             }
--            if (!mManageApplications.mShowSystem && !mManageApplications.mShowSubstratum) {
--                filterObj = new CompoundFilter(filterObj,
--                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
-+            if (!mManageApplications.mShowSystem) {
-                 filterObj = new CompoundFilter(filterObj,
--                        ApplicationsState.FILTER_SUBSTRATUM);
--            } else if (!mManageApplications.mShowSystem) {
-+                                               ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
-+            }
-+            if (!mManageApplications.mShowSubstratum) {
-                 filterObj = new CompoundFilter(filterObj,
--                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
--            } else if (!mManageApplications.mShowSubstratum) {
-+                                               ApplicationsState.FILTER_SUBSTRATUM);
-+            }
-+            if (!mManageApplications.mShowSubstratumIcons) {
-                 filterObj = new CompoundFilter(filterObj,
--                        ApplicationsState.FILTER_SUBSTRATUM);
-+                                               ApplicationsState.FILTER_SUBSTRATUM_ICONS);
-             }
-             switch (mLastSortMode) {
-                 case R.id.sort_order_size:
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch b/packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch
deleted file mode 100644 (file)
index f140374..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 9e3533dad0365c72196f773688d54061572943ca Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Fri, 9 Dec 2016 02:19:20 +0100
-Subject: [PATCH 09/15] Exclude overlays from the app counter
-
-This exclude overlays from the app counter that shows
-in manage app summary.
-
-idea from @KreAch3R
-
-Change-Id: I8cd591dc89eb87057e8c2ae3b2cca2c76c34534b
-(cherry picked from commit 990eeb53387bbd52e76ce7e7b45c171d1e01e7a1)
----
- src/com/android/settings/applications/AppCounter.java         | 1 +
- src/com/android/settings/applications/ManageApplications.java | 6 ++++++
- 2 files changed, 7 insertions(+)
-
-diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
-index fb8d580..852358d 100644
---- a/src/com/android/settings/applications/AppCounter.java
-+++ b/src/com/android/settings/applications/AppCounter.java
-@@ -47,6 +47,7 @@ public abstract class AppCounter extends AsyncTask<Void, Void, Integer> {
-                 ParceledListSlice<ApplicationInfo> list =
-                         mIpm.getInstalledApplications(PackageManager.GET_DISABLED_COMPONENTS
-                                 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
-+                                | PackageManager.GET_META_DATA
-                                 | (user.isAdmin() ? PackageManager.GET_UNINSTALLED_PACKAGES : 0),
-                                 user.id);
-                 for (ApplicationInfo info : list.getList()) {
-diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
-index 5d3b353..ed61781 100644
---- a/src/com/android/settings/applications/ManageApplications.java
-+++ b/src/com/android/settings/applications/ManageApplications.java
-@@ -1297,6 +1297,12 @@ public class ManageApplications extends InstrumentedFragment
-                         if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
-                             return true;
-                         } else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-+                            if (info.metaData != null) {
-+                                if (info.metaData.getString("Substratum_Parent") != null
-+                                        || info.metaData.getString("Substratum_IconPack") != null) {
-+                                    return false;
-+                                }
-+                            }
-                             return true;
-                         }
-                         Intent launchIntent = new Intent(Intent.ACTION_MAIN, null)
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch b/packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch
deleted file mode 100644 (file)
index 6c5bcb3..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-From 6e982674f97c80b325d739c417c95734991f1eaa Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Wed, 14 Dec 2016 14:58:54 +0100
-Subject: [PATCH 10/15] Hide the "show/hide overlays" when no overlay installed
-
-Change-Id: I54088d27c9492e0992992de59bf340fe2465260a
----
- .../settings/applications/ManageApplications.java  | 38 +++++++++++++++++++---
- 1 file changed, 34 insertions(+), 4 deletions(-)
-
-diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
-index ed61781..c3bc4d4 100644
---- a/src/com/android/settings/applications/ManageApplications.java
-+++ b/src/com/android/settings/applications/ManageApplications.java
-@@ -195,6 +195,10 @@ public class ManageApplications extends InstrumentedFragment
-     private boolean mShowSubstratum;
-     private boolean mShowSubstratumIcons;
-+    // if app and icon overlay installed
-+    private boolean mAppOverlayInstalled;
-+    private boolean mIconOverlayInstalled;
-+
-     private ApplicationsState mApplicationsState;
-     public int mListType;
-@@ -556,6 +560,9 @@ public class ManageApplications extends InstrumentedFragment
-     }
-     void updateOptionsMenu() {
-+        mAppOverlayInstalled = isOverlayInstalled("app");
-+        mIconOverlayInstalled = isOverlayInstalled("icon");
-+
-         if (mOptionsMenu == null) {
-             return;
-         }
-@@ -573,13 +580,13 @@ public class ManageApplications extends InstrumentedFragment
-                 && mListType != LIST_TYPE_HIGH_POWER);
-         mOptionsMenu.findItem(R.id.show_substratum).setVisible(!mShowSubstratum
--                && mListType != LIST_TYPE_HIGH_POWER);
-+                && mListType != LIST_TYPE_HIGH_POWER && mAppOverlayInstalled);
-         mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
--                && mListType != LIST_TYPE_HIGH_POWER);
-+                && mListType != LIST_TYPE_HIGH_POWER && mAppOverlayInstalled);
-         mOptionsMenu.findItem(R.id.show_substratum_icons).setVisible(!mShowSubstratumIcons
--                && mListType != LIST_TYPE_HIGH_POWER);
-+                && mListType != LIST_TYPE_HIGH_POWER && mIconOverlayInstalled);
-         mOptionsMenu.findItem(R.id.hide_substratum_icons).setVisible(mShowSubstratumIcons
--                && mListType != LIST_TYPE_HIGH_POWER);
-+                && mListType != LIST_TYPE_HIGH_POWER && mIconOverlayInstalled);
-     }
-     @Override
-@@ -668,6 +675,29 @@ public class ManageApplications extends InstrumentedFragment
-         mFilterAdapter.setFilterEnabled(FILTER_APPS_DISABLED, hasDisabledApps);
-     }
-+    boolean isOverlayInstalled(String type) {
-+        List<ApplicationInfo> packages = getActivity().getPackageManager()
-+                .getInstalledApplications(PackageManager.GET_META_DATA);
-+
-+        for (ApplicationInfo packageInfo : packages) {
-+            if (packageInfo.metaData != null) {
-+                if (type.equals("app")) {
-+                    if (packageInfo.metaData
-+                                    .getString("Substratum_Parent") != null) {
-+                        return true;
-+                    }
-+                }
-+                if (type.equals("icon")) {
-+                    if (packageInfo.metaData
-+                                    .getString("Substratum_IconPack") != null) {
-+                        return true;
-+                    }
-+                }
-+            }
-+        }
-+        return false;
-+    }
-+
-     static class FilterSpinnerAdapter extends ArrayAdapter<CharSequence> {
-         private final ManageApplications mManageApplications;
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch b/packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch
deleted file mode 100644 (file)
index 67df099..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-From f50ef9c89b3cd4ae9d66e885b2d406fdad3931be Mon Sep 17 00:00:00 2001
-From: Clark Scheff <clark@scheffsblend.com>
-Date: Fri, 23 Dec 2016 09:52:57 -0500
-Subject: [PATCH 11/15] Expose color for external settings icons
-
-Marhsmallow now allows for system apps to add settings.  An icon is
-loaded from the external package and a tint is applied to the icon
-so that it matches other icons in the dashboard.  The tint color
-uses the colorAccent attribute from the currently applied style.
-Themes can overlay the colorAccent but this color is also used for
-other elements of the UI which may not be ideal.
-
-This patch adds a new color external_tile_icon_tint_color which
-points to the attribute ?android:attr/colorAccent when not themed.
-This retains the original look but offers better flexibility for
-theme designers.
-
-- Ported up to 7.1.1
-
-Change-Id: Ifb4a99a315271cdcf978a796e3dea0eaef8d7750
----
- res/values/projekt_colors.xml                            |  4 +++-
- src/com/android/settings/dashboard/DashboardAdapter.java | 14 +++++++++-----
- 2 files changed, 12 insertions(+), 6 deletions(-)
-
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index e1977f9..4ecd1b2 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -39,9 +39,11 @@
-     <color name="storage_private_3">#fff2a600</color>
-     <color name="storage_private_4">#ffec407a</color>
-     <color name="storage_private_5">#ffc0ca33</color>
--
-     <!-- Linear color bar -->
-     <color name="linear_color_bar_left">@*android:color/accent_device_default_light</color>
-     <color name="linear_color_bar_middle">@*android:color/accent_device_default_light</color>
-     <color name="linear_color_bar_right">#ffced7db</color>
-+
-+    <!-- External Icon Tint -->
-+    <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
- </resources>
-diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
-index 6b2e145..c29da43 100644
---- a/src/com/android/settings/dashboard/DashboardAdapter.java
-+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
-@@ -114,10 +114,10 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
-         mSuggestions = suggestions;
-         mCategories = categories;
--        // TODO: Better place for tinting?
--        TypedValue tintColor = new TypedValue();
--        mContext.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
--                tintColor, true);
-+        TypedValue tintColorValue = new TypedValue();
-+        mContext.getResources().getValue(R.color.external_tile_icon_tint_color,
-+                tintColorValue, true);
-+
-         for (int i = 0; i < categories.size(); i++) {
-             for (int j = 0; j < categories.get(i).tiles.size(); j++) {
-                 Tile tile = categories.get(i).tiles.get(j);
-@@ -126,7 +126,11 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
-                         tile.intent.getComponent().getPackageName())) {
-                     // If this drawable is coming from outside Settings, tint it to match the
-                     // color.
--                    tile.icon.setTint(tintColor.data);
-+                    if (tintColorValue.type == TypedValue.TYPE_ATTRIBUTE) {
-+                        mContext.getTheme().resolveAttribute(tintColorValue.data,
-+                                tintColorValue, true);
-+                    }
-+                    tile.icon.setTint(tintColorValue.data);
-                 }
-             }
-         }
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch b/packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch
deleted file mode 100644 (file)
index 192868c..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From 0d488d0698cb80ee8236743a8be9300c7c807917 Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Sun, 8 Jan 2017 00:18:47 +0100
-Subject: [PATCH 12/15] Expose dashboard category padding bottom
-
-Change-Id: I5a0d3266bbe96dbe6a136f78ed84cb1ee0a6a19b
----
- res/layout/dashboard_category.xml |  2 +-
- res/values/projekt_dimens.xml     | 16 ++++++++++++++++
- 2 files changed, 17 insertions(+), 1 deletion(-)
- create mode 100644 res/values/projekt_dimens.xml
-
-diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
-index 7836644..86dac35 100644
---- a/res/layout/dashboard_category.xml
-+++ b/res/layout/dashboard_category.xml
-@@ -19,7 +19,7 @@
-     android:layout_width="match_parent"
-     android:layout_height="@dimen/dashboard_category_height"
-     android:orientation="vertical"
--    android:paddingBottom="8dip"
-+    android:paddingBottom="@dimen/dashboard_category_padding_bottom"
-     android:background="@drawable/dashboard_category_title_bg">
-     <TextView android:id="@android:id/title"
-diff --git a/res/values/projekt_dimens.xml b/res/values/projekt_dimens.xml
-new file mode 100644
-index 0000000..a5aae4e
---- /dev/null
-+++ b/res/values/projekt_dimens.xml
-@@ -0,0 +1,16 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<!--
-+    Copyright (c) 2017 Projekt Substratum
-+    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>
-+    <dimen name="dashboard_category_padding_bottom">8dip</dimen>
-+</resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0013-Expose-switchbar-background-color.patch b/packages/apps/Settings/0013-Expose-switchbar-background-color.patch
deleted file mode 100644 (file)
index 4609b94..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-From 1fd8e4207626877ebf22d1c6b258fade0790a704 Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Sun, 8 Jan 2017 01:22:47 +0100
-Subject: [PATCH 13/15] Expose switchbar background color
-
-Change-Id: Idc8b09c921bb57c9464d6ea956cfdd9b2b95e6a8
----
- res/values/projekt_colors.xml                  |  2 ++
- res/values/themes.xml                          |  4 ++--
- src/com/android/settings/widget/SwitchBar.java | 11 ++++++++++-
- 3 files changed, 14 insertions(+), 3 deletions(-)
-
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index 4ecd1b2..f37cc54 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -46,4 +46,6 @@
-     <!-- External Icon Tint -->
-     <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
-+    <!-- Settings switchbar background -->
-+    <color name="switchbar_background_color">?android:attr/colorSecondary</color>
- </resources>
-diff --git a/res/values/themes.xml b/res/values/themes.xml
-index ffe802e..acabe21 100644
---- a/res/values/themes.xml
-+++ b/res/values/themes.xml
-@@ -196,13 +196,13 @@
-     <style name="ThemeOverlay.SwitchBar.Settings" parent="@*android:style/ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent">
-         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
-         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
--        <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
-+        <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
-     </style>
-     <style name="ThemeOverlay.SwitchBar.SubSettings" parent="@android:style/ThemeOverlay.Material.Dark.ActionBar">
-         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
-         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
--        <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
-+        <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
-     </style>
-     <style name="Theme.DialogWhenLarge" parent="@*android:style/Theme.DeviceDefault.Settings.DialogWhenLarge">
-diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
-index 240c062..ce73a39 100644
---- a/src/com/android/settings/widget/SwitchBar.java
-+++ b/src/com/android/settings/widget/SwitchBar.java
-@@ -24,6 +24,7 @@ import android.text.SpannableStringBuilder;
- import android.text.TextUtils;
- import android.text.style.TextAppearanceSpan;
- import android.util.AttributeSet;
-+import android.util.TypedValue;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
-@@ -96,9 +97,17 @@ public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedC
-         final TypedArray a = context.obtainStyledAttributes(attrs, XML_ATTRIBUTES);
-         int switchBarMarginStart = (int) a.getDimension(0, 0);
-         int switchBarMarginEnd = (int) a.getDimension(1, 0);
--        int switchBarBackgroundColor = (int) a.getColor(2, 0);
-         a.recycle();
-+        TypedValue backgroundColorValue = new TypedValue();
-+        mContext.getResources().getValue(R.color.switchbar_background_color,
-+                backgroundColorValue, true);
-+        if (backgroundColorValue.type == TypedValue.TYPE_ATTRIBUTE) {
-+            context.getTheme().resolveAttribute(backgroundColorValue.data,
-+                    backgroundColorValue, true);
-+        }
-+        int switchBarBackgroundColor = backgroundColorValue.data;
-+
-         mTextView = (TextView) findViewById(R.id.switch_text);
-         mTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
-         mLabel = getResources().getString(R.string.switch_off_text);
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch b/packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch
deleted file mode 100644 (file)
index b17f145..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 1edcfb911d77e894086bf88ac47f966a8b88fb22 Mon Sep 17 00:00:00 2001
-From: SpiritCroc <spiritcroc@gmail.com>
-Date: Sun, 22 Jan 2017 20:51:47 +0100
-Subject: [PATCH 14/15] Settings: Expose bluetooth pin confirm dialog text
- colors
-
-Change-Id: I1e1eb2da23f2470a82574da7ef326d56f770eb95
----
- res/layout/bluetooth_pin_confirm.xml | 6 +++---
- res/values/projekt_colors.xml        | 5 +++++
- 2 files changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/res/layout/bluetooth_pin_confirm.xml b/res/layout/bluetooth_pin_confirm.xml
-index ebdf65d..6609a1b 100644
---- a/res/layout/bluetooth_pin_confirm.xml
-+++ b/res/layout/bluetooth_pin_confirm.xml
-@@ -40,7 +40,7 @@
-             android:text="@string/bluetooth_pairing_key_msg"
-             android:visibility="gone"
-             android:textAppearance="@android:style/TextAppearance.Material.Body1"
--            android:textColor="@*android:color/secondary_text_material_light"  />
-+            android:textColor="@color/bluetooth_pairing_caption"  />
-         <TextView
-             android:id="@+id/pairing_subhead"
-@@ -63,7 +63,7 @@
-             android:gravity="center_vertical"
-             android:text="@string/bluetooth_enter_passkey_msg"
-             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
--            android:textColor="@*android:color/secondary_text_material_light"
-+            android:textColor="@color/bluetooth_pairing_code_message"
-             android:visibility="gone" />
-         <CheckBox
-@@ -73,7 +73,7 @@
-             android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-             android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
-             android:textAppearance="@android:style/TextAppearance.Material.Body1"
--            android:textColor="@*android:color/secondary_text_material_light"  />
-+            android:textColor="@color/bluetooth_phonebook_sharing_message_confirm_pin"  />
-     </LinearLayout>
-diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
-index f37cc54..e0d3ab1 100644
---- a/res/values/projekt_colors.xml
-+++ b/res/values/projekt_colors.xml
-@@ -48,4 +48,9 @@
-     <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
-     <!-- Settings switchbar background -->
-     <color name="switchbar_background_color">?android:attr/colorSecondary</color>
-+
-+    <!-- Bluetooth pairing pin confirm dialog -->
-+    <color name="bluetooth_pairing_caption">@*android:color/secondary_text_material_light</color>
-+    <color name="bluetooth_pairing_code_message">@*android:color/secondary_text_material_light</color>
-+    <color name="bluetooth_phonebook_sharing_message_confirm_pin">@*android:color/secondary_text_material_light</color>
- </resources>
--- 
-2.9.3
-
diff --git a/packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch b/packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch
deleted file mode 100644 (file)
index 5cdcb63..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 9bb5dca50887734bbc12e46254464f1d0734ac6f Mon Sep 17 00:00:00 2001
-From: Ivan Iskandar <iiiiskandar14@gmail.com>
-Date: Sat, 28 Jan 2017 13:40:55 +0100
-Subject: [PATCH 15/15] Set external settings icon tint mode to SRC_ATOP
-
-With "Expose color for external settings icons" commit, themers can change
-the color of the external settings icon to whatever they want except
-transparent. When they set the tint color to transparent the icon will be
-dissapeared, this commits fixed the problem by changing the tint mode.
-
-Before: http://i.imgur.com/ghDPs27.jpg
-After: http://i.imgur.com/AUEFgNO.jpg
-
-Change-Id: I65b710e2abefd1052b3af154a98247de9b4fe98d
----
- src/com/android/settings/dashboard/DashboardAdapter.java | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
-index c29da43..8259d39 100644
---- a/src/com/android/settings/dashboard/DashboardAdapter.java
-+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
-@@ -19,6 +19,7 @@ import android.content.Context;
- import android.content.pm.PackageManager;
- import android.graphics.drawable.Drawable;
- import android.graphics.drawable.Icon;
-+import android.graphics.PorterDuff.Mode;
- import android.os.Bundle;
- import android.support.v7.widget.PopupMenu;
- import android.support.v7.widget.RecyclerView;
-@@ -130,7 +131,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
-                         mContext.getTheme().resolveAttribute(tintColorValue.data,
-                                 tintColorValue, true);
-                     }
--                    tile.icon.setTint(tintColorValue.data);
-+                    tile.icon.setTint(tintColorValue.data).setTintMode(Mode.SRC_ATOP);
-                 }
-             }
-         }
--- 
-2.9.3
-
index 05f455ddc7b7a54cf43a2452698bce93c551c3b5..66fa8d4686301b684bc5080d75ebdb239bb217f0 100755 (executable)
--- a/patch.sh
+++ b/patch.sh
@@ -14,7 +14,7 @@ REPOSITORIES=(
 for repository in "${REPOSITORIES[@]}"; do
     cd "${ROOT}/${repository}"
 
-    git am "${ROOT}/oms-patches/${repository}"/*
+    git am "${ROOT}/vendor/extra/patches/${repository}"/*
 
     cd "${ROOT}"
 done
diff --git a/patches/build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch b/patches/build/0001-OMS-N-adb-shell-command-to-access-OverlayManagerServ.patch
new file mode 100644 (file)
index 0000000..80b0242
--- /dev/null
@@ -0,0 +1,44 @@
+From 9c60c359e98e9c862411c08e72bb7a1520b736d1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Mon, 27 Jul 2015 12:24:40 +0200
+Subject: [PATCH] OMS-N: adb shell command to access OverlayManagerService
+
+Add a command to communicate with the OverlayManagerService for
+debugging purposes. This mirrors the am and pm commands.
+
+This commit restores the functionality after the Nougat rebase from
+Sony.
+
+Example use:
+    $ adb shell om list
+    com.android.systemui
+        [ ] com.test.awesome-home-button
+
+    $ adb shell om enable com.test.awesome-home-button
+
+    $ adb shell om list
+    com.android.systemui
+        [x] com.test.awesome-home-button
+
+Co-authored-by: Martin Wallgren <martin.wallgren@sonymobile.com>
+Signed-off-by: Zoran Jovanovic <zoran.jovanovic@sonymobile.com>
+Change-Id: If424b8ef6052e4121902b630279c0ebaf416203c
+---
+ target/product/base.mk | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/target/product/base.mk b/target/product/base.mk
+index dcd48e7..a12f939 100644
+--- a/target/product/base.mk
++++ b/target/product/base.mk
+@@ -108,6 +108,7 @@ PRODUCT_PACKAGES += \
+     mtpd \
+     ndc \
+     netd \
++    om \
+     ping \
+     ping6 \
+     platform.xml \
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch b/patches/frameworks/base/0001-OMS7-N-Support-tagging-resources-as-OK-to-overlay-1-.patch
new file mode 100644 (file)
index 0000000..342173e
--- /dev/null
@@ -0,0 +1,474 @@
+From 75d5463e848764c3255c32d126415faceca62023 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Tue, 15 Dec 2015 16:08:31 +0100
+Subject: [PATCH 01/38] OMS7-N: Support tagging resources as OK to overlay
+ [1/11]
+
+This will allow applications to have a resource xml defining what
+resources that are safe to overlay by third party overlay packages.
+The format of the tag is <overlay type="..." name="..."/> and it will
+result in the FLAG_OVELAY being set on the resource entry.
+
+An overlay package with resources that are not tagged as OK
+to overlay by the target application, is considered to be a dangerous
+overlay.
+
+Idmaps generated for dangerous overlays will be flagged as dangerous in
+the idmap header. It is still possible to use both idmap and overlays that
+are dangerous, but it might not be advisable.
+
+The intention is to allow dangerous overlays to be used if
+they are pre-installed or if the signature of the overlay package
+matches the signature of the target package.
+
+Change-Id: I08d11de845c1679017798ea1636ef4c36f820d8e
+---
+ cmds/idmap/create.cpp             |  2 +-
+ cmds/idmap/inspect.cpp            |  6 +++
+ include/androidfw/ResourceTypes.h | 10 ++--
+ libs/androidfw/AssetManager.cpp   |  2 +-
+ libs/androidfw/ResourceTypes.cpp  | 27 ++++++++---
+ tools/aapt/ResourceTable.cpp      | 96 ++++++++++++++++++++++++++++++++++++++-
+ tools/aapt/ResourceTable.h        | 36 ++++++++++++++-
+ 7 files changed, 164 insertions(+), 15 deletions(-)
+
+diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
+index c13d318..8656b0e 100644
+--- a/cmds/idmap/create.cpp
++++ b/cmds/idmap/create.cpp
+@@ -106,7 +106,7 @@ fail:
+         uint32_t cached_target_crc, cached_overlay_crc;
+         String8 cached_target_path, cached_overlay_path;
+-        if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc,
++        if (!ResTable::getIdmapInfo(buf, N, NULL, NULL, &cached_target_crc, &cached_overlay_crc,
+                     &cached_target_path, &cached_overlay_path)) {
+             return true;
+         }
+diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
+index f6afc85..924090f 100644
+--- a/cmds/idmap/inspect.cpp
++++ b/cmds/idmap/inspect.cpp
+@@ -192,6 +192,12 @@ namespace {
+         if (err != NO_ERROR) {
+             return err;
+         }
++        print("", "dangerous", i, "");
++
++        err = buf.nextUint32(&i);
++        if (err != NO_ERROR) {
++            return err;
++        }
+         print("", "base crc", i, "");
+         err = buf.nextUint32(&i);
+diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
+index 12a6b0f..6094a57 100644
+--- a/include/androidfw/ResourceTypes.h
++++ b/include/androidfw/ResourceTypes.h
+@@ -1382,7 +1382,11 @@ struct ResTable_entry
+         // If set, this is a weak resource and may be overriden by strong
+         // resources of the same name/type. This is only useful during
+         // linking with other resource tables.
+-        FLAG_WEAK = 0x0004
++        FLAG_WEAK = 0x0004,
++        // If set, this resource has been declared OK to overlay, so overlay
++        // packages may be added to the resource table to provide alternative
++        // resource values.
++        FLAG_OVERLAY = 0x0008,
+     };
+     uint16_t flags;
+     
+@@ -1861,14 +1865,14 @@ public:
+             const char* targetPath, const char* overlayPath,
+             void** outData, size_t* outSize) const;
+-    static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256;
++    static const size_t IDMAP_HEADER_SIZE_BYTES = 5 * sizeof(uint32_t) + 2 * 256;
+     // Retrieve idmap meta-data.
+     //
+     // This function only requires the idmap header (the first
+     // IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
+     static bool getIdmapInfo(const void* idmap, size_t size,
+-            uint32_t* pVersion,
++            uint32_t* pVersion, uint32_t* pDangerous,
+             uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+             String8* pTargetPath, String8* pOverlayPath);
+diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
+index fdd0caf..edc625b 100644
+--- a/libs/androidfw/AssetManager.cpp
++++ b/libs/androidfw/AssetManager.cpp
+@@ -252,7 +252,7 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
+     String8 targetPath;
+     String8 overlayPath;
+     if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
+-                NULL, NULL, NULL, &targetPath, &overlayPath)) {
++                NULL, NULL, NULL, NULL, &targetPath, &overlayPath)) {
+         ALOGW("failed to read idmap file %s\n", idmapPath.string());
+         delete idmap;
+         return false;
+diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
+index e8c6fcf..022f19e 100644
+--- a/libs/androidfw/ResourceTypes.cpp
++++ b/libs/androidfw/ResourceTypes.cpp
+@@ -59,7 +59,7 @@ namespace android {
+ #endif
+ #define IDMAP_MAGIC             0x504D4449
+-#define IDMAP_CURRENT_VERSION   0x00000001
++#define IDMAP_CURRENT_VERSION   0x00000002
+ #define APP_PACKAGE_ID      0x7f
+ #define CMSDK_PACKAGE_ID    0x3f
+@@ -6601,6 +6601,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
+         return UNKNOWN_ERROR;
+     }
++    bool isDangerous = false;
+     KeyedVector<uint8_t, IdmapTypeMap> map;
+     // overlaid packages are assumed to contain only one package group
+@@ -6675,6 +6676,13 @@ status_t ResTable::createIdmap(const ResTable& overlay,
+                 }
+             }
+             typeMap.entryMap.add(Res_GETENTRY(overlayResID));
++
++            Entry entry;
++            if (getEntry(pg, typeIndex, entryIndex, NULL, &entry)) {
++                return UNKNOWN_ERROR;
++            }
++            isDangerous = isDangerous ||
++                ((dtohs(entry.entry->flags) & ResTable_entry::FLAG_OVERLAY) == 0);
+         }
+         if (!typeMap.entryMap.isEmpty()) {
+@@ -6697,6 +6705,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
+     uint32_t* data = (uint32_t*)*outData;
+     *data++ = htodl(IDMAP_MAGIC);
+     *data++ = htodl(IDMAP_CURRENT_VERSION);
++    *data++ = htodl(isDangerous ? 1 : 0);
+     *data++ = htodl(targetCrc);
+     *data++ = htodl(overlayCrc);
+     const char* paths[] = { targetPath, overlayPath };
+@@ -6737,7 +6746,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
+ }
+ bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
+-                            uint32_t* pVersion,
++                            uint32_t* pVersion, uint32_t* pDangerous,
+                             uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+                             String8* pTargetPath, String8* pOverlayPath)
+ {
+@@ -6748,17 +6757,20 @@ bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
+     if (pVersion) {
+         *pVersion = dtohl(map[1]);
+     }
++    if (pDangerous) {
++        *pDangerous = dtohl(map[2]);
++    }
+     if (pTargetCrc) {
+-        *pTargetCrc = dtohl(map[2]);
++        *pTargetCrc = dtohl(map[3]);
+     }
+     if (pOverlayCrc) {
+-        *pOverlayCrc = dtohl(map[3]);
++        *pOverlayCrc = dtohl(map[4]);
+     }
+     if (pTargetPath) {
+-        pTargetPath->setTo(reinterpret_cast<const char*>(map + 4));
++        pTargetPath->setTo(reinterpret_cast<const char*>(map + 5));
+     }
+     if (pOverlayPath) {
+-        pOverlayPath->setTo(reinterpret_cast<const char*>(map + 4 + 256 / sizeof(uint32_t)));
++        pOverlayPath->setTo(reinterpret_cast<const char*>(map + 5 + 256 / sizeof(uint32_t)));
+     }
+     return true;
+ }
+@@ -7085,6 +7097,9 @@ void ResTable::print(bool inclValues) const
+                     if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) {
+                         printf(" (PUBLIC)");
+                     }
++                    if ((dtohs(ent->flags)&ResTable_entry::FLAG_OVERLAY) != 0) {
++                        printf(" (OVERLAY)");
++                    }
+                     printf("\n");
+                     if (inclValues) {
+diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
+index a1b1879..b2d0480 100644
+--- a/tools/aapt/ResourceTable.cpp
++++ b/tools/aapt/ResourceTable.cpp
+@@ -800,6 +800,7 @@ status_t compileResourceFile(Bundle* bundle,
+     const String16 string_array16("string-array");
+     const String16 integer_array16("integer-array");
+     const String16 public16("public");
++    const String16 overlay16("overlay");
+     const String16 public_padding16("public-padding");
+     const String16 private_symbols16("private-symbols");
+     const String16 java_symbol16("java-symbol");
+@@ -1003,6 +1004,41 @@ status_t compileResourceFile(Bundle* bundle,
+                 }
+                 continue;
++            } else if (strcmp16(block.getElementName(&len), overlay16.string()) == 0) {
++                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
++
++                String16 type;
++                const ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
++                if (typeIdx < 0) {
++                    srcPos.error("A 'type' attribute is required for <overlay>\n");
++                    hasErrors = localHasErrors = true;
++                }
++                type = String16(block.getAttributeStringValue(typeIdx, &len));
++
++                String16 name;
++                const ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
++                if (nameIdx < 0) {
++                    srcPos.error("A 'name' attribute is required for <overlay>\n");
++                    hasErrors = localHasErrors = true;
++                }
++                name = String16(block.getAttributeStringValue(nameIdx, &len));
++
++                if (!localHasErrors) {
++                    err = outTable->addOverlay(srcPos, myPackage, type, name);
++                    if (err < NO_ERROR) {
++                        hasErrors = localHasErrors = true;
++                    }
++                }
++
++                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
++                    if (code == ResXMLTree::END_TAG) {
++                        if (strcmp16(block.getElementName(&len), overlay16.string()) == 0) {
++                            break;
++                        }
++                    }
++                }
++                continue;
++
+             } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
+                 SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+             
+@@ -1865,6 +1901,29 @@ status_t ResourceTable::addPublic(const SourcePos& sourcePos,
+     return t->addPublic(sourcePos, name, ident);
+ }
++status_t ResourceTable::addOverlay(const SourcePos& sourcePos,
++                                  const String16& package,
++                                  const String16& type,
++                                  const String16& name)
++{
++    uint32_t rid = mAssets->getIncludedResources()
++        .identifierForName(name.string(), name.size(),
++                           type.string(), type.size(),
++                           package.string(), package.size());
++    if (rid != 0) {
++        sourcePos.error("Error declaring overlay resource %s/%s for included package %s\n",
++                String8(type).string(), String8(name).string(),
++                String8(package).string());
++        return UNKNOWN_ERROR;
++    }
++
++    sp<Type> t = getType(package, type, sourcePos);
++    if (t == NULL) {
++        return UNKNOWN_ERROR;
++    }
++    return t->addOverlay(sourcePos, name);
++}
++
+ status_t ResourceTable::addEntry(const SourcePos& sourcePos,
+                                  const String16& package,
+                                  const String16& type,
+@@ -2665,6 +2724,11 @@ status_t ResourceTable::assignResourceIds()
+                 firstError = err;
+             }
++            err = t->applyOverlay();
++            if (err != NO_ERROR && firstError == NO_ERROR) {
++                firstError = err;
++            }
++
+             const size_t N = t->getOrderedConfigs().size();
+             t->setIndex(ti + 1 + typeIdOffset);
+@@ -3254,7 +3318,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
+                         index[ei] = htodl(data->getSize()-typeStart-typeSize);
+                         // Create the entry.
+-                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
++                        ssize_t amt = e->flatten(bundle, data, cl->getPublic(), cl->getOverlay());
+                         if (amt < 0) {
+                             return amt;
+                         }
+@@ -3759,7 +3823,8 @@ status_t ResourceTable::Entry::remapStringValue(StringPool* strings)
+     return NO_ERROR;
+ }
+-ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>& data, bool isPublic)
++ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>& data, bool isPublic,
++        bool isOverlay)
+ {
+     size_t amt = 0;
+     ResTable_entry header;
+@@ -3772,6 +3837,9 @@ ssize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>&
+     if (isPublic) {
+         header.flags |= htods(header.FLAG_PUBLIC);
+     }
++    if (isOverlay) {
++        header.flags |= htods(header.FLAG_OVERLAY);
++    }
+     header.key.index = htodl(mNameIndex);
+     if (ty != TYPE_BAG) {
+         status_t err = data->writeData(&header, sizeof(header));
+@@ -3912,6 +3980,13 @@ status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
+     return NO_ERROR;
+ }
++status_t ResourceTable::Type::addOverlay(const SourcePos& sourcePos,
++                                         const String16& name)
++{
++    mOverlay.add(name, Overlay(sourcePos, String16()));
++    return NO_ERROR;
++}
++
+ void ResourceTable::Type::canAddEntry(const String16& name)
+ {
+     mCanAddEntries.add(name);
+@@ -4014,6 +4089,7 @@ sp<ResourceTable::ConfigList> ResourceTable::Type::removeEntry(const String16& e
+     }
+     mPublic.removeItem(entry);
++    mOverlay.removeItem(entry);
+     return removed;
+ }
+@@ -4115,6 +4191,22 @@ status_t ResourceTable::Type::applyPublicEntryOrder()
+     return hasError ? STATUST(UNKNOWN_ERROR) : NO_ERROR;
+ }
++status_t ResourceTable::Type::applyOverlay() {
++    const size_t N = mOverlay.size();
++    const size_t M = mOrderedConfigs.size();
++    for (size_t i = 0; i < N; i++) {
++        const String16& name = mOverlay.keyAt(i);
++        for (size_t j = 0; j < M; j++) {
++            sp<ConfigList> e = mOrderedConfigs.itemAt(j);
++            if (e->getName() == name) {
++                e->setOverlay(true);
++                break;
++            }
++        }
++    }
++    return NO_ERROR;
++}
++
+ ResourceTable::Package::Package(const String16& name, size_t packageId)
+     : mName(name), mPackageId(packageId),
+       mTypeStringsMapping(0xffffffff),
+diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
+index 54d56cf..7e9b044 100644
+--- a/tools/aapt/ResourceTable.h
++++ b/tools/aapt/ResourceTable.h
+@@ -139,6 +139,11 @@ public:
+                        const String16& name,
+                        const uint32_t ident);
++    status_t addOverlay(const SourcePos& pos,
++                       const String16& package,
++                       const String16& type,
++                       const String16& name);
++
+     status_t addEntry(const SourcePos& pos,
+                       const String16& package,
+                       const String16& type,
+@@ -388,7 +393,7 @@ public:
+         status_t remapStringValue(StringPool* strings);
+-        ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic);
++        ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic, bool isOverlay);
+         const SourcePos& getPos() const { return mPos; }
+@@ -407,7 +412,7 @@ public:
+     class ConfigList : public RefBase {
+     public:
+         ConfigList(const String16& name, const SourcePos& pos)
+-            : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { }
++            : mName(name), mPos(pos), mPublic(false), mOverlay(false), mEntryIndex(-1) { }
+         virtual ~ConfigList() { }
+         
+         String16 getName() const { return mName; }
+@@ -427,6 +432,9 @@ public:
+         bool getPublic() const { return mPublic; }
+         void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; }
+         const SourcePos& getPublicSourcePos() { return mPublicSourcePos; }
++
++        void setOverlay(bool o) { mOverlay = o; }
++        bool getOverlay() const { return mOverlay; }
+         
+         void addEntry(const ResTable_config& config, const sp<Entry>& entry) {
+             mEntries.add(config, entry);
+@@ -440,6 +448,7 @@ public:
+         String16 mTypeComment;
+         bool mPublic;
+         SourcePos mPublicSourcePos;
++        bool mOverlay;
+         int32_t mEntryIndex;
+         DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries;
+     };
+@@ -467,6 +476,24 @@ public:
+         String16    comment;
+         uint32_t    ident;
+     };
++
++    class Overlay {
++    public:
++        Overlay() : sourcePos() { }
++        Overlay(const SourcePos& pos, const String16& _comment)
++            : sourcePos(pos), comment(_comment) { }
++        Overlay(const Overlay& o) : sourcePos(o.sourcePos), comment(o.comment) { }
++        ~Overlay() { }
++
++        Overlay& operator=(const Overlay& o) {
++            sourcePos = o.sourcePos;
++            comment = o.comment;
++            return *this;
++        }
++
++        SourcePos   sourcePos;
++        String16    comment;
++    };
+     
+     class Type : public RefBase {
+     public:
+@@ -478,6 +505,9 @@ public:
+         status_t addPublic(const SourcePos& pos,
+                            const String16& name,
+                            const uint32_t ident);
++
++        status_t addOverlay(const SourcePos& pos,
++                            const String16& name);
+                            
+         void canAddEntry(const String16& name);
+         
+@@ -505,6 +535,7 @@ public:
+         void setIndex(int32_t index) { mIndex = index; }
+         status_t applyPublicEntryOrder();
++        status_t applyOverlay();
+         const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
+         const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
+@@ -516,6 +547,7 @@ public:
+         String16 mName;
+         SourcePos* mFirstPublicSourcePos;
+         DefaultKeyedVector<String16, Public> mPublic;
++        DefaultKeyedVector<String16, Overlay> mOverlay;
+         DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
+         Vector<sp<ConfigList> > mOrderedConfigs;
+         SortedVector<String16> mCanAddEntries;
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch b/patches/frameworks/base/0002-OMS7-N-Introduce-the-OverlayManagerService-2-11.patch
new file mode 100644 (file)
index 0000000..919e42c
--- /dev/null
@@ -0,0 +1,3082 @@
+From 90815d5667efdc258011508a5599a45bd3d66756 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Tue, 15 Dec 2015 16:40:23 +0100
+Subject: [PATCH 02/38] OMS7-N: Introduce the OverlayManagerService [2/11]
+
+Add a new system service to manage Runtime Resource Overlays. This will
+offload the PackageManagerService and allow administration of overlay
+packages while affected packages continue to execute.
+
+Overlays can be enabled or disabled during runtime. To the running
+application the change is invisible. Technically, the overlay is added
+or removed from the running application similarly to how multi-window
+affects resources.
+
+Before an overlay can be enabled it has to be approved. This happens
+during package installation or upgrade and if an error occurs, the
+overlay is marked as not approved.
+
+The system performs the following security checks, in
+the order listed, to determine if an overlay can be approved:
+
+  1. Is the overlay package pre-installed? If yes, OK to use.
+
+  2. Are the target and overlay packages signed with the same
+     certificate? If yes, OK to use.
+
+  3. Is the overlay dangerous? If no, OK to use.
+
+An overlay is said to be dangerous if it modifies resources not
+explicitly specified by the target as OK to overlay. (This is done by
+adding <overlay type="..." name="..."/> tags to the target's resources.)
+
+The decision to approve/not approve an overlay is not re-evaluated until
+the next time either the overlay or its target package is changed.
+
+The order in which a set of overlays is loaded may also be changed
+during runtime. The underlying mechanics are the same as for when an
+overlay is enabled or disabled.
+
+When an overlay changes state, e.g. becomes enabled, the
+OverlayManagerService will broadcast one of the new intents
+android.intent.action.OVERLAY_ADDED, *_CHANGED, *_REMOVED or
+*.OVERLAYS_REORDERED.
+
+Clients that wish to read information about overlays for users other
+than themselves are required to hold the
+android.permission.INTERACT_ACROSS_USERS_FULL permission. This mirrors
+the protection level of PackageManager.getPackageInfo.
+
+Clients that wish to change the information are required to
+hold the permission android.permission.CHANGE_CONFIGURATION.
+
+Each pair of overlay package and corresponding target package is
+respresented by a new OverlayInfo class. This class mirrors the
+existing PackageInfo class.
+
+Overlay packages are handled per Android user. The data is persisted in
+/data/system/overlays.xml.
+
+Change-Id: Icc3c7daa25345d20bc5014b865024422eab72f5b
+---
+ Android.mk                                         |   1 +
+ core/java/android/content/Context.java             |  10 +
+ core/java/android/content/Intent.java              |  34 +
+ core/java/android/content/om/IOverlayManager.aidl  | 129 +++
+ core/java/android/content/om/OverlayInfo.aidl      |  19 +
+ core/java/android/content/om/OverlayInfo.java      | 290 +++++++
+ .../android/content/pm/PackageManagerInternal.java |  24 +
+ core/res/AndroidManifest.xml                       |   4 +
+ .../java/com/android/server/om/IdmapManager.java   | 116 +++
+ .../android/server/om/OverlayManagerService.java   | 901 +++++++++++++++++++++
+ .../server/om/OverlayManagerServiceImpl.java       | 478 +++++++++++
+ .../android/server/om/OverlayManagerSettings.java  | 656 +++++++++++++++
+ .../server/om/OverlayManagerShellCommand.java      | 179 ++++
+ .../android/server/pm/PackageManagerService.java   |  41 +
+ 14 files changed, 2882 insertions(+)
+ create mode 100644 core/java/android/content/om/IOverlayManager.aidl
+ create mode 100644 core/java/android/content/om/OverlayInfo.aidl
+ create mode 100644 core/java/android/content/om/OverlayInfo.java
+ create mode 100644 services/core/java/com/android/server/om/IdmapManager.java
+ create mode 100644 services/core/java/com/android/server/om/OverlayManagerService.java
+ create mode 100644 services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+ create mode 100644 services/core/java/com/android/server/om/OverlayManagerSettings.java
+ create mode 100644 services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+
+diff --git a/Android.mk b/Android.mk
+index bdb4555..df42780 100644
+--- a/Android.mk
++++ b/Android.mk
+@@ -137,6 +137,7 @@ LOCAL_SRC_FILES += \
+       core/java/android/content/ISyncContext.aidl \
+       core/java/android/content/ISyncServiceAdapter.aidl \
+       core/java/android/content/ISyncStatusObserver.aidl \
++      core/java/android/content/om/IOverlayManager.aidl \
+       core/java/android/content/pm/ILauncherApps.aidl \
+       core/java/android/content/pm/IOnAppsChangedListener.aidl \
+       core/java/android/content/pm/IOtaDexopt.aidl \
+diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
+index 3a2f471..1ca44e0 100644
+--- a/core/java/android/content/Context.java
++++ b/core/java/android/content/Context.java
+@@ -3656,6 +3656,16 @@ public abstract class Context {
+     public static final String GATEKEEPER_SERVICE = "android.service.gatekeeper.IGateKeeperService";
+     /**
++     * Use with {@link #getSystemService} to retrieve a {@link
++     * android.content.om.OverlayManager} for managing overlay packages.
++     *
++     * @see #getSystemService
++     * @see android.content.om.OverlayManager
++     * @hide
++     */
++    public static final String OVERLAY_SERVICE = "overlay";
++
++    /**
+      * Determine whether the given permission is allowed for a particular
+      * process and user ID running in the system.
+      *
+diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
+index 861aae5..1afae79 100644
+--- a/core/java/android/content/Intent.java
++++ b/core/java/android/content/Intent.java
+@@ -3092,6 +3092,40 @@ public class Intent implements Parcelable, Cloneable {
+             "android.intent.action.MEDIA_RESOURCE_GRANTED";
+     /**
++     * Broadcast Action: An overlay package has been installed. The data
++     * contains the name of the added overlay package.
++     * @hide
++     */
++    public static final String ACTION_OVERLAY_ADDED = "android.intent.action.OVERLAY_ADDED";
++
++    /**
++     * Broadcast Action: An overlay package has changed. The data contains the
++     * name of the overlay package which has changed. This is broadcast on all
++     * changes to the OverlayInfo returned by {@link
++     * android.content.om.IOverlayManager#getOverlayInfo(String, int)}. The
++     * most common change is a state change that will change whether the
++     * overlay is enabled or not.
++     * @hide
++     */
++    public static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
++
++    /**
++     * Broadcast Action: An overlay package has been removed. The data contains
++     * the name of the overlay package which has been removed.
++     * @hide
++     */
++    public static final String ACTION_OVERLAY_REMOVED = "android.intent.action.OVERLAY_REMOVED";
++
++    /**
++     * Broadcast Action: The order of a package's list of overlay packages has
++     * changed. The data contains the package name of the overlay package that
++     * had its position in the list adjusted.
++     * @hide
++     */
++    public static final String
++            ACTION_OVERLAY_PRIORITY_CHANGED = "android.intent.action.OVERLAY_PRIORITY_CHANGED";
++
++    /**
+      * Activity Action: Allow the user to select and return one or more existing
+      * documents. When invoked, the system will display the various
+      * {@link DocumentsProvider} instances installed on the device, letting the
+diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
+new file mode 100644
+index 0000000..4f5d960
+--- /dev/null
++++ b/core/java/android/content/om/IOverlayManager.aidl
+@@ -0,0 +1,129 @@
++/*
++ * Copyright (C) 2015 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package android.content.om;
++
++import android.content.om.OverlayInfo;
++
++/**
++ * Api for getting information about overlay packages.
++ *
++ * {@hide}
++ */
++interface IOverlayManager {
++    /**
++     * Returns information about all installed overlay packages for the
++     * specified user. If there are no installed overlay packages for this user,
++     * an empty map is returned (i.e. null is never returned). The returned map is a
++     * mapping of target package names to lists of overlays. Each list for a
++     * given target package is sorted in priority order, with the overlay with
++     * the highest priority at the end of the list.
++     *
++     * @param userId The user to get the OverlayInfos for.
++     * @return A Map<String, List<OverlayInfo>> with target package names
++     *         mapped to lists of overlays; if no overlays exist for the
++     *         requested user, an empty map is returned.
++     */
++    Map getAllOverlays(in int userId);
++
++    /**
++     * Returns information about all overlays for the given target package for
++     * the specified user. The returned list is ordered according to the
++     * overlay priority with the highest priority at the end of the list.
++     *
++     * @param targetPackageName The name of the target package.
++     * @param userId The user to get the OverlayInfos for.
++     * @return A list of OverlayInfo objects; if no overlays exist for the
++     *         requested package, an empty list is returned.
++     */
++    List getOverlayInfosForTarget(in String targetPackageName, in int userId);
++
++    /**
++     * Returns information about the overlay with the given package name for the
++     * specified user.
++     *
++     * @param packageName The name of the overlay package.
++     * @param userId The user to get the OverlayInfo for.
++     * @return The OverlayInfo for the overlay package; or null if no such
++     *         overlay package exists.
++     */
++    OverlayInfo getOverlayInfo(in String packageName, in int userId);
++
++    /**
++     * Request that an overlay package be enabled or disabled when possible to
++     * do so.
++     *
++     * It is always possible to disable an overlay, but due to technical and
++     * security reasons it may not always be possible to enable an overlay. An
++     * example of the latter is when the related target package is not
++     * installed. If the technical obstacle is later overcome, the overlay is
++     * automatically enabled at that point in time.
++     *
++     * An enabled overlay is a part of target package's resources, i.e. it will
++     * be part of any lookups performed via {@link android.content.res.Resources}
++     * and {@link android.content.res.AssetManager}. A disabled overlay will no
++     * longer affect the resources of the target package. If the target is
++     * currently running, its outdated resources will be replaced by new ones.
++     * This happens the same way as when an application enters or exits split
++     * window mode.
++     *
++     * @param packageName The name of the overlay package.
++     * @param enable true to enable the overlay, false to disable it.
++     * @param userId The user for which to change the overlay.
++     * @return true if the system successfully registered the request, false
++     *         otherwise.
++     */
++    boolean setEnabled(in String packageName, in boolean enable, in int userId);
++
++    /**
++     * Change the priority of the given overlay to be just higher than the
++     * overlay with package name newParentPackageName. Both overlay packages
++     * must have the same target and user.
++     *
++     * @see getOverlayInfosForTarget
++     *
++     * @param packageName The name of the overlay package whose priority should
++     *        be adjusted.
++     * @param newParentPackageName The name of the overlay package the newly
++     *        adjusted overlay package should just outrank.
++     * @param userId The user for which to change the overlay.
++     */
++    boolean setPriority(in String packageName, in String newParentPackageName, in int userId);
++
++    /**
++     * Change the priority of the given overlay to the highest priority relative to
++     * the other overlays with the same target and user.
++     *
++     * @see getOverlayInfosForTarget
++     *
++     * @param packageName The name of the overlay package whose priority should
++     *        be adjusted.
++     * @param userId The user for which to change the overlay.
++     */
++    boolean setHighestPriority(in String packageName, in int userId);
++
++    /**
++     * Change the priority of the overlay to the lowest priority relative to
++     * the other overlays for the same target and user.
++     *
++     * @see getOverlayInfosForTarget
++     *
++     * @param packageName The name of the overlay package whose priority should
++     *        be adjusted.
++     * @param userId The user for which to change the overlay.
++     */
++    boolean setLowestPriority(in String packageName, in int userId);
++}
+diff --git a/core/java/android/content/om/OverlayInfo.aidl b/core/java/android/content/om/OverlayInfo.aidl
+new file mode 100644
+index 0000000..e7d413d
+--- /dev/null
++++ b/core/java/android/content/om/OverlayInfo.aidl
+@@ -0,0 +1,19 @@
++/*
++ * Copyright (C) 2015 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package android.content.om;
++
++parcelable OverlayInfo;
+diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
+new file mode 100644
+index 0000000..a25cf0c
+--- /dev/null
++++ b/core/java/android/content/om/OverlayInfo.java
+@@ -0,0 +1,290 @@
++/*
++ * Copyright (C) 2015 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package android.content.om;
++
++import android.annotation.NonNull;
++import android.os.Parcel;
++import android.os.Parcelable;
++
++/**
++ * Immutable overlay information about a package. All PackageInfos that
++ * represent an overlay package will have a corresponding OverlayInfo.
++ *
++ * @hide
++ */
++public final class OverlayInfo implements Parcelable {
++    /**
++     * An internal state used as the initial state of an overlay. OverlayInfo
++     * objects exposed outside the {@link
++     * com.android.server.om.OverlayManagerService} should never have this
++     * state.
++     */
++    public static final int STATE_NOT_APPROVED_UNKNOWN = -1;
++
++    /**
++     * The overlay package is disabled by the PackageManager.
++     */
++    public static final int STATE_NOT_APPROVED_COMPONENT_DISABLED = 0;
++
++    /**
++     * The target package of the overlay is not installed.
++     */
++    public static final int STATE_NOT_APPROVED_MISSING_TARGET = 1;
++
++    /**
++     * Creation of idmap file failed (e.g. no matching resources).
++     */
++    public static final int STATE_NOT_APPROVED_NO_IDMAP = 2;
++
++    /**
++     * The overlay package is dangerous, i.e. it touches resources not explicitly
++     * OK'd by the target package.
++     */
++    public static final int STATE_NOT_APPROVED_DANGEROUS_OVERLAY = 3;
++
++    /**
++     * The OverlayInfo is currently disabled but it is allowed to be enabled
++     * ({@link #STATE_APPROVED_ENABLED}) in the future.
++     */
++    public static final int STATE_APPROVED_DISABLED = 4;
++
++    /**
++     * The OverlayInfo is enabled but can be disabled
++     * ({@link #STATE_APPROVED_DISABLED}) in the future.
++     */
++    public static final int STATE_APPROVED_ENABLED = 5;
++
++    /**
++     * Package name of the overlay package
++     */
++    public final String packageName;
++
++    /**
++     * Package name of the target package
++     */
++    public final String targetPackageName;
++
++    /**
++     * Full path to the base APK for this overlay package
++     */
++    public final String baseCodePath;
++
++    /**
++     * The state of this OverlayInfo as defined by the STATE_* constants in this class.
++     * <p/>
++     * The state of an OverlayInfo determines if it is approved and/or enabled. An OverlayInfo with
++     * one of the STATE_NOT_APPROVED_* states cannot be enabled, and can thus never be part of the
++     * best match in the resource lookup.
++     * <p/>
++     * The only way to get an overlay package to be active and be part of the best matching in the
++     * resource lookup is if the corresponding OverlayInfo is in an STATE_*_ENABLED state.
++     *
++     * @see #STATE_NOT_APPROVED_COMPONENT_DISABLED
++     * @see #STATE_NOT_APPROVED_MISSING_TARGET
++     * @see #STATE_NOT_APPROVED_NO_IDMAP
++     * @see #STATE_NOT_APPROVED_DANGEROUS_OVERLAY
++     * @see #STATE_APPROVED_DISABLED
++     * @see #STATE_APPROVED_ENABLED
++     */
++    public final int state;
++
++    /**
++     * User handle for which this overlay applies
++     */
++    public final int userId;
++
++    /**
++     * Create a new OverlayInfo based on source with an updated state.
++     *
++     * @param source the source OverlayInfo to base the new instance on
++     * @param state the new state for the source OverlayInfo
++     */
++    public OverlayInfo(@NonNull OverlayInfo source, int state) {
++        this(source.packageName, source.targetPackageName, source.baseCodePath, state,
++                source.userId);
++    }
++
++    public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
++            @NonNull String baseCodePath, int state, int userId) {
++        this.packageName = packageName;
++        this.targetPackageName = targetPackageName;
++        this.baseCodePath = baseCodePath;
++        this.state = state;
++        this.userId = userId;
++        ensureValidState();
++    }
++
++    public OverlayInfo(Parcel source) {
++        packageName = source.readString();
++        targetPackageName = source.readString();
++        baseCodePath = source.readString();
++        state = source.readInt();
++        userId = source.readInt();
++        ensureValidState();
++    }
++
++    private void ensureValidState() {
++        if (packageName == null) {
++            throw new IllegalArgumentException("packageName must not be null");
++        }
++        if (targetPackageName == null) {
++            throw new IllegalArgumentException("targetPackageName must not be null");
++        }
++        if (baseCodePath == null) {
++            throw new IllegalArgumentException("baseCodePath must not be null");
++        }
++        switch (state) {
++            case STATE_NOT_APPROVED_UNKNOWN:
++            case STATE_NOT_APPROVED_COMPONENT_DISABLED:
++            case STATE_NOT_APPROVED_MISSING_TARGET:
++            case STATE_NOT_APPROVED_NO_IDMAP:
++            case STATE_NOT_APPROVED_DANGEROUS_OVERLAY:
++            case STATE_APPROVED_DISABLED:
++            case STATE_APPROVED_ENABLED:
++                break;
++            default:
++                throw new IllegalArgumentException("State " + state + " is not a valid state");
++        }
++    }
++
++    @Override
++    public int describeContents() {
++        return 0;
++    }
++
++    @Override
++    public void writeToParcel(Parcel dest, int flags) {
++        dest.writeString(packageName);
++        dest.writeString(targetPackageName);
++        dest.writeString(baseCodePath);
++        dest.writeInt(state);
++        dest.writeInt(userId);
++    }
++
++    public static final Parcelable.Creator<OverlayInfo> CREATOR = new Parcelable.Creator<OverlayInfo>() {
++        @Override
++        public OverlayInfo createFromParcel(Parcel source) {
++            return new OverlayInfo(source);
++        }
++
++        @Override
++        public OverlayInfo[] newArray(int size) {
++            return new OverlayInfo[size];
++        }
++    };
++
++    /**
++     * Returns true if this overlay is enabled, i.e. should be used to overlay
++     * the resources in the target package.
++     *
++     * Disabled overlay packages are installed but are currently not in use.
++     *
++     * @return true if the overlay is enabled, else false.
++     */
++    public boolean isEnabled() {
++        switch (state) {
++            case STATE_APPROVED_ENABLED:
++                return true;
++            default:
++                return false;
++        }
++    }
++
++    /**
++     * Returns true if this overlay is approved.
++     *
++     * @return true if this overlay is approved, else false.
++     */
++    public boolean isApproved() {
++        switch (state) {
++            case STATE_APPROVED_ENABLED:
++            case STATE_APPROVED_DISABLED:
++                return true;
++            default:
++                return false;
++        }
++    }
++
++    public static String stateToString(int state) {
++        switch (state) {
++            case STATE_NOT_APPROVED_UNKNOWN:
++                return "STATE_NOT_APPROVED_UNKNOWN";
++            case STATE_NOT_APPROVED_COMPONENT_DISABLED:
++                return "STATE_NOT_APPROVED_COMPONENT_DISABLED";
++            case STATE_NOT_APPROVED_MISSING_TARGET:
++                return "STATE_NOT_APPROVED_MISSING_TARGET";
++            case STATE_NOT_APPROVED_NO_IDMAP:
++                return "STATE_NOT_APPROVED_NO_IDMAP";
++            case STATE_NOT_APPROVED_DANGEROUS_OVERLAY:
++                return "STATE_NOT_APPROVED_DANGEROUS_OVERLAY";
++            case STATE_APPROVED_DISABLED:
++                return "STATE_APPROVED_DISABLED";
++            case STATE_APPROVED_ENABLED:
++                return "STATE_APPROVED_ENABLED";
++            default:
++                return "<unknown state>";
++        }
++    }
++
++    @Override
++    public int hashCode() {
++        final int prime = 31;
++        int result = 1;
++        result = prime * result + userId;
++        result = prime * result + state;
++        result = prime * result + ((packageName == null) ? 0 : packageName.hashCode());
++        result = prime * result + ((targetPackageName == null) ? 0 : targetPackageName.hashCode());
++        result = prime * result + ((baseCodePath == null) ? 0 : baseCodePath.hashCode());
++        return result;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if (this == obj) {
++            return true;
++        }
++        if (obj == null) {
++            return false;
++        }
++        if (getClass() != obj.getClass()) {
++            return false;
++        }
++        OverlayInfo other = (OverlayInfo) obj;
++        if (userId != other.userId) {
++            return false;
++        }
++        if (state != other.state) {
++            return false;
++        }
++        if (!packageName.equals(other.packageName)) {
++            return false;
++        }
++        if (!targetPackageName.equals(other.targetPackageName)) {
++            return false;
++        }
++        if (!baseCodePath.equals(other.baseCodePath)) {
++            return false;
++        }
++        return true;
++    }
++
++    @Override
++    public String toString() {
++        return "OverlayInfo { overlay=" + packageName + ", target=" + targetPackageName + ", state="
++                + state + " (" + stateToString(state) + "), userId=" + userId + " }";
++    }
++}
+diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
+index f5bcf64..bdbdd1e 100644
+--- a/core/java/android/content/pm/PackageManagerInternal.java
++++ b/core/java/android/content/pm/PackageManagerInternal.java
+@@ -168,4 +168,28 @@ public abstract class PackageManagerInternal {
+      * @return Whether was launched.
+      */
+     public abstract boolean wasPackageEverLaunched(String packageName, int userId);
++
++    /**
++     * Get all overlay packages for a user.
++     * @param userId The user for which to get the overlays.
++     * @return A list of overlay packages. An empty list is returned if the
++     *         user has no installed overlay packages.
++     */
++    public abstract List<PackageInfo> getOverlayPackages(int userId);
++
++    /**
++     * Get the names of all target packages for a user.
++     * @param userId The user for which to get the package names.
++     * @return A list of target package names. This list includes the "android" package.
++     */
++    public abstract List<String> getTargetPackageNames(int userId);
++
++    /**
++     * Set which overlay to use for a package.
++     * @param userId The user for which to update the overlays.
++     * @param packageName The package name of the package for which to update the overlays.
++     * @param resourceDirs The paths to the overlay packages to use, ordered in the order in
++     *                     which to load the paths, or null if no overlays should be used.
++     */
++    public abstract void setResourceDirs(int userId, String packageName, String[] resourceDirs);
+ }
+diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
+index c2f12ef..986be28 100644
+--- a/core/res/AndroidManifest.xml
++++ b/core/res/AndroidManifest.xml
+@@ -84,6 +84,10 @@
+     <protected-broadcast android:name="android.intent.action.USER_INITIALIZE" />
+     <protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
+     <protected-broadcast android:name="android.intent.action.SU_SESSION_CHANGED" />
++    <protected-broadcast android:name="android.intent.action.OVERLAY_ADDED" />
++    <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
++    <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
++    <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
+     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
+     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
+diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
+new file mode 100644
+index 0000000..e2a3775
+--- /dev/null
++++ b/services/core/java/com/android/server/om/IdmapManager.java
+@@ -0,0 +1,116 @@
++/*
++ * Copyright (C) 2016 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package com.android.server.om;
++
++import static com.android.server.om.OverlayManagerService.DEBUG;
++import static com.android.server.om.OverlayManagerService.TAG;
++
++import android.annotation.NonNull;
++import android.content.om.OverlayInfo;
++import android.content.pm.PackageInfo;
++import android.os.UserHandle;
++import android.util.Slog;
++import com.android.internal.os.InstallerConnection.InstallerException;
++import com.android.server.pm.Installer;
++
++import java.io.DataInputStream;
++import java.io.File;
++import java.io.FileInputStream;
++import java.io.IOException;
++
++/**
++ * Handle the creation and deletion of idmap files.
++ *
++ * The actual work is performed by the idmap binary, launched through Installer
++ * and installd.
++ *
++ * Note: this class is subclassed in the OMS unit tests, and hence not marked as final.
++ */
++class IdmapManager {
++    private final Installer mInstaller;
++
++    IdmapManager(final Installer installer) {
++        mInstaller = installer;
++    }
++
++    boolean createIdmap(@NonNull final PackageInfo targetPackage,
++            @NonNull final PackageInfo overlayPackage, int userId) {
++        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
++        if (DEBUG) {
++            Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " +
++                    overlayPackage.packageName);
++        }
++        final int sharedGid = UserHandle.getSharedAppGid(targetPackage.applicationInfo.uid);
++        final String targetPath = targetPackage.applicationInfo.getBaseCodePath();
++        final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
++        try {
++            mInstaller.idmap(targetPath, overlayPath, sharedGid);
++        } catch (InstallerException e) {
++            Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " +
++                    overlayPath + ": " + e.getMessage());
++            return false;
++        }
++        return true;
++    }
++
++    boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
++        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
++        if (DEBUG) {
++            Slog.d(TAG, "remove idmap for " + oi.baseCodePath);
++        }
++        try {
++            mInstaller.removeIdmap(oi.baseCodePath);
++        } catch (InstallerException e) {
++            Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage());
++            return false;
++        }
++        return true;
++    }
++
++    boolean idmapExists(@NonNull final OverlayInfo oi) {
++        // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
++        return new File(getIdmapPath(oi.baseCodePath)).isFile();
++    }
++
++    boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
++        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
++        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
++    }
++
++    boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) {
++        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
++        return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath()));
++    }
++
++    private String getIdmapPath(@NonNull final String baseCodePath) {
++        final StringBuilder sb = new StringBuilder("/data/resource-cache/");
++        sb.append(baseCodePath.substring(1).replace('/', '@'));
++        sb.append("@idmap");
++        return sb.toString();
++    }
++
++    private boolean isDangerous(@NonNull final String idmapPath) {
++        try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) {
++            final int magic = dis.readInt();
++            final int version = dis.readInt();
++            final int dangerous = dis.readInt();
++            return dangerous != 0;
++        } catch (IOException e) {
++            return true;
++        }
++    }
++}
+diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
+new file mode 100644
+index 0000000..ec148dd
+--- /dev/null
++++ b/services/core/java/com/android/server/om/OverlayManagerService.java
+@@ -0,0 +1,901 @@
++/*
++ * Copyright (C) 2016 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package com.android.server.om;
++
++import static android.app.AppGlobals.getPackageManager;
++import static android.content.Intent.ACTION_PACKAGE_ADDED;
++import static android.content.Intent.ACTION_PACKAGE_CHANGED;
++import static android.content.Intent.ACTION_PACKAGE_REMOVED;
++import static android.content.Intent.ACTION_USER_REMOVED;
++import static android.content.pm.PackageManager.SIGNATURE_MATCH;
++
++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;
++import android.content.Intent;
++import android.content.IntentFilter;
++import android.content.om.IOverlayManager;
++import android.content.om.OverlayInfo;
++import android.content.pm.IPackageManager;
++import android.content.pm.PackageInfo;
++import android.content.pm.PackageManagerInternal;
++import android.content.pm.UserInfo;
++import android.net.Uri;
++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.UserHandle;
++import android.util.ArrayMap;
++import android.util.AtomicFile;
++import android.util.Slog;
++import android.util.SparseArray;
++
++import com.android.server.FgThread;
++import com.android.server.IoThread;
++import com.android.server.LocalServices;
++import com.android.server.SystemService;
++import com.android.server.pm.Installer;
++import com.android.server.pm.UserManagerService;
++
++import org.xmlpull.v1.XmlPullParserException;
++
++import java.io.File;
++import java.io.FileDescriptor;
++import java.io.FileInputStream;
++import java.io.FileOutputStream;
++import java.io.IOException;
++import java.io.PrintWriter;
++import java.util.ArrayList;
++import java.util.Collection;
++import java.util.Collections;
++import java.util.HashMap;
++import java.util.Iterator;
++import java.util.List;
++import java.util.Map;
++import java.util.concurrent.atomic.AtomicBoolean;
++
++/**
++ * Service to manage asset overlays.
++ *
++ * <p>Asset overlays are additional resources that come from apks loaded
++ * alongside the system and app apks. This service, the OverlayManagerService
++ * (OMS), tracks which installed overlays to use and provides methods to change
++ * this. Changes propagate to running applications as part of the Activity
++ * lifecycle. This allows Activities to reread their resources at a well
++ * defined point.</p>
++ *
++ * <p>By itself, the OMS will not change what overlays should be active.
++ * Instead, it is only responsible for making sure that overlays *can* be used
++ * from a technical and security point of view and to activate overlays in
++ * response to external requests. The responsibility to toggle overlays on and
++ * off lies within components that implement different use-cases such as themes
++ * or dynamic customization.</p>
++ *
++ * <p>The OMS receives input from three sources:</p>
++ *
++ * <ul>
++ *     <li>Callbacks from the SystemService class, specifically when the
++ *     Android framework is booting and when the end user switches Android
++ *     users.</li>
++ *
++ *     <li>Intents from the PackageManagerService (PMS). Overlays are regular
++ *     apks, and whenever a package is installed (or removed, or has a
++ *     component enabled or disabled), the PMS broadcasts this as an intent.
++ *     When the OMS receives one of these intents, it updates its internal
++ *     representation of the available overlays and, if there was a visible
++ *     change, triggers an asset refresh in the affected apps.</li>
++ *
++ *     <li>External requests via the {@link IOverlayManager AIDL interface}.
++ *     The interface allows clients to read information about the currently
++ *     available overlays, change whether an overlay should be used or not, and
++ *     change the relative order in which overlay packages are loaded.
++ *     Read-access is granted if the request targets the same Android user as
++ *     the caller runs as, or if the caller holds the
++ *     INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
++ *     caller is granted read-access and additionaly holds the
++ *     CHANGE_CONFIGURATION permission.</li>
++ * </ul>
++ *
++ * <p>The AIDL interface works with String package names, int user IDs, and
++ * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
++ * specific pair of target and overlay packages and include information such as
++ * the current state of the overlay. OverlayInfo objects are immutable.</p>
++ *
++ * <p>Internally, OverlayInfo objects are maintained by the
++ * OverlayManagerSettings class. The OMS and its helper classes are notified of
++ * changes to the settings by the OverlayManagerSettings.ChangeListener
++ * callback interface. The file /data/system/overlays.xml is used to persist
++ * the settings.</p>
++ *
++ * <p>Creation and deletion of idmap files are handled by the IdmapManager
++ * class.</p>
++ *
++ * <p>The following is an overview of OMS and its related classes. Note how box
++ * (2) does the heavy lifting, box (1) interacts with the Android framework,
++ * and box (3) replaces box (1) during unit testing.</p>
++ *
++ * <pre>
++ *         Android framework
++ *            |         ^
++ *      . . . | . . . . | . . . .
++ *     .      |         |       .
++ *     .    AIDL,   broadcasts  .
++ *     .   intents      |       .
++ *     .      |         |       . . . . . . . . . . . .
++ *     .      v         |       .                     .
++ *     .  OverlayManagerService . OverlayManagerTests .
++ *     .                  \     .     /               .
++ *     . (1)               \    .    /            (3) .
++ *      . . . . . . . . . . \ . . . / . . . . . . . . .
++ *     .                     \     /              .
++ *     . (2)                  \   /               .
++ *     .           OverlayManagerServiceImpl      .
++ *     .                  |            |          .
++ *     .                  |            |          .
++ *     . OverlayManagerSettings     IdmapManager  .
++ *     .                                          .
++ *     . . . .  . . . . . . . . . . . . . . . . . .
++ * </pre>
++ *
++ * <p>Finally, here is a list of keywords used in the OMS context.</p>
++ *
++ * <ul>
++ *     <li><b>target [package]</b> -- A regular apk that may have its resource
++ *     pool extended  by zero or more overlay packages.</li>
++ *
++ *     <li><b>overlay [package]</b> -- An apk that provides additional
++ *     resources to another apk.</li>
++ *
++ *     <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
++ *
++ *     <li><b>approved</b> -- An overlay is approved if the OMS has verified
++ *     that it can be used technically speaking (its target package is
++ *     installed, at least one resource name in both packages match, the
++ *     idmap was created, etc) and that it is secure to do so. External
++ *     clients can not change this state.</li>
++ *
++ *     <li><b>not approved</b> -- The opposite of approved.</li>
++ *
++ *     <li><b>enabled</b> -- An overlay currently in active use and thus part
++ *     of resource lookups. This requires the overlay to be approved. Only
++ *     external clients can change this state.</li>
++ *
++ *     <li><b>disabled</b> -- The opposite of enabled.</li>
++ *
++ *     <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
++ *     used during resource lookup. Also the name of the binary that creates
++ *     the mapping.</li>
++ * </ul>
++ */
++public final class OverlayManagerService extends SystemService {
++
++    static final String TAG = "OverlayManager";
++
++    static final boolean DEBUG = false;
++
++    private final Object mLock = new Object();
++
++    private final AtomicFile mSettingsFile;
++
++    private final PackageManagerHelper mPackageManager;
++
++    private final UserManagerService mUserManager;
++
++    private final OverlayManagerSettings mSettings;
++
++    private final OverlayManagerServiceImpl mImpl;
++
++    private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
++
++    public OverlayManagerService(@NonNull final Context context,
++            @NonNull final Installer installer) {
++        super(context);
++        mSettingsFile =
++            new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"));
++        mPackageManager = new PackageManagerHelper();
++        mUserManager = UserManagerService.getInstance();
++        IdmapManager im = new IdmapManager(installer);
++        mSettings = new OverlayManagerSettings();
++        mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings);
++
++        final IntentFilter packageFilter = new IntentFilter();
++        packageFilter.addAction(ACTION_PACKAGE_ADDED);
++        packageFilter.addAction(ACTION_PACKAGE_CHANGED);
++        packageFilter.addAction(ACTION_PACKAGE_REMOVED);
++        packageFilter.addDataScheme("package");
++        getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
++                packageFilter, null, null);
++
++        final IntentFilter userFilter = new IntentFilter();
++        userFilter.addAction(ACTION_USER_REMOVED);
++        getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
++                userFilter, null, null);
++
++        restoreSettings();
++        onSwitchUser(UserHandle.USER_SYSTEM);
++        schedulePersistSettings();
++
++        mSettings.addChangeListener(new OverlayChangeListener());
++
++        publishBinderService(Context.OVERLAY_SERVICE, mService);
++        publishLocalService(OverlayManagerService.class, this);
++    }
++
++    @Override
++    public void onStart() {
++        // Intentionally left empty.
++    }
++
++    @Override
++    public void onSwitchUser(final int newUserId) {
++        // ensure overlays in the settings are up-to-date, and propagate
++        // any asset changes to the rest of the system
++        final List<String> targets;
++        synchronized (mLock) {
++            targets = mImpl.onSwitchUser(newUserId);
++        }
++        updateAssets(newUserId, targets);
++    }
++
++    public List<String> getEnabledOverlayPaths(@NonNull final String packageName,
++            final int userId) {
++        synchronized (mLock) {
++            return mImpl.onGetEnabledOverlayPaths(packageName, userId);
++        }
++    }
++
++    private final class PackageReceiver extends BroadcastReceiver {
++        @Override
++        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
++            final Uri data = intent.getData();
++            if (data == null) {
++                Slog.e(TAG, "Cannot handle package broadcast with null data");
++                return;
++            }
++            final String packageName = data.getSchemeSpecificPart();
++
++            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
++
++            final int[] userIds;
++            final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
++            if (extraUid == UserHandle.USER_NULL) {
++                userIds = mUserManager.getUserIds();
++            } else {
++                userIds = new int[] { UserHandle.getUserId(extraUid) };
++            }
++
++            switch (intent.getAction()) {
++                case ACTION_PACKAGE_ADDED:
++                    if (replacing) {
++                        onPackageUpgraded(packageName, userIds);
++                    } else {
++                        onPackageAdded(packageName, userIds);
++                    }
++                    break;
++                case ACTION_PACKAGE_CHANGED:
++                    onPackageChanged(packageName, userIds);
++                    break;
++                case ACTION_PACKAGE_REMOVED:
++                    if (replacing) {
++                        onPackageUpgrading(packageName, userIds);
++                    } else {
++                        onPackageRemoved(packageName, userIds);
++                    }
++                    break;
++                default:
++                    // do nothing
++                    break;
++            }
++        }
++
++        private void onPackageAdded(@NonNull final String packageName,
++                @NonNull final int[] userIds) {
++            for (final int userId : userIds) {
++                synchronized (mLock) {
++                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
++                    if (pi != null) {
++                        mPackageManager.cachePackageInfo(packageName, userId, pi);
++                        if (!isOverlayPackage(pi)) {
++                            mImpl.onTargetPackageAdded(packageName, userId);
++                        } else {
++                            mImpl.onOverlayPackageAdded(packageName, userId);
++                        }
++                    }
++                }
++            }
++        }
++
++        private void onPackageChanged(@NonNull final String packageName,
++                @NonNull final int[] userIds) {
++            for (int userId : userIds) {
++                synchronized (mLock) {
++                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
++                    if (pi != null) {
++                        mPackageManager.cachePackageInfo(packageName, userId, pi);
++                        if (!isOverlayPackage(pi)) {
++                            mImpl.onTargetPackageChanged(packageName, userId);
++                        } else {
++                            mImpl.onOverlayPackageChanged(packageName, userId);
++                        }
++                    }
++                }
++            }
++        }
++
++        private void onPackageUpgrading(@NonNull final String packageName,
++                @NonNull final int[] userIds) {
++            for (int userId : userIds) {
++                synchronized (mLock) {
++                    mPackageManager.forgetPackageInfo(packageName, userId);
++                    final OverlayInfo oi = mImpl.onGetOverlayInfo(packageName, userId);
++                    if (oi == null) {
++                        mImpl.onTargetPackageUpgrading(packageName, userId);
++                    } else {
++                        mImpl.onOverlayPackageUpgrading(packageName, userId);
++                    }
++                }
++            }
++        }
++
++        private void onPackageUpgraded(@NonNull final String packageName,
++                @NonNull final int[] userIds) {
++            for (int userId : userIds) {
++                synchronized (mLock) {
++                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
++                    if (pi != null) {
++                        mPackageManager.cachePackageInfo(packageName, userId, pi);
++                        if (!isOverlayPackage(pi)) {
++                            mImpl.onTargetPackageUpgraded(packageName, userId);
++                        } else {
++                            mImpl.onOverlayPackageUpgraded(packageName, userId);
++                        }
++                    }
++                }
++            }
++        }
++
++        private void onPackageRemoved(@NonNull final String packageName,
++                @NonNull final int[] userIds) {
++            for (int userId : userIds) {
++                synchronized (mLock) {
++                    mPackageManager.forgetPackageInfo(packageName, userId);
++                    final OverlayInfo oi = mImpl.onGetOverlayInfo(packageName, userId);
++                    if (oi == null) {
++                        mImpl.onTargetPackageRemoved(packageName, userId);
++                    } else {
++                        mImpl.onOverlayPackageRemoved(packageName, userId);
++                    }
++                }
++            }
++        }
++    }
++
++    private final class UserReceiver extends BroadcastReceiver {
++        @Override
++        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
++            switch (intent.getAction()) {
++                case ACTION_USER_REMOVED:
++                    final int userId =
++                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
++                    if (userId != UserHandle.USER_NULL) {
++                        synchronized (mLock) {
++                            mImpl.onUserRemoved(userId);
++                            mPackageManager.forgetAllPackageInfos(userId);
++                        }
++                    }
++                    break;
++                default:
++                    // do nothing
++                    break;
++            }
++        }
++    }
++
++    private final IBinder mService = new IOverlayManager.Stub() {
++        @Override
++        public Map<String, List<OverlayInfo>> getAllOverlays(int userId)
++                throws RemoteException {
++            userId = handleIncomingUser(userId, "getAllOverlays");
++
++            synchronized (mLock) {
++                return mImpl.onGetOverlaysForUser(userId);
++            }
++        }
++
++        @Override
++        public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
++                int userId) throws RemoteException {
++            userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
++            if (targetPackageName == null) {
++                return Collections.emptyList();
++            }
++
++            synchronized (mLock) {
++                return mImpl.onGetOverlayInfosForTarget(targetPackageName, userId);
++            }
++        }
++
++        @Override
++        public OverlayInfo getOverlayInfo(@Nullable final String packageName,
++                int userId) throws RemoteException {
++            userId = handleIncomingUser(userId, "getOverlayInfo");
++            if (packageName == null) {
++                return null;
++            }
++
++            synchronized (mLock) {
++                return mImpl.onGetOverlayInfo(packageName, userId);
++            }
++        }
++
++        @Override
++        public boolean setEnabled(@Nullable final String packageName, final boolean enable,
++                int userId) throws RemoteException {
++            enforceChangeConfigurationPermission("setEnabled");
++            userId = handleIncomingUser(userId, "setEnabled");
++            if (packageName == null) {
++                return false;
++            }
++
++            final long ident = Binder.clearCallingIdentity();
++            try {
++                synchronized (mLock) {
++                    return mImpl.onSetEnabled(packageName, enable, userId);
++                }
++            } finally {
++                Binder.restoreCallingIdentity(ident);
++            }
++        }
++
++        @Override
++        public boolean setPriority(@Nullable final String packageName,
++                @Nullable final String parentPackageName, int userId) throws RemoteException {
++            enforceChangeConfigurationPermission("setPriority");
++            userId = handleIncomingUser(userId, "setPriority");
++            if (packageName == null || parentPackageName == null) {
++                return false;
++            }
++
++            final long ident = Binder.clearCallingIdentity();
++            try {
++                synchronized (mLock) {
++                    return mImpl.onSetPriority(packageName, parentPackageName, userId);
++                }
++            } finally {
++                Binder.restoreCallingIdentity(ident);
++            }
++        }
++
++        @Override
++        public boolean setHighestPriority(@Nullable final String packageName, int userId)
++                throws RemoteException {
++            enforceChangeConfigurationPermission("setHighestPriority");
++            userId = handleIncomingUser(userId, "setHighestPriority");
++            if (packageName == null) {
++                return false;
++            }
++
++            final long ident = Binder.clearCallingIdentity();
++            try {
++                synchronized (mLock) {
++                    return mImpl.onSetHighestPriority(packageName, userId);
++                }
++            } finally {
++                Binder.restoreCallingIdentity(ident);
++            }
++        }
++
++        @Override
++        public boolean setLowestPriority(@Nullable final String packageName, int userId)
++                throws RemoteException {
++            enforceChangeConfigurationPermission("setLowestPriority");
++            userId = handleIncomingUser(userId, "setLowestPriority");
++            if (packageName == null) {
++                return false;
++            }
++
++            final long ident = Binder.clearCallingIdentity();
++            try {
++                synchronized (mLock) {
++                    return mImpl.onSetLowestPriority(packageName, userId);
++                }
++            } finally {
++                Binder.restoreCallingIdentity(ident);
++            }
++        }
++
++        @Override
++        public void onShellCommand(@NonNull final FileDescriptor in,
++                @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
++                @NonNull final String[] args, @NonNull final ResultReceiver resultReceiver) {
++            (new OverlayManagerShellCommand(this)).exec(
++                    this, in, out, err, args, resultReceiver);
++        }
++
++        @Override
++        protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw,
++                @NonNull final String[] argv) {
++            enforceDumpPermission("dump");
++
++            final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]);
++
++            synchronized (mLock) {
++                mImpl.onDump(pw);
++                mPackageManager.dump(pw, verbose);
++            }
++        }
++
++        /**
++         * Ensure that the caller has permission to interact with the given userId.
++         * If the calling user is not the same as the provided user, the caller needs
++         * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
++         * root).
++         *
++         * @param userId the user to interact with
++         * @param message message for any SecurityException
++         */
++        private int handleIncomingUser(final int userId, @NonNull final String message) {
++            return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
++                    Binder.getCallingUid(), userId, false, true, message, null);
++        }
++
++        /**
++         * Enforce that the caller holds the CHANGE_CONFIGURATION permission (or is
++         * system or root).
++         *
++         * @param message used as message if SecurityException is thrown
++         * @throws SecurityException if the permission check fails
++         */
++        private void enforceChangeConfigurationPermission(@NonNull final String message) {
++            final int callingUid = Binder.getCallingUid();
++
++            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
++                getContext().enforceCallingOrSelfPermission(
++                        android.Manifest.permission.CHANGE_CONFIGURATION, message);
++            }
++        }
++
++        /**
++         * Enforce that the caller holds the DUMP permission (or is system or root).
++         *
++         * @param message used as message if SecurityException is thrown
++         * @throws SecurityException if the permission check fails
++         */
++        private void enforceDumpPermission(@NonNull final String message) {
++            final int callingUid = Binder.getCallingUid();
++
++            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
++                getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
++                        message);
++            }
++        }
++    };
++
++    private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
++        return pi != null && pi.overlayTarget != null;
++    }
++
++    private final class OverlayChangeListener implements OverlayManagerSettings.ChangeListener {
++        @Override
++        public void onSettingsChanged() {
++            schedulePersistSettings();
++        }
++
++        @Override
++        public void onOverlayAdded(@NonNull final OverlayInfo oi) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
++        }
++
++        @Override
++        public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
++        }
++
++        @Override
++        public void onOverlayChanged(@NonNull final OverlayInfo oi,
++                @NonNull final OverlayInfo oldOi) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
++        }
++
++        @Override
++        public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
++        }
++
++        private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
++                final boolean doUpdate) {
++            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
++        }
++
++        private final class BroadcastRunnable extends Thread {
++            private final String mAction;
++            private final OverlayInfo mOverlayInfo;
++            private final boolean mDoUpdate;
++
++            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
++                    final boolean doUpdate) {
++                mAction = action;
++                mOverlayInfo = oi;
++                mDoUpdate = doUpdate;
++            }
++
++            public void run() {
++                if (mDoUpdate) {
++                    updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
++                }
++                sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
++                        mOverlayInfo.userId);
++            }
++
++            private void sendBroadcast(@NonNull final String action,
++                    @NonNull final String targetPackageName, @NonNull final String packageName,
++                    final int userId) {
++                final Intent intent = new Intent(action, Uri.fromParts("package",
++                            String.format("%s/%s", targetPackageName, packageName), null));
++                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
++                if (DEBUG) {
++                    Slog.d(TAG, String.format("send broadcast %s", intent));
++                }
++                try {
++                    ActivityManagerNative.getDefault().broadcastIntent(null, intent, null, null, 0,
++                            null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
++                            userId);
++                } catch (RemoteException e) {
++                    // Intentionally left empty.
++                }
++            }
++
++        }
++    }
++
++    private void updateAssets(final int userId, final String targetPackageName) {
++        final List<String> list = new ArrayList<>();
++        list.add(targetPackageName);
++        updateAssets(userId, list);
++    }
++
++    private void updateAssets(final int userId, List<String> targetPackageNames) {
++        // TODO: uncomment 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, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
++        // synchronized (mLock) {
++        //     final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
++        //     for (final String packageName : targetPackageNames) {
++        //         final List<String> paths = new ArrayList<>();
++        //         paths.addAll(frameworkPaths);
++        //         if (!"android".equals(packageName)) {
++        //             paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
++        //         }
++        //         allPaths.put(packageName,
++        //             paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
++        //     }
++        // }
++
++        // for (String packageName : targetPackageNames) {
++        //     pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
++        // }
++
++        // final IActivityManager am = ActivityManagerNative.getDefault();
++        // try {
++        //     am.updateAssets(userId, targetPackageNames);
++        // } catch (RemoteException e) {
++        //     // Intentionally left empty.
++        // }
++    }
++
++    private void schedulePersistSettings() {
++        if (mPersistSettingsScheduled.get()) {
++            return;
++        }
++        mPersistSettingsScheduled.set(true);
++        IoThread.getHandler().post(new Runnable() {
++            @Override
++            public void run() {
++                mPersistSettingsScheduled.set(false);
++                synchronized (mLock) {
++                    FileOutputStream stream = null;
++                    try {
++                        stream = mSettingsFile.startWrite();
++                        mSettings.persist(stream);
++                        mSettingsFile.finishWrite(stream);
++                    } catch (IOException | XmlPullParserException e) {
++                        mSettingsFile.failWrite(stream);
++                        Slog.e(TAG, "failed to persist overlay state", e);
++                    }
++                }
++            }
++        });
++    }
++
++    private void restoreSettings() {
++        synchronized (mLock) {
++            if (!mSettingsFile.getBaseFile().exists()) {
++                return;
++            }
++            try (final FileInputStream stream = mSettingsFile.openRead()) {
++                mSettings.restore(stream);
++
++                // We might have data for dying users if the device was
++                // restarted before we received USER_REMOVED. Remove data for
++                // users that will not exist after the system is ready.
++
++                for (final UserInfo deadUser : getDeadUsers()) {
++                    final int userId = deadUser.getUserHandle().getIdentifier();
++                    mSettings.removeUser(userId);
++                }
++            } catch (IOException | XmlPullParserException e) {
++                Slog.e(TAG, "failed to restore overlay state", e);
++            }
++        }
++    }
++
++    private List<UserInfo> getDeadUsers() {
++        final List<UserInfo> users = mUserManager.getUsers(false);
++        final List<UserInfo> onlyLiveUsers = mUserManager.getUsers(true);
++
++        // UserInfo doesn't implement equals, so we'll roll our own
++        // Collection.removeAll implementation
++        final Iterator<UserInfo> iter = users.iterator();
++        while (iter.hasNext()) {
++            final UserInfo ui = iter.next();
++            for (final UserInfo live : onlyLiveUsers) {
++                if (ui.id == live.id) {
++                    iter.remove();
++                    break;
++                }
++            }
++        }
++
++        return users;
++    }
++
++    private static final class PackageManagerHelper implements
++        OverlayManagerServiceImpl.PackageManagerHelper {
++
++        private final IPackageManager mPackageManager;
++        private final PackageManagerInternal mPackageManagerInternal;
++
++        // Use a cache for performance and for consistency within OMS: because
++        // additional PACKAGE_* intents may be delivered while we process an
++        // intent, querying the PackageManagerService for the actual current
++        // state may lead to contradictions within OMS. Better then to lag
++        // behind until all pending intents have been processed.
++        private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
++
++        public PackageManagerHelper() {
++            mPackageManager = getPackageManager();
++            mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
++        }
++
++        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
++                final boolean useCache) {
++            if (useCache) {
++                final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
++                if (cachedPi != null) {
++                    return cachedPi;
++                }
++            }
++            try {
++                final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
++                if (useCache && pi != null) {
++                    cachePackageInfo(packageName, userId, pi);
++                }
++                return pi;
++            } catch (RemoteException e) {
++                // Intentionally left empty.
++            }
++            return null;
++        }
++
++        @Override
++        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
++            return getPackageInfo(packageName, userId, true);
++        }
++
++        @Override
++        public boolean signaturesMatching(@NonNull final String packageName1,
++                @NonNull final String packageName2, final int userId) {
++            // The package manager does not support different versions of packages
++            // to be installed for different users: ignore userId for now.
++            try {
++                return mPackageManager.checkSignatures(packageName1, packageName2) == SIGNATURE_MATCH;
++            } catch (RemoteException e) {
++                // Intentionally left blank
++            }
++            return false;
++        }
++
++        @Override
++        public List<PackageInfo> getOverlayPackages(final int userId) {
++            return mPackageManagerInternal.getOverlayPackages(userId);
++        }
++
++        public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
++                final int userId) {
++            final HashMap<String, PackageInfo> map = mCache.get(userId);
++            return map == null ? null : map.get(packageName);
++        }
++
++        public void cachePackageInfo(@NonNull final String packageName, final int userId,
++                @NonNull final PackageInfo pi) {
++            HashMap<String, PackageInfo> map = mCache.get(userId);
++            if (map == null) {
++                map = new HashMap<>();
++                mCache.put(userId, map);
++            }
++            map.put(packageName, pi);
++        }
++
++        public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
++            final HashMap<String, PackageInfo> map = mCache.get(userId);
++            if (map == null) {
++                return;
++            }
++            map.remove(packageName);
++            if (map.isEmpty()) {
++                mCache.delete(userId);
++            }
++        }
++
++        public void forgetAllPackageInfos(final int userId) {
++            mCache.delete(userId);
++        }
++
++        private static final String TAB1 = "    ";
++        private static final String TAB2 = TAB1 + TAB1;
++
++        public void dump(@NonNull final PrintWriter pw, final boolean verbose) {
++            pw.println("PackageInfo cache");
++
++            if (!verbose) {
++                int n = 0;
++                for (int i = 0; i < mCache.size(); i++) {
++                    final int userId = mCache.keyAt(i);
++                    n += mCache.get(userId).size();
++                }
++                pw.println(TAB1 + n + " package(s)");
++                return;
++            }
++
++            if (mCache.size() == 0) {
++                pw.println(TAB1 + "<empty>");
++                return;
++            }
++
++            for (int i = 0; i < mCache.size(); i++) {
++                final int userId = mCache.keyAt(i);
++                pw.println(TAB1 + "User " + userId);
++                final HashMap<String, PackageInfo> map = mCache.get(userId);
++                for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
++                    pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
++                }
++            }
++        }
++    }
++}
+diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+new file mode 100644
+index 0000000..2a0d88b
+--- /dev/null
++++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+@@ -0,0 +1,478 @@
++/*
++ * Copyright (C) 2016 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package com.android.server.om;
++
++import static android.content.om.OverlayInfo.STATE_APPROVED_DISABLED;
++import static android.content.om.OverlayInfo.STATE_APPROVED_ENABLED;
++import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_COMPONENT_DISABLED;
++import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
++import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_MISSING_TARGET;
++import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_NO_IDMAP;
++import static com.android.server.om.OverlayManagerService.DEBUG;
++import static com.android.server.om.OverlayManagerService.TAG;
++
++import android.annotation.NonNull;
++import android.annotation.Nullable;
++import android.content.om.OverlayInfo;
++import android.content.pm.ApplicationInfo;
++import android.content.pm.PackageInfo;
++import android.util.ArrayMap;
++import android.util.ArraySet;
++import android.util.Slog;
++
++import java.io.PrintWriter;
++import java.util.ArrayList;
++import java.util.Iterator;
++import java.util.List;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Internal implementation of OverlayManagerService.
++ *
++ * Methods in this class should only be called by the OverlayManagerService.
++ * This class is not thread-safe; the caller is expected to ensure the
++ * necessary thread synchronization.
++ *
++ * @see OverlayManagerService
++ */
++final class OverlayManagerServiceImpl {
++    private final PackageManagerHelper mPackageManager;
++    private final IdmapManager mIdmapManager;
++    private final OverlayManagerSettings mSettings;
++
++    OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
++            @NonNull final IdmapManager idmapManager,
++            @NonNull final OverlayManagerSettings settings) {
++        mPackageManager = packageManager;
++        mIdmapManager = idmapManager;
++        mSettings = settings;
++    }
++
++    /*
++     * Call this when switching to a new Android user. Will return a list of
++     * target packages that must refresh their overlays. This list is the union
++     * of two sets: the set of targets with currently active overlays, and the
++     * set of targets that had, but no longer have, active overlays.
++     */
++    List<String> onSwitchUser(final int newUserId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
++        }
++
++        final Set<String> packagesToUpdateAssets = new ArraySet<>();
++        final Map<String, List<OverlayInfo>> tmp = mSettings.getOverlaysForUser(newUserId);
++        final Map<String, OverlayInfo> storedOverlayInfos = new ArrayMap<>(tmp.size());
++        for (final List<OverlayInfo> chunk: tmp.values()) {
++            for (final OverlayInfo oi: chunk) {
++                storedOverlayInfos.put(oi.packageName, oi);
++            }
++        }
++
++        for (PackageInfo overlayPackage: mPackageManager.getOverlayPackages(newUserId)) {
++            final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
++            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
++                if (oi != null) {
++                    packagesToUpdateAssets.add(oi.targetPackageName);
++                }
++                mSettings.init(overlayPackage.packageName, newUserId,
++                        overlayPackage.overlayTarget,
++                        overlayPackage.applicationInfo.getBaseCodePath());
++            }
++
++            try {
++                final PackageInfo targetPackage =
++                    mPackageManager.getPackageInfo(overlayPackage.overlayTarget, newUserId);
++                updateState(targetPackage, overlayPackage, newUserId);
++            } catch (OverlayManagerSettings.BadKeyException e) {
++                Slog.e(TAG, "failed to update settings", e);
++                mSettings.remove(overlayPackage.packageName, newUserId);
++            }
++
++            packagesToUpdateAssets.add(overlayPackage.overlayTarget);
++            storedOverlayInfos.remove(overlayPackage.packageName);
++        }
++
++        // any OverlayInfo left in storedOverlayInfos is no longer
++        // installed and should be removed
++        for (final OverlayInfo oi: storedOverlayInfos.values()) {
++            mSettings.remove(oi.packageName, oi.userId);
++            removeIdmapIfPossible(oi);
++            packagesToUpdateAssets.add(oi.targetPackageName);
++        }
++
++        // remove target packages that are not installed
++        final Iterator<String> iter = packagesToUpdateAssets.iterator();
++        while (iter.hasNext()) {
++            String targetPackageName = iter.next();
++            if (mPackageManager.getPackageInfo(targetPackageName, newUserId) == null) {
++                iter.remove();
++            }
++        }
++
++        return new ArrayList<String>(packagesToUpdateAssets);
++    }
++
++    void onUserRemoved(final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onUserRemoved userId=" + userId);
++        }
++        mSettings.removeUser(userId);
++    }
++
++    void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
++        updateAllOverlaysForTarget(packageName, userId, targetPackage);
++    }
++
++    void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
++        updateAllOverlaysForTarget(packageName, userId, targetPackage);
++    }
++
++    void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId=" + userId);
++        }
++
++        updateAllOverlaysForTarget(packageName, userId, null);
++    }
++
++    void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
++        updateAllOverlaysForTarget(packageName, userId, targetPackage);
++    }
++
++    void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
++        }
++
++        updateAllOverlaysForTarget(packageName, userId, null);
++    }
++
++    private void updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
++            @Nullable final PackageInfo targetPackage) {
++        final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
++        for (final OverlayInfo oi : ois) {
++            final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
++            if (overlayPackage == null) {
++                mSettings.remove(oi.packageName, oi.userId);
++                removeIdmapIfPossible(oi);
++            } else {
++                try {
++                    updateState(targetPackage, overlayPackage, userId);
++                } catch (OverlayManagerSettings.BadKeyException e) {
++                    Slog.e(TAG, "failed to update settings", e);
++                    mSettings.remove(oi.packageName, userId);
++                }
++            }
++        }
++    }
++
++    void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
++        if (overlayPackage == null) {
++            Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
++            onOverlayPackageRemoved(packageName, userId);
++            return;
++        }
++
++        final PackageInfo targetPackage =
++            mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
++
++        mSettings.init(packageName, userId, overlayPackage.overlayTarget,
++                overlayPackage.applicationInfo.getBaseCodePath());
++        try {
++            updateState(targetPackage, overlayPackage, userId);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            Slog.e(TAG, "failed to update settings", e);
++            mSettings.remove(packageName, userId);
++        }
++    }
++
++    void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
++        if (overlayPackage == null) {
++            Slog.w(TAG, "overlay package " + packageName + " was changed, but couldn't be found");
++            onOverlayPackageRemoved(packageName, userId);
++            return;
++        }
++
++        final PackageInfo targetPackage =
++            mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
++
++        try {
++            updateState(targetPackage, overlayPackage, userId);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            Slog.e(TAG, "failed to update settings", e);
++            mSettings.remove(packageName, userId);
++        }
++    }
++
++    void onOverlayPackageUpgrading(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onOverlayPackageUpgrading packageName=" + packageName + " userId=" + userId);
++        }
++
++        try {
++            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
++            mSettings.setUpgrading(packageName, userId, true);
++            removeIdmapIfPossible(oi);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            Slog.e(TAG, "failed to update settings", e);
++            mSettings.remove(packageName, userId);
++        }
++    }
++
++    void onOverlayPackageUpgraded(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onOverlayPackageUpgraded packageName=" + packageName + " userId=" + userId);
++        }
++
++        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
++        if (overlayPackage == null) {
++            Slog.w(TAG, "overlay package " + packageName + " was upgraded, but couldn't be found");
++            onOverlayPackageRemoved(packageName, userId);
++            return;
++        }
++
++        try {
++            final String storedTargetPackageName = mSettings.getTargetPackageName(packageName, userId);
++            if (!overlayPackage.overlayTarget.equals(storedTargetPackageName)) {
++                // Sneaky little hobbitses, changing the overlay's target package
++                // from one version to the next! We can't use the old version's
++                // state.
++                mSettings.remove(packageName, userId);
++                onOverlayPackageAdded(packageName, userId);
++                return;
++            }
++
++            mSettings.setUpgrading(packageName, userId, false);
++            final PackageInfo targetPackage =
++                mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
++            updateState(targetPackage, overlayPackage, userId);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            Slog.e(TAG, "failed to update settings", e);
++            mSettings.remove(packageName, userId);
++        }
++    }
++
++    void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, "onOverlayPackageRemoved packageName=" + packageName + " userId=" + userId);
++        }
++
++        try {
++            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
++            mSettings.remove(packageName, userId);
++            removeIdmapIfPossible(oi);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            Slog.e(TAG, "failed to remove overlay package", e);
++        }
++    }
++
++    OverlayInfo onGetOverlayInfo(@NonNull final String packageName, final int userId) {
++        try {
++            return mSettings.getOverlayInfo(packageName, userId);
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            return null;
++        }
++    }
++
++    List<OverlayInfo> onGetOverlayInfosForTarget(@NonNull final String targetPackageName,
++            final int userId) {
++        return mSettings.getOverlaysForTarget(targetPackageName, userId);
++    }
++
++    Map<String, List<OverlayInfo>> onGetOverlaysForUser(final int userId) {
++        return mSettings.getOverlaysForUser(userId);
++    }
++
++    boolean onSetEnabled(@NonNull final String packageName, final boolean enable,
++            final int userId) {
++        if (DEBUG) {
++            Slog.d(TAG, String.format("onSetEnabled packageName=%s enable=%s userId=%d",
++                        packageName, enable, userId));
++        }
++
++        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
++        if (overlayPackage == null) {
++            return false;
++        }
++
++        try {
++            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
++            final PackageInfo targetPackage =
++                mPackageManager.getPackageInfo(oi.targetPackageName, userId);
++            mSettings.setEnabled(packageName, userId, enable);
++            updateState(targetPackage, overlayPackage, userId);
++            return true;
++        } catch (OverlayManagerSettings.BadKeyException e) {
++            return false;
++        }
++    }
++
++    boolean onSetPriority(@NonNull final String packageName,
++            @NonNull final String newParentPackageName, final int userId) {
++        return mSettings.setPriority(packageName, newParentPackageName, userId);
++    }
++
++    boolean onSetHighestPriority(@NonNull final String packageName, final int userId) {
++        return mSettings.setHighestPriority(packageName, userId);
++    }
++
++    boolean onSetLowestPriority(@NonNull final String packageName, final int userId) {
++        return mSettings.setLowestPriority(packageName, userId);
++    }
++
++    void onDump(@NonNull final PrintWriter pw) {
++        mSettings.dump(pw);
++    }
++
++    List<String> onGetEnabledOverlayPaths(@NonNull final String targetPackageName,
++            final int userId) {
++        final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId);
++        final List<String> paths = new ArrayList<>(overlays.size());
++        for (final OverlayInfo oi : overlays) {
++            if (oi.isEnabled()) {
++                paths.add(oi.baseCodePath);
++            }
++        }
++        return paths;
++    }
++
++    private void updateState(@Nullable final PackageInfo targetPackage,
++            @NonNull final PackageInfo overlayPackage, final int userId)
++        throws OverlayManagerSettings.BadKeyException {
++        if (targetPackage != null) {
++            mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
++        }
++
++        mSettings.setBaseCodePath(overlayPackage.packageName, userId,
++                overlayPackage.applicationInfo.getBaseCodePath());
++
++        final int currentState = mSettings.getState(overlayPackage.packageName, userId);
++        final int newState = calculateNewState(targetPackage, overlayPackage, userId);
++        if (currentState != newState) {
++            if (DEBUG) {
++                Slog.d(TAG, String.format("%s:%d: %s -> %s",
++                            overlayPackage.packageName, userId,
++                            OverlayInfo.stateToString(currentState),
++                            OverlayInfo.stateToString(newState)));
++            }
++            mSettings.setState(overlayPackage.packageName, userId, newState);
++        }
++    }
++
++    private int calculateNewState(@Nullable final PackageInfo targetPackage,
++            @NonNull final PackageInfo overlayPackage, final int userId)
++        throws OverlayManagerSettings.BadKeyException {
++        if (!overlayPackage.applicationInfo.enabled) {
++            return STATE_NOT_APPROVED_COMPONENT_DISABLED;
++        }
++
++        if (targetPackage == null) {
++            return STATE_NOT_APPROVED_MISSING_TARGET;
++        }
++
++        if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
++            return STATE_NOT_APPROVED_NO_IDMAP;
++        }
++
++        final boolean enableIfApproved = mSettings.getEnabled(overlayPackage.packageName, userId);
++
++        if (mPackageManager.signaturesMatching(targetPackage.packageName,
++                    overlayPackage.packageName, userId)) {
++            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
++        }
++
++        if ((overlayPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
++            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
++        }
++
++        if (!mIdmapManager.isDangerous(overlayPackage, userId)) {
++            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
++        }
++
++        return STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
++    }
++
++    private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
++        // For a given package, all Android users share the same idmap file.
++        // This works because Android currently does not support users to
++        // install different versions of the same package. It also means we
++        // cannot remove an idmap file if any user still needs it.
++        //
++        // When/if the Android framework allows different versions of the same
++        // package to be installed for different users, idmap file handling
++        // should be revised:
++        //
++        // - an idmap file should be unique for each {user, package} pair
++        //
++        // - the path to the idmap file should be passed to the native Asset
++        //   Manager layers, just like the path to the apk is passed today
++        //
++        // As part of that change, calls to this method should be replaced by
++        // direct calls to IdmapManager.removeIdmap, without looping over all
++        // users.
++
++        if (!mIdmapManager.idmapExists(oi)) {
++            return;
++        }
++        final List<Integer> userIds = mSettings.getUsers();
++        for (final int userId : userIds) {
++            try {
++                final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
++                if (tmp != null && tmp.isEnabled()) {
++                    // someone is still using the idmap file -> we cannot remove it
++                    return;
++                }
++            } catch (OverlayManagerSettings.BadKeyException e) {
++                // intentionally left empty
++            }
++        }
++        mIdmapManager.removeIdmap(oi, oi.userId);
++    }
++
++    interface PackageManagerHelper {
++        PackageInfo getPackageInfo(@NonNull String packageName, int userId);
++        boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
++                                   int userId);
++        List<PackageInfo> getOverlayPackages(int userId);
++    }
++}
+diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
+new file mode 100644
+index 0000000..af0bb64
+--- /dev/null
++++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
+@@ -0,0 +1,656 @@
++/*
++ * Copyright (C) 2016 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package com.android.server.om;
++
++import static android.content.om.OverlayInfo.STATE_NOT_APPROVED_UNKNOWN;
++import static com.android.server.om.OverlayManagerService.DEBUG;
++import static com.android.server.om.OverlayManagerService.TAG;
++
++import android.annotation.NonNull;
++import android.annotation.Nullable;
++import android.content.om.OverlayInfo;
++import android.util.AndroidRuntimeException;
++import android.util.ArrayMap;
++import android.util.Slog;
++import android.util.Xml;
++
++import com.android.internal.util.FastXmlSerializer;
++import com.android.internal.util.XmlUtils;
++
++import org.xmlpull.v1.XmlPullParser;
++import org.xmlpull.v1.XmlPullParserException;
++
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.InputStreamReader;
++import java.io.OutputStream;
++import java.io.PrintWriter;
++import java.util.ArrayList;
++import java.util.Collections;
++import java.util.Iterator;
++import java.util.List;
++import java.util.ListIterator;
++import java.util.Map;
++
++/**
++ * Data structure representing the current state of all overlay packages in the
++ * system.
++ *
++ * Modifications to the data are exposed through the ChangeListener interface.
++ *
++ * @see ChangeListener
++ * @see OverlayManagerService
++ */
++final class OverlayManagerSettings {
++    private final List<ChangeListener> mListeners = new ArrayList<>();
++
++    private final ArrayList<SettingsItem> mItems = new ArrayList<>();
++
++    void init(@NonNull final String packageName, final int userId,
++            @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
++        remove(packageName, userId);
++        final SettingsItem item =
++            new SettingsItem(packageName, userId, targetPackageName, baseCodePath);
++        mItems.add(item);
++    }
++
++    void remove(@NonNull final String packageName, final int userId) {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            return;
++        }
++        final OverlayInfo oi = item.getOverlayInfo();
++        mItems.remove(item);
++        if (oi != null) {
++            notifyOverlayRemoved(oi);
++        }
++    }
++
++    boolean contains(@NonNull final String packageName, final int userId) {
++        return select(packageName, userId) != null;
++    }
++
++    OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        return item.getOverlayInfo();
++    }
++
++    String getTargetPackageName(@NonNull final String packageName, final int userId)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        return item.getTargetPackageName();
++    }
++
++    void setBaseCodePath(@NonNull final String packageName, final int userId,
++            @NonNull final String path) throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        item.setBaseCodePath(path);
++        notifySettingsChanged();
++    }
++
++    boolean getUpgrading(@NonNull final String packageName, final int userId)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        return item.isUpgrading();
++    }
++
++    void setUpgrading(@NonNull final String packageName, final int userId, final boolean newValue)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        if (newValue == item.isUpgrading()) {
++            return; // nothing to do
++        }
++
++        if (newValue) {
++            final OverlayInfo oi = item.getOverlayInfo();
++            item.setUpgrading(true);
++            item.setState(STATE_NOT_APPROVED_UNKNOWN);
++            notifyOverlayRemoved(oi);
++        } else {
++            item.setUpgrading(false);
++        }
++        notifySettingsChanged();
++    }
++
++    boolean getEnabled(@NonNull final String packageName, final int userId) throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        return item.isEnabled();
++    }
++
++    void setEnabled(@NonNull final String packageName, final int userId, final boolean enable)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        if (enable == item.isEnabled()) {
++            return; // nothing to do
++        }
++
++        item.setEnabled(enable);
++        notifySettingsChanged();
++    }
++
++    int getState(@NonNull final String packageName, final int userId) throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        return item.getState();
++    }
++
++    void setState(@NonNull final String packageName, final int userId, final int state)
++            throws BadKeyException {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null) {
++            throw new BadKeyException(packageName, userId);
++        }
++        final OverlayInfo previous = item.getOverlayInfo();
++        item.setState(state);
++        final OverlayInfo current = item.getOverlayInfo();
++        if (previous.state == STATE_NOT_APPROVED_UNKNOWN) {
++            notifyOverlayAdded(current);
++            notifySettingsChanged();
++        } else if (current.state != previous.state) {
++            notifyOverlayChanged(current, previous);
++            notifySettingsChanged();
++        }
++    }
++
++    List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
++            final int userId) {
++        final List<SettingsItem> items = selectWhereTarget(targetPackageName, userId);
++        if (items.isEmpty()) {
++            return Collections.emptyList();
++        }
++        final List<OverlayInfo> out = new ArrayList<>(items.size());
++        for (final SettingsItem item : items) {
++            if (item.isUpgrading()) {
++                continue;
++            }
++            out.add(item.getOverlayInfo());
++        }
++        return out;
++    }
++
++    Map<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
++        final List<SettingsItem> items = selectWhereUser(userId);
++        if (items.isEmpty()) {
++            return Collections.emptyMap();
++        }
++        final Map<String, List<OverlayInfo>> out = new ArrayMap<>(items.size());
++        for (final SettingsItem item : items) {
++            if (item.isUpgrading()) {
++                continue;
++            }
++            final String targetPackageName = item.getTargetPackageName();
++            if (!out.containsKey(targetPackageName)) {
++                out.put(targetPackageName, new ArrayList<OverlayInfo>());
++            }
++            final List<OverlayInfo> overlays = out.get(targetPackageName);
++            overlays.add(item.getOverlayInfo());
++        }
++        return out;
++    }
++
++    List<String> getTargetPackageNamesForUser(final int userId) {
++        final List<SettingsItem> items = selectWhereUser(userId);
++        if (items.isEmpty()) {
++            return Collections.emptyList();
++        }
++        final List<String> out = new ArrayList<>();
++        for (final SettingsItem item : items) {
++            if (item.isUpgrading()) {
++                continue;
++            }
++            final String targetPackageName = item.getTargetPackageName();
++            if (!out.contains(targetPackageName)) {
++                out.add(targetPackageName);
++            }
++        }
++        return out;
++    }
++
++    List<Integer> getUsers() {
++        final ArrayList<Integer> users = new ArrayList<>();
++        for (final SettingsItem item : mItems) {
++            if (!users.contains(item.userId)) {
++                users.add(item.userId);
++            }
++        }
++        return users;
++    }
++
++    void removeUser(final int userId) {
++        final Iterator<SettingsItem> iter = mItems.iterator();
++        while (iter.hasNext()) {
++            final SettingsItem item = iter.next();
++            if (item.userId == userId) {
++                iter.remove();
++            }
++        }
++    }
++
++    boolean setPriority(@NonNull final String packageName,
++            @NonNull final String newParentPackageName, final int userId) {
++        if (packageName.equals(newParentPackageName)) {
++            return false;
++        }
++        final SettingsItem rowToMove = select(packageName, userId);
++        if (rowToMove == null || rowToMove.isUpgrading()) {
++            return false;
++        }
++        final SettingsItem newParentRow = select(newParentPackageName, userId);
++        if (newParentRow == null || newParentRow.isUpgrading()) {
++            return false;
++        }
++        if (!rowToMove.getTargetPackageName().equals(newParentRow.getTargetPackageName())) {
++            return false;
++        }
++
++        mItems.remove(rowToMove);
++        final ListIterator<SettingsItem> iter = mItems.listIterator();
++        while (iter.hasNext()) {
++            final SettingsItem item = iter.next();
++            if (item.userId == userId && item.packageName.equals(newParentPackageName)) {
++                iter.add(rowToMove);
++                notifyOverlayPriorityChanged(rowToMove.getOverlayInfo());
++                notifySettingsChanged();
++                return true;
++            }
++        }
++
++        Slog.wtf(TAG, "failed to find the parent item a second time");
++        return false;
++    }
++
++    boolean setLowestPriority(@NonNull final String packageName, final int userId) {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null || item.isUpgrading()) {
++            return false;
++        }
++        mItems.remove(item);
++        mItems.add(0, item);
++        notifyOverlayPriorityChanged(item.getOverlayInfo());
++        notifySettingsChanged();
++        return true;
++    }
++
++    boolean setHighestPriority(@NonNull final String packageName, final int userId) {
++        final SettingsItem item = select(packageName, userId);
++        if (item == null || item.isUpgrading()) {
++            return false;
++        }
++        mItems.remove(item);
++        mItems.add(item);
++        notifyOverlayPriorityChanged(item.getOverlayInfo());
++        notifySettingsChanged();
++        return true;
++    }
++
++    private static final String TAB1 = "    ";
++    private static final String TAB2 = TAB1 + TAB1;
++    private static final String TAB3 = TAB2 + TAB1;
++
++    void dump(@NonNull final PrintWriter pw) {
++        pw.println("Settings");
++        dumpItems(pw);
++        dumpListeners(pw);
++    }
++
++    private void dumpItems(@NonNull final PrintWriter pw) {
++        pw.println(TAB1 + "Items");
++
++        if (mItems.isEmpty()) {
++            pw.println(TAB2 + "<none>");
++            return;
++        }
++
++        for (final SettingsItem item : mItems) {
++            final StringBuilder sb = new StringBuilder();
++            sb.append(TAB2 + item.packageName + ":" + item.userId + " {\n");
++            sb.append(TAB3 + "packageName.......: " + item.packageName + "\n");
++            sb.append(TAB3 + "userId............: " + item.userId + "\n");
++            sb.append(TAB3 + "targetPackageName.: " + item.getTargetPackageName() + "\n");
++            sb.append(TAB3 + "baseCodePath......: " + item.getBaseCodePath() + "\n");
++            sb.append(TAB3 + "state.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
++            sb.append(TAB3 + "isEnabled.........: " + item.isEnabled() + "\n");
++            sb.append(TAB3 + "isUpgrading.......: " + item.isUpgrading() + "\n");
++            sb.append(TAB2 + "}");
++            pw.println(sb.toString());
++        }
++    }
++
++    private void dumpListeners(@NonNull final PrintWriter pw) {
++        pw.println(TAB1 + "Change listeners");
++
++        if (mListeners.isEmpty()) {
++            pw.println(TAB2 + "<none>");
++            return;
++        }
++
++        for (ChangeListener ch : mListeners) {
++            pw.println(TAB2 + ch);
++        }
++
++    }
++
++    void restore(@NonNull final InputStream is) throws IOException, XmlPullParserException {
++        Serializer.restore(mItems, is);
++    }
++
++    void persist(@NonNull final OutputStream os) throws IOException, XmlPullParserException {
++        Serializer.persist(mItems, os);
++    }
++
++    private static final class Serializer {
++        private static final String TAG_OVERLAYS = "overlays";
++        private static final String TAG_ITEM = "item";
++
++        private static final String ATTR_BASE_CODE_PATH = "baseCodePath";
++        private static final String ATTR_IS_ENABLED = "isEnabled";
++        private static final String ATTR_IS_UPGRADING = "isUpgrading";
++        private static final String ATTR_PACKAGE_NAME = "packageName";
++        private static final String ATTR_STATE = "state";
++        private static final String ATTR_TARGET_PACKAGE_NAME = "targetPackageName";
++        private static final String ATTR_USER_ID = "userId";
++        private static final String ATTR_VERSION = "version";
++
++        private static final int CURRENT_VERSION = 1;
++
++        public static void restore(@NonNull final ArrayList<SettingsItem> table,
++                @NonNull final InputStream is) throws IOException, XmlPullParserException {
++
++            table.clear();
++            final XmlPullParser parser = Xml.newPullParser();
++            parser.setInput(new InputStreamReader(is));
++            XmlUtils.beginDocument(parser, TAG_OVERLAYS);
++            int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION);
++            if (version != CURRENT_VERSION) {
++                throw new XmlPullParserException("unrecognized version " + version);
++            }
++            int depth = parser.getDepth();
++
++            while (XmlUtils.nextElementWithin(parser, depth)) {
++                switch (parser.getName()) {
++                    case TAG_ITEM:
++                        final SettingsItem item = restoreRow(parser, depth + 1);
++                        table.add(item);
++                        break;
++                }
++            }
++        }
++
++        private static SettingsItem restoreRow(@NonNull final XmlPullParser parser, final int depth)
++                throws IOException {
++            final String packageName = XmlUtils.readStringAttribute(parser, ATTR_PACKAGE_NAME);
++            final int userId = XmlUtils.readIntAttribute(parser, ATTR_USER_ID);
++            final String targetPackageName = XmlUtils.readStringAttribute(parser,
++                    ATTR_TARGET_PACKAGE_NAME);
++            final String baseCodePath = XmlUtils.readStringAttribute(parser, ATTR_BASE_CODE_PATH);
++            final int state = XmlUtils.readIntAttribute(parser, ATTR_STATE);
++            final boolean isEnabled = XmlUtils.readBooleanAttribute(parser, ATTR_IS_ENABLED);
++            final boolean isUpgrading = XmlUtils.readBooleanAttribute(parser, ATTR_IS_UPGRADING);
++
++            return new SettingsItem(packageName, userId, targetPackageName, baseCodePath, state,
++                    isEnabled, isUpgrading);
++        }
++
++        public static void persist(@NonNull final ArrayList<SettingsItem> table,
++                @NonNull final OutputStream os) throws IOException, XmlPullParserException {
++            final FastXmlSerializer xml = new FastXmlSerializer();
++            xml.setOutput(os, "utf-8");
++            xml.startDocument(null, true);
++            xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
++            xml.startTag(null, TAG_OVERLAYS);
++            XmlUtils.writeIntAttribute(xml, ATTR_VERSION, CURRENT_VERSION);
++
++            for (final SettingsItem item : table) {
++                persistRow(xml, item);
++            }
++            xml.endTag(null, TAG_OVERLAYS);
++            xml.endDocument();
++        }
++
++        private static void persistRow(@NonNull final FastXmlSerializer xml,
++                @NonNull final SettingsItem item) throws IOException {
++            xml.startTag(null, TAG_ITEM);
++            XmlUtils.writeStringAttribute(xml, ATTR_PACKAGE_NAME, item.packageName);
++            XmlUtils.writeIntAttribute(xml, ATTR_USER_ID, item.userId);
++            XmlUtils.writeStringAttribute(xml, ATTR_TARGET_PACKAGE_NAME, item.targetPackageName);
++            XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.baseCodePath);
++            XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.state);
++            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.isEnabled);
++            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_UPGRADING, item.isUpgrading);
++            xml.endTag(null, TAG_ITEM);
++        }
++    }
++
++    private static final class SettingsItem {
++        private final int userId;
++        private final String packageName;
++        private final String targetPackageName;
++        private String baseCodePath;
++        private int state;
++        private boolean isEnabled;
++        private boolean isUpgrading;
++        private OverlayInfo cache;
++
++        SettingsItem(@NonNull final String packageName, final int userId,
++                @NonNull final String targetPackageName, @NonNull final String baseCodePath,
++                final int state, final boolean isEnabled, final boolean isUpgrading) {
++            this.packageName = packageName;
++            this.userId = userId;
++            this.targetPackageName = targetPackageName;
++            this.baseCodePath = baseCodePath;
++            this.state = state;
++            this.isEnabled = isEnabled;
++            this.isUpgrading = isUpgrading;
++            cache = null;
++        }
++
++        SettingsItem(@NonNull final String packageName, final int userId,
++                @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
++            this(packageName, userId, targetPackageName, baseCodePath, STATE_NOT_APPROVED_UNKNOWN,
++                    false, false);
++        }
++
++        private String getTargetPackageName() {
++            return targetPackageName;
++        }
++
++        private String getBaseCodePath() {
++            return baseCodePath;
++        }
++
++        private void setBaseCodePath(@NonNull final String path) {
++            if (!baseCodePath.equals(path)) {
++                baseCodePath = path;
++                invalidateCache();
++            }
++        }
++
++        private int getState() {
++            return state;
++        }
++
++        private void setState(final int state) {
++            if (this.state != state) {
++                this.state = state;
++                invalidateCache();
++            }
++        }
++
++        private boolean isEnabled() {
++            return isEnabled;
++        }
++
++        private void setEnabled(final boolean enable) {
++            if (isEnabled != enable) {
++                isEnabled = enable;
++                invalidateCache();
++            }
++        }
++
++        private boolean isUpgrading() {
++            return isUpgrading;
++        }
++
++        private void setUpgrading(final boolean upgrading) {
++            if (isUpgrading != upgrading) {
++                isUpgrading = upgrading;
++                invalidateCache();
++            }
++        }
++
++        private OverlayInfo getOverlayInfo() {
++            if (isUpgrading) {
++                return null;
++            }
++            if (cache == null) {
++                cache = new OverlayInfo(packageName, targetPackageName, baseCodePath,
++                        state, userId);
++            }
++            return cache;
++        }
++
++        private void invalidateCache() {
++            cache = null;
++        }
++    }
++
++    private SettingsItem select(@NonNull final String packageName, final int userId) {
++        for (final SettingsItem item : mItems) {
++            if (item.userId == userId && item.packageName.equals(packageName)) {
++                return item;
++            }
++        }
++        return null;
++    }
++
++    private List<SettingsItem> selectWhereUser(final int userId) {
++        final ArrayList<SettingsItem> items = new ArrayList<>();
++        for (final SettingsItem item : mItems) {
++            if (item.userId == userId) {
++                items.add(item);
++            }
++        }
++        return items;
++    }
++
++    private List<SettingsItem> selectWhereTarget(@NonNull final String targetPackageName,
++            final int userId) {
++        final ArrayList<SettingsItem> items = new ArrayList<>();
++        for (final SettingsItem item : mItems) {
++            if (item.userId == userId && item.getTargetPackageName().equals(targetPackageName)) {
++                items.add(item);
++            }
++        }
++        return items;
++    }
++
++    private void assertNotNull(@Nullable final Object o) {
++        if (o == null) {
++            throw new AndroidRuntimeException("object must not be null");
++        }
++    }
++
++    void addChangeListener(@NonNull final ChangeListener listener) {
++        mListeners.add(listener);
++    }
++
++    void removeChangeListener(@NonNull final ChangeListener listener) {
++        mListeners.remove(listener);
++    }
++
++    private void notifySettingsChanged() {
++        for (final ChangeListener listener : mListeners) {
++            listener.onSettingsChanged();
++        }
++    }
++
++    private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
++        if (DEBUG) {
++            assertNotNull(oi);
++        }
++        for (final ChangeListener listener : mListeners) {
++            listener.onOverlayAdded(oi);
++        }
++    }
++
++    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
++        if (DEBUG) {
++            assertNotNull(oi);
++        }
++        for (final ChangeListener listener : mListeners) {
++            listener.onOverlayRemoved(oi);
++        }
++    }
++
++    private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
++            @NonNull final OverlayInfo oldOi) {
++        if (DEBUG) {
++            assertNotNull(oi);
++            assertNotNull(oldOi);
++        }
++        for (final ChangeListener listener : mListeners) {
++            listener.onOverlayChanged(oi, oldOi);
++        }
++    }
++
++    private void notifyOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
++        if (DEBUG) {
++            assertNotNull(oi);
++        }
++        for (final ChangeListener listener : mListeners) {
++            listener.onOverlayPriorityChanged(oi);
++        }
++    }
++
++    interface ChangeListener {
++        void onSettingsChanged();
++        void onOverlayAdded(@NonNull OverlayInfo oi);
++        void onOverlayRemoved(@NonNull OverlayInfo oi);
++        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
++        void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
++    }
++
++    static final class BadKeyException extends RuntimeException {
++        public BadKeyException(@NonNull final String packageName, final int userId) {
++            super("Bad key packageName=" + packageName + " userId=" + userId);
++        }
++    }
++}
+diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+new file mode 100644
+index 0000000..d6f5373
+--- /dev/null
++++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+@@ -0,0 +1,179 @@
++/*
++ * Copyright (C) 2016 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package com.android.server.om;
++
++import android.annotation.NonNull;
++import android.annotation.Nullable;
++import android.content.om.IOverlayManager;
++import android.content.om.OverlayInfo;
++import android.os.RemoteException;
++import android.os.ShellCommand;
++import android.os.UserHandle;
++
++import java.io.PrintWriter;
++import java.util.List;
++import java.util.Map;
++
++/**
++ * Implementation of 'cmd overlay' commands.
++ *
++ * This class provides an interface to the OverlayManagerService via adb.
++ * Intended only for manual debugging. Execute 'adb exec-out cmd overlay help'
++ * for a list of available commands.
++ */
++final class OverlayManagerShellCommand extends ShellCommand {
++    private final IOverlayManager mInterface;
++
++    OverlayManagerShellCommand(@NonNull final IOverlayManager iom) {
++        mInterface = iom;
++    }
++
++    @Override
++    public int onCommand(@Nullable final String cmd) {
++        if (cmd == null) {
++            return handleDefaultCommands(cmd);
++        }
++        final PrintWriter err = getErrPrintWriter();
++        try {
++            switch (cmd) {
++                case "list":
++                    return runList();
++                case "enable":
++                    return runEnableDisable(true);
++                case "disable":
++                    return runEnableDisable(false);
++                case "set-priority":
++                    return runSetPriority();
++                default:
++                    return handleDefaultCommands(cmd);
++            }
++        } catch (IllegalArgumentException e) {
++            err.println("Error: " + e.getMessage());
++        } catch (RemoteException e) {
++            err.println("Remote exception: " + e);
++        }
++        return -1;
++    }
++
++    @Override
++    public void onHelp() {
++        final PrintWriter out = getOutPrintWriter();
++        out.println("Overlay manager (overlay) commands:");
++        out.println("  help");
++        out.println("    Print this help text.");
++        out.println("  dump [--verbose] [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
++        out.println("    Print debugging information about the overlay manager.");
++        out.println("  list [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
++        out.println("    Print information about target and overlay packages.");
++        out.println("    Overlay packages are printed in priority order. With optional");
++        out.println("    parameters PACKAGEs, limit output to the specified packages");
++        out.println("    but include more information about each package.");
++        out.println("  enable [--user USER_ID] PACKAGE");
++        out.println("    Enable overlay package PACKAGE.");
++        out.println("  disable [--user USER_ID] PACKAGE");
++        out.println("    Disable overlay package PACKAGE.");
++        out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
++        out.println("    Change the priority of the overlay PACKAGE to be just higher than");
++        out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
++        out.println("    'lowest', change priority of PACKAGE to the lowest priority.");
++        out.println("    If PARENT is the special keyword 'highest', change priority of");
++        out.println("    PACKAGE to the highest priority.");
++    }
++
++    private int runList() throws RemoteException {
++        final PrintWriter out = getOutPrintWriter();
++        final PrintWriter err = getErrPrintWriter();
++
++        int userId = UserHandle.USER_SYSTEM;
++        String opt;
++        while ((opt = getNextOption()) != null) {
++            switch (opt) {
++                case "--user":
++                    userId = UserHandle.parseUserArg(getNextArgRequired());
++                    break;
++                default:
++                    err.println("Error: Unknown option: " + opt);
++                    return 1;
++            }
++        }
++
++        final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
++        for (final String targetPackageName : allOverlays.keySet()) {
++            out.println(targetPackageName);
++            for (final OverlayInfo oi : allOverlays.get(targetPackageName)) {
++                String status = "---";
++                if (oi.isApproved()) {
++                    status = "[ ]";
++                }
++                if (oi.isEnabled()) {
++                    status = "[x]";
++                }
++                out.println(String.format("%s %s", status, oi.packageName));
++            }
++            out.println();
++        }
++        return 0;
++    }
++
++    private int runEnableDisable(final boolean enable) throws RemoteException {
++        final PrintWriter err = getErrPrintWriter();
++
++        int userId = UserHandle.USER_SYSTEM;
++        String opt;
++        while ((opt = getNextOption()) != null) {
++            switch (opt) {
++                case "--user":
++                    userId = UserHandle.parseUserArg(getNextArgRequired());
++                    break;
++                default:
++                    err.println("Error: Unknown option: " + opt);
++                    return 1;
++            }
++        }
++
++        final String packageName = getNextArgRequired();
++        return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
++    }
++
++    private int runSetPriority() throws RemoteException {
++        final PrintWriter err = getErrPrintWriter();
++
++        int userId = UserHandle.USER_SYSTEM;
++        String opt;
++        while ((opt = getNextOption()) != null) {
++            switch (opt) {
++                case "--user":
++                    userId = UserHandle.parseUserArg(getNextArgRequired());
++                    break;
++                default:
++                    err.println("Error: Unknown option: " + opt);
++                    return 1;
++            }
++        }
++
++        final String packageName = getNextArgRequired();
++        final String newParentPackageName = getNextArgRequired();
++
++        if ("highest".equals(newParentPackageName)) {
++            return mInterface.setHighestPriority(packageName, userId) ? 0 : 1;
++        } else if ("lowest".equals(newParentPackageName)) {
++            return mInterface.setLowestPriority(packageName, userId) ? 0 : 1;
++        } else {
++            return mInterface.setPriority(packageName, newParentPackageName, userId) ? 0 : 1;
++        }
++    }
++}
+diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
+index 583cb23..3892f8f 100644
+--- a/services/core/java/com/android/server/pm/PackageManagerService.java
++++ b/services/core/java/com/android/server/pm/PackageManagerService.java
+@@ -21444,6 +21444,47 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
+                 return mSettings.wasPackageEverLaunchedLPr(packageName, userId);
+             }
+         }
++
++        @Override
++        public List<PackageInfo> getOverlayPackages(int userId) {
++            final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
++            synchronized (mPackages) {
++                for (PackageParser.Package p : mPackages.values()) {
++                    if (p.mOverlayTarget != null) {
++                        PackageInfo pkg = generatePackageInfo((PackageSetting)p.mExtras, 0, userId);
++                        if (pkg != null) {
++                            overlayPackages.add(pkg);
++                        }
++                    }
++                }
++            }
++            return overlayPackages;
++        }
++
++        @Override
++        public List<String> getTargetPackageNames(int userId) {
++            List<String> targetPackages = new ArrayList<>();
++            synchronized (mPackages) {
++                for (PackageParser.Package p : mPackages.values()) {
++                    if (p.mOverlayTarget == null) {
++                        targetPackages.add(p.packageName);
++                    }
++                }
++            }
++            return targetPackages;
++        }
++
++        @Override
++        public void setResourceDirs(int userId, String packageName, String[] resourceDirs) {
++            // TODO: uncomment when we integrate OMS properly
++            // synchronized (mPackages) {
++            //     PackageSetting ps = mSettings.mPackages.get(packageName);
++            //     if (ps == null) {
++            //         return;
++            //     }
++            //     ps.setResourceDirs(resourceDirs, userId);
++            // }
++        }
+     }
+     @Override
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch b/patches/frameworks/base/0003-OMS7-N-Integrate-OverlayManagerService-into-framewor.patch
new file mode 100644 (file)
index 0000000..5104306
--- /dev/null
@@ -0,0 +1,1473 @@
+From 2a5bd30d939fd04580f162115ddba6c359290b6f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Thu, 2 Jun 2016 09:35:31 +0200
+Subject: [PATCH 03/38] OMS7-N: Integrate OverlayManagerService into framework
+ [3/11]
+
+Hand over ownership of overlays to OverlayManagerService.
+
+Changes to a package's overlays are propagated using the activity life
+cycle. Affected activities will be recreated as needed. This provides a
+well-defined point to modify an application's assets while the
+application is paused.
+
+Consolidate how overlays targeting the system and overlays targeting
+regular applications are handled. Previously, system overlays were
+handled as a special case. Now, everything is handled identically. As a
+side effect, the call to idmap --scan during Zygote boot has become
+obsolete and is removed.
+
+Deprecate and remove use of SCAN_TRUSTED_OVERLAY from
+PackageManagerService. Previously, the flag was used to restrict what
+paths overlays were allowed to be installed in. Now, overlay packages
+are first class packages and it is up to the OverlayManagerService to
+decide whether to use the overlay or not.
+
+Information on what overlays to use is recorded in
+ApplicationInfo.resourceDirs. The PackageManagerService is responsible
+for the creation of ApplicationInfo objects. The OverlayManagerService
+is responsible for informing the PackageManagerService in advance about
+what resourceDirs to use.
+
+When launching an application, the ApplicationInfo is already populated
+with up-to-date information about overlays.
+
+When enabling or disabling an overlay for a running application, the
+OverlayManagerService first notifies the OverlayManagerService about the
+updated resourceDirs. It then tells the ActivityManagerService to push
+the new ApplicationInfo object to the application's ActivityThread.
+Finally the application requests its ResourcesManager to create new
+ResourcesImpl objects based on the updated paths.
+
+Change-Id: If0b1eaa690c38f9c33f7c8dc981314205a73fa9c
+---
+ cmds/idmap/Android.mk                              |   2 +-
+ cmds/idmap/idmap.cpp                               |  55 ---------
+ cmds/idmap/idmap.h                                 |   6 -
+ core/java/android/app/ActivityManagerNative.java   |  30 +++++
+ core/java/android/app/ActivityThread.java          |  45 +++++++
+ core/java/android/app/ApplicationThreadNative.java |  21 ++++
+ core/java/android/app/IActivityManager.java        |   2 +
+ core/java/android/app/IApplicationThread.java      |   2 +
+ core/java/android/app/ResourcesManager.java        | 119 ++++++++++++++----
+ core/java/android/content/pm/PackageParser.java    |  20 +--
+ core/java/android/content/pm/PackageUserState.java |   6 +
+ core/jni/android_util_AssetManager.cpp             |  95 ---------------
+ include/androidfw/AssetManager.h                   |  15 +--
+ libs/androidfw/AssetManager.cpp                    | 104 ----------------
+ .../com/android/server/SystemServiceManager.java   |  24 ++--
+ .../android/server/am/ActivityManagerService.java  |  51 ++++++++
+ .../android/server/om/OverlayManagerService.java   |  61 +++++-----
+ .../android/server/pm/PackageManagerService.java   | 134 ++++-----------------
+ .../com/android/server/pm/PackageSettingBase.java  |   8 +-
+ .../core/java/com/android/server/pm/Settings.java  |   4 +-
+ services/java/com/android/server/SystemServer.java |   4 +
+ 21 files changed, 335 insertions(+), 473 deletions(-)
+
+diff --git a/cmds/idmap/Android.mk b/cmds/idmap/Android.mk
+index 50ccb07..eb6da18 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 @@ 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\
+@@ -49,11 +47,6 @@ OPTIONS \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\
+ \n\
+@@ -97,16 +90,6 @@ 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;
+@@ -167,36 +150,6 @@ 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
+@@ -235,14 +188,6 @@ 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]);
+     }
+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_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_
+diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
+index 50479c8..389f342 100644
+--- a/core/java/android/app/ActivityManagerNative.java
++++ b/core/java/android/app/ActivityManagerNative.java
+@@ -16,6 +16,7 @@
+ package android.app;
++import android.annotation.NonNull;
+ import android.annotation.UserIdInt;
+ import android.app.ActivityManager.StackInfo;
+ import android.app.assist.AssistContent;
+@@ -1226,6 +1227,19 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
+             return true;
+         }
++        case UPDATE_ASSETS_TRANSACTION: {
++            data.enforceInterface(IActivityManager.descriptor);
++            final int userId = data.readInt();
++            final int N = data.readInt();
++            final List<String> packageNames = new ArrayList<>();
++            for (int i = 0; i < N; i++) {
++                packageNames.add(data.readString());
++            }
++            updateAssets(userId, packageNames);
++            reply.writeNoException();
++            return true;
++        }
++
+         case SET_REQUESTED_ORIENTATION_TRANSACTION: {
+             data.enforceInterface(IActivityManager.descriptor);
+             IBinder token = data.readStrongBinder();
+@@ -4586,6 +4600,22 @@ class ActivityManagerProxy implements IActivityManager
+         data.recycle();
+         reply.recycle();
+     }
++    public void updateAssets(final int userId, @NonNull final List<String> packageNames)
++            throws RemoteException
++    {
++        final Parcel data = Parcel.obtain();
++        final Parcel reply = Parcel.obtain();
++        data.writeInterfaceToken(IActivityManager.descriptor);
++        data.writeInt(userId);
++        data.writeInt(packageNames.size());
++        for (int i = 0; i < packageNames.size(); i++) {
++            data.writeString(packageNames.get(i));
++        }
++        mRemote.transact(UPDATE_ASSETS_TRANSACTION, data, reply, 0);
++        reply.readException();
++        data.recycle();
++        reply.recycle();
++    }
+     public void setRequestedOrientation(IBinder token, int requestedOrientation)
+             throws RemoteException {
+         Parcel data = Parcel.obtain();
+diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
+index 2d22f26..55fc25d 100644
+--- a/core/java/android/app/ActivityThread.java
++++ b/core/java/android/app/ActivityThread.java
+@@ -897,6 +897,14 @@ public final class ActivityThread {
+             sendMessage(H.CONFIGURATION_CHANGED, config);
+         }
++        public void scheduleAssetsChanged(@NonNull final String packageName,
++                @NonNull final ApplicationInfo ai) {
++            final SomeArgs args = SomeArgs.obtain();
++            args.arg1 = packageName;
++            args.arg2 = ai;
++            sendMessage(H.ASSETS_CHANGED, args);
++        }
++
+         public void updateTimeZone() {
+             TimeZone.setDefault(null);
+         }
+@@ -1405,6 +1413,7 @@ public final class ActivityThread {
+         public static final int MULTI_WINDOW_MODE_CHANGED = 152;
+         public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
+         public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
++        public static final int ASSETS_CHANGED = 155;
+         String codeToString(int code) {
+             if (DEBUG_MESSAGES) {
+@@ -1461,6 +1470,7 @@ public final class ActivityThread {
+                     case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED";
+                     case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
+                     case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
++                    case ASSETS_CHANGED: return "ASSETS_CHANGED";
+                 }
+             }
+             return Integer.toString(code);
+@@ -1716,6 +1726,10 @@ public final class ActivityThread {
+                     handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
+                             (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
+                     break;
++                case ASSETS_CHANGED:
++                    handleAssetsChanged((String)((SomeArgs)msg.obj).arg1,
++                            (ApplicationInfo)((SomeArgs)msg.obj).arg2);
++                    break;
+             }
+             Object obj = msg.obj;
+             if (obj instanceof SomeArgs) {
+@@ -4803,6 +4817,37 @@ public final class ActivityThread {
+         }
+     }
++    final void handleAssetsChanged(@NonNull final String packageToUpdate,
++            @NonNull final ApplicationInfo ai) {
++        synchronized (mResourcesManager) {
++            // Update all affected loaded packages with new overlay package information
++            final ArrayList<WeakReference<LoadedApk>> loadedPackages = new ArrayList<>();
++            loadedPackages.addAll(mPackages.values());
++            loadedPackages.addAll(mResourcePackages.values());
++            for (final WeakReference<LoadedApk> ref : loadedPackages) {
++                final LoadedApk apk = ref.get();
++                if (apk != null) {
++                    final String packageName = apk.getPackageName();
++                    if (packageToUpdate.equals(packageName)) {
++                        apk.updateApplicationInfo(ai, null);
++                    }
++                }
++            }
++
++            // Update all affected Resources objects to use new ResourcesImpl
++            mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs);
++        }
++
++        // Schedule all activities to reload
++        for (final Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
++            final Activity activity = entry.getValue().activity;
++            if (!activity.mFinished) {
++                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false,
++                        false);
++            }
++        }
++    }
++
+     static void freeTextLayoutCachesIfNeeded(int configDiff) {
+         if (configDiff != 0) {
+             // Ask text layout engine to free its caches if there is a locale change
+diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
+index 05d9d7e..47b05ee 100644
+--- a/core/java/android/app/ApplicationThreadNative.java
++++ b/core/java/android/app/ApplicationThreadNative.java
+@@ -16,6 +16,7 @@
+ package android.app;
++import android.annotation.NonNull;
+ import android.content.ComponentName;
+ import android.content.Intent;
+ import android.content.IIntentReceiver;
+@@ -331,6 +332,15 @@ public abstract class ApplicationThreadNative extends Binder
+             return true;
+         }
++        case SCHEDULE_ASSETS_CHANGED_TRANSACTION:
++        {
++            data.enforceInterface(IApplicationThread.descriptor);
++            final String packageName = data.readString();
++            final ApplicationInfo ai = ApplicationInfo.CREATOR.createFromParcel(data);
++            scheduleAssetsChanged(packageName, ai);
++            return true;
++        }
++
+         case UPDATE_TIME_ZONE_TRANSACTION: {
+             data.enforceInterface(IApplicationThread.descriptor);
+             updateTimeZone();
+@@ -1126,6 +1136,17 @@ class ApplicationThreadProxy implements IApplicationThread {
+         data.recycle();
+     }
++    public final void scheduleAssetsChanged(@NonNull final String packageName,
++            @NonNull final ApplicationInfo ai) throws RemoteException {
++        final Parcel data = Parcel.obtain();
++        data.writeInterfaceToken(IApplicationThread.descriptor);
++        data.writeString(packageName);
++        ai.writeToParcel(data, 0);
++        mRemote.transact(SCHEDULE_ASSETS_CHANGED_TRANSACTION, data, null,
++                IBinder.FLAG_ONEWAY);
++        data.recycle();
++    }
++
+     public void updateTimeZone() throws RemoteException {
+         Parcel data = Parcel.obtain();
+         data.writeInterfaceToken(IApplicationThread.descriptor);
+diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
+index 5a4470b..c7522b9 100644
+--- a/core/java/android/app/IActivityManager.java
++++ b/core/java/android/app/IActivityManager.java
+@@ -266,6 +266,7 @@ public interface IActivityManager extends IInterface {
+     public Configuration getConfiguration() throws RemoteException;
+     public void updateConfiguration(Configuration values) throws RemoteException;
++    public void updateAssets(int userId, List<String> packageNames) throws RemoteException;
+     public void setRequestedOrientation(IBinder token,
+             int requestedOrientation) throws RemoteException;
+     public int getRequestedOrientation(IBinder token) throws RemoteException;
+@@ -1075,4 +1076,5 @@ public interface IActivityManager extends IInterface {
+     int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
+     int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
+     int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380;
++    int UPDATE_ASSETS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 381;
+ }
+diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
+index 3fa88ae..fcc97e3 100644
+--- a/core/java/android/app/IApplicationThread.java
++++ b/core/java/android/app/IApplicationThread.java
+@@ -104,6 +104,7 @@ public interface IApplicationThread extends IInterface {
+     void scheduleExit() throws RemoteException;
+     void scheduleSuicide() throws RemoteException;
+     void scheduleConfigurationChanged(Configuration config) throws RemoteException;
++    void scheduleAssetsChanged(String packageName, ApplicationInfo ai) throws RemoteException;
+     void updateTimeZone() throws RemoteException;
+     void clearDnsCache() throws RemoteException;
+     void setHttpProxy(String proxy, String port, String exclList,
+@@ -225,4 +226,5 @@ public interface IApplicationThread extends IInterface {
+     int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
+     int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
+     int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60;
++    int SCHEDULE_ASSETS_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61;
+ }
+diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
+index 4916c1c..8cbca31 100644
+--- a/core/java/android/app/ResourcesManager.java
++++ b/core/java/android/app/ResourcesManager.java
+@@ -29,6 +29,7 @@ import android.content.res.ResourcesImpl;
+ import android.content.res.ResourcesKey;
+ import android.hardware.display.DisplayManagerGlobal;
+ import android.os.IBinder;
++import android.os.Process;
+ import android.os.Trace;
+ import android.util.ArrayMap;
+ import android.util.DisplayMetrics;
+@@ -52,6 +53,8 @@ public class ResourcesManager {
+     static final String TAG = "ResourcesManager";
+     private static final boolean DEBUG = false;
++    private static final String FRAMEWORK_RESOURCES_PATH = "/system/framework/framework-res.apk";
++
+     private static ResourcesManager sResourcesManager;
+     /**
+@@ -916,44 +919,108 @@ public class ResourcesManager {
+                 }
+             }
+-            // Bail early if there is no work to do.
+-            if (updatedResourceKeys.isEmpty()) {
+-                return;
++            redirectResourcesToNewImplLocked(updatedResourceKeys);
++        }
++    }
++
++    final void applyNewResourceDirsLocked(@NonNull final String baseCodePath,
++            @NonNull final String[] newResourceDirs) {
++        try {
++            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
++                    "ResourcesManager#applyNewResourceDirsLocked");
++
++            ApplicationPackageManager.configurationChanged();
++
++            if (Process.myUid() == Process.SYSTEM_UID) {
++                // Resources.getSystem Resources are created on request and aren't tracked by
++                // mResourceReferences.
++                //
++                // If overlays targeting "android" are to be used, we must create the system
++                // resources regardless of whether they already exist, since otherwise the
++                // information on what overlays to use would be lost. This is wasteful for most
++                // applications, so limit this operation to the system user only. (This means
++                // Resources.getSystem() will *not* use overlays for applications.)
++                if (FRAMEWORK_RESOURCES_PATH.equals(baseCodePath)) {
++                    final ResourcesKey key = new ResourcesKey(
++                            FRAMEWORK_RESOURCES_PATH,
++                            null,
++                            newResourceDirs,
++                            null,
++                            Display.DEFAULT_DISPLAY,
++                            null,
++                            null);
++                    final ResourcesImpl impl = createResourcesImpl(key);
++                    Resources.getSystem().setImpl(impl);
++                }
+             }
+-            // Update any references to ResourcesImpl that require reloading.
+-            final int resourcesCount = mResourceReferences.size();
+-            for (int i = 0; i < resourcesCount; i++) {
+-                final Resources r = mResourceReferences.get(i).get();
++
++            final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
++            final int implCount = mResourceImpls.size();
++            for (int i = 0; i < implCount; i++) {
++                final ResourcesImpl impl = mResourceImpls.valueAt(i).get();
++                final ResourcesKey key = mResourceImpls.keyAt(i);
++                if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
++
++                    updatedResourceKeys.put(impl, new ResourcesKey(
++                            key.mResDir,
++                            key.mSplitResDirs,
++                            newResourceDirs,
++                            key.mLibDirs,
++                            key.mDisplayId,
++                            key.mOverrideConfiguration,
++                            key.mCompatInfo));
++                }
++            }
++
++            invalidatePath("/");
++
++            redirectResourcesToNewImplLocked(updatedResourceKeys);
++        } finally {
++            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
++        }
++    }
++
++    private void redirectResourcesToNewImplLocked(
++            @NonNull final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys) {
++
++        // Bail early if there is no work to do.
++        if (updatedResourceKeys.isEmpty()) {
++            return;
++        }
++
++        // Update any references to ResourcesImpl that require reloading.
++        final int resourcesCount = mResourceReferences.size();
++        for (int i = 0; i < resourcesCount; i++) {
++            final Resources r = mResourceReferences.get(i).get();
++            if (r != null) {
++                final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
++                if (key != null) {
++                    final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
++                    if (impl == null) {
++                        throw new Resources.NotFoundException("failed to load");
++                    }
++                    r.setImpl(impl);
++                }
++            }
++        }
++
++        // Update any references to ResourcesImpl that require reloading for each Activity.
++        for (final ActivityResources activityResources : mActivityResourceReferences.values()) {
++            final int resCount = activityResources.activityResources.size();
++            for (int i = 0; i < resCount; i++) {
++                final Resources r = activityResources.activityResources.get(i).get();
+                 if (r != null) {
+                     final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
+                     if (key != null) {
+                         final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
+                         if (impl == null) {
+-                            throw new Resources.NotFoundException("failed to load " + libAsset);
++                            throw new Resources.NotFoundException("failed to load");
+                         }
+                         r.setImpl(impl);
+                     }
+                 }
+             }
+-
+-            // Update any references to ResourcesImpl that require reloading for each Activity.
+-            for (ActivityResources activityResources : mActivityResourceReferences.values()) {
+-                final int resCount = activityResources.activityResources.size();
+-                for (int i = 0; i < resCount; i++) {
+-                    final Resources r = activityResources.activityResources.get(i).get();
+-                    if (r != null) {
+-                        final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
+-                        if (key != null) {
+-                            final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
+-                            if (impl == null) {
+-                                throw new Resources.NotFoundException("failed to load " + libAsset);
+-                            }
+-                            r.setImpl(impl);
+-                        }
+-                    }
+-                }
+-            }
+         }
+     }
+ }
+diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
+index f2e3333..8d42d2c 100644
+--- a/core/java/android/content/pm/PackageParser.java
++++ b/core/java/android/content/pm/PackageParser.java
+@@ -668,10 +668,9 @@ public class PackageParser {
+     public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
+     public final static int PARSE_IS_PRIVILEGED = 1<<7;
+     public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
+-    public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
+-    public final static int PARSE_ENFORCE_CODE = 1<<10;
+-    public final static int PARSE_IS_EPHEMERAL = 1<<11;
+-    public final static int PARSE_FORCE_SDK = 1<<12;
++    public final static int PARSE_ENFORCE_CODE = 1<<9;
++    public final static int PARSE_IS_EPHEMERAL = 1<<10;
++    public final static int PARSE_FORCE_SDK = 1<<11;
+     private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
+@@ -1806,9 +1805,6 @@ 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) {
+@@ -1816,14 +1812,7 @@ 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)) {
+                 if (!parseKeySets(pkg, res, parser, outError)) {
+                     return null;
+@@ -4913,8 +4902,6 @@ public class PackageParser {
+         public String mRequiredAccountType;
+         public String mOverlayTarget;
+-        public int mOverlayPriority;
+-        public boolean mTrustedOverlay;
+         /**
+          * Data used to feed the KeySetManagerService
+@@ -5455,6 +5442,7 @@ public class PackageParser {
+             ai.enabled = false;
+         }
+         ai.enabledSetting = state.enabled;
++        ai.resourceDirs = state.resourceDirs;
+         if (state.protectedComponents != null) {
+             ai.protect = state.protectedComponents.size() > 0;
+         }
+diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
+index e64e4c4..4b276fb 100644
+--- a/core/java/android/content/pm/PackageUserState.java
++++ b/core/java/android/content/pm/PackageUserState.java
+@@ -31,6 +31,8 @@ import android.util.ArraySet;
+ import com.android.internal.util.ArrayUtils;
++import java.util.Arrays;
++
+ /**
+  * Per-user state information about a package.
+  * @hide
+@@ -53,6 +55,8 @@ public class PackageUserState {
+     public ArraySet<String> protectedComponents;
+     public ArraySet<String> visibleComponents;
++    public String[] resourceDirs;
++
+     public PackageUserState() {
+         installed = true;
+         hidden = false;
+@@ -76,6 +80,8 @@ public class PackageUserState {
+         appLinkGeneration = o.appLinkGeneration;
+         disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
+         enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
++        resourceDirs =
++            o.resourceDirs == null ? null : Arrays.copyOf(o.resourceDirs, o.resourceDirs.length);
+         protectedComponents = o.protectedComponents != null
+                 ? new ArraySet<String>(o.protectedComponents) : null;
+         visibleComponents = o.visibleComponents != null
+diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
+index 1a7294f..6c5a88f 100644
+--- a/core/jni/android_util_AssetManager.cpp
++++ b/core/jni/android_util_AssetManager.cpp
+@@ -129,85 +129,6 @@ 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(const char* overlay_dir)
+-{
+-    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[7];
+-                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
+-                // /vendor/overlay
+-
+-               if (stat(overlay_dir, &st) == 0) {
+-                   argv[argc++] = overlay_dir;
+-                }
+-
+-                // Finally, invoke idmap (if any overlay directory exists)
+-                if (argc > 5) {
+-                    execv(AssetManager::IDMAP_BIN, (char* const*)argv);
+-                    ALOGE("failed to execl 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
+@@ -2078,22 +1999,6 @@ static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jo
+ static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
+ {
+-    if (isSystem) {
+-        // Load frameworks-res.apk's overlay through regionalization environment
+-        if (Environment::isSupported()) {
+-            Environment* environment = new Environment();
+-            if (environment != NULL) {
+-                const char* overlay_dir = environment->getOverlayDir();
+-                if (overlay_dir != NULL && strcmp(overlay_dir, "") != 0) {
+-                    ALOGD("Regionalization - getOverlayDir:%s", overlay_dir);
+-                    verifySystemIdmaps(overlay_dir);
+-                }
+-                delete environment;
+-            }
+-        }
+-
+-        verifySystemIdmaps(AssetManager::OVERLAY_DIR);
+-    }
+     AssetManager* am = new AssetManager();
+     if (am == NULL) {
+         jniThrowException(env, "java/lang/OutOfMemoryError", "");
+diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
+index 914ac3d..651765b 100644
+--- a/include/androidfw/AssetManager.h
++++ b/include/androidfw/AssetManager.h
+@@ -238,12 +238,10 @@ public:
+ 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;
+     };
+@@ -288,9 +286,6 @@ 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);
+@@ -305,9 +300,6 @@ private:
+         
+         bool isUpToDate();
+-        void addOverlay(const asset_path& ap);
+-        bool getOverlay(size_t idx, asset_path* out) const;
+-        
+     protected:
+         ~SharedZip();
+@@ -322,8 +314,6 @@ private:
+         Asset* mResourceTableAsset;
+         ResTable* mResourceTable;
+-        Vector<asset_path> mOverlays;
+-
+         static Mutex gLock;
+         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
+     };
+@@ -356,9 +346,6 @@ private:
+         static String8 getPathName(const char* path);
+         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/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
+index edc625b..924b230 100644
+--- a/libs/androidfw/AssetManager.cpp
++++ b/libs/androidfw/AssetManager.cpp
+@@ -214,15 +214,6 @@ 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);
+     }
+@@ -606,11 +597,6 @@ 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;
+@@ -652,14 +638,6 @@ 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);
+             }
+@@ -772,58 +750,6 @@ 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);
+@@ -1962,20 +1888,6 @@ 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) {
+@@ -2101,22 +2013,6 @@ 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.
+  *
+diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
+index 90f507c..904c967 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;
+@@ -104,22 +105,25 @@ public class SystemServiceManager {
+                         + ": 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 e31b409..2822dc9 100644
+--- a/services/core/java/com/android/server/am/ActivityManagerService.java
++++ b/services/core/java/com/android/server/am/ActivityManagerService.java
+@@ -19297,6 +19297,57 @@ public final class ActivityManagerService extends ActivityManagerNative
+     }
+     /**
++     * @hide
++     */
++    @Override
++    public void updateAssets(final int userId, @NonNull final List<String> packageNames) {
++        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateAssets()");
++
++        synchronized(this) {
++            final long origId = Binder.clearCallingIdentity();
++            try {
++                updateAssetsLocked(userId, packageNames);
++            } finally {
++                Binder.restoreCallingIdentity(origId);
++            }
++        }
++    }
++
++    void updateAssetsLocked(final int userId, @NonNull final List<String> packagesToUpdate) {
++        final IPackageManager pm = AppGlobals.getPackageManager();
++        final Map<String, ApplicationInfo> cache = new ArrayMap<>();
++
++        final boolean updateFrameworkRes = packagesToUpdate.contains("android");
++        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
++            final ProcessRecord app = mLruProcesses.get(i);
++            if (app.userId != userId || app.thread == null) {
++                continue;
++            }
++
++            for (final String packageName : app.pkgList.keySet()) {
++                if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
++                    try {
++                        final ApplicationInfo ai;
++                        if (cache.containsKey(packageName)) {
++                            ai = cache.get(packageName);
++                        } else {
++                            ai = pm.getApplicationInfo(packageName, 0, userId);
++                            cache.put(packageName, ai);
++                        }
++
++                        if (ai != null) {
++                            app.thread.scheduleAssetsChanged(packageName, ai);
++                        }
++                    } catch (RemoteException e) {
++                        Slog.w(TAG, String.format("Failed to update %s assets for %s",
++                                    packageName, app));
++                    }
++                }
++            }
++        }
++    }
++
++    /**
+      * Decide based on the configuration whether we should shouw the ANR,
+      * crash, etc dialogs.  The idea is that if there is no affordence to
+      * press the on-screen buttons, or the user experience would be more
+diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
+index ec148dd..761ef52 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerService.java
++++ b/services/core/java/com/android/server/om/OverlayManagerService.java
+@@ -676,37 +676,36 @@ public final class OverlayManagerService extends SystemService {
+     }
+     private void updateAssets(final int userId, List<String> targetPackageNames) {
+-        // TODO: uncomment 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, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
+-        // synchronized (mLock) {
+-        //     final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
+-        //     for (final String packageName : targetPackageNames) {
+-        //         final List<String> paths = new ArrayList<>();
+-        //         paths.addAll(frameworkPaths);
+-        //         if (!"android".equals(packageName)) {
+-        //             paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
+-        //         }
+-        //         allPaths.put(packageName,
+-        //             paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
+-        //     }
+-        // }
+-
+-        // for (String packageName : targetPackageNames) {
+-        //     pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
+-        // }
+-
+-        // final IActivityManager am = ActivityManagerNative.getDefault();
+-        // try {
+-        //     am.updateAssets(userId, targetPackageNames);
+-        // } catch (RemoteException e) {
+-        //     // Intentionally left empty.
+-        // }
++        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
++        final boolean updateFrameworkRes = targetPackageNames.contains("android");
++        if (updateFrameworkRes) {
++            targetPackageNames = pm.getTargetPackageNames(userId);
++        }
++
++        final Map<String, String[]> allPaths = new ArrayMap<>(targetPackageNames.size());
++        synchronized (mLock) {
++            final List<String> frameworkPaths = mImpl.onGetEnabledOverlayPaths("android", userId);
++            for (final String packageName : targetPackageNames) {
++                final List<String> paths = new ArrayList<>();
++                paths.addAll(frameworkPaths);
++                if (!"android".equals(packageName)) {
++                    paths.addAll(mImpl.onGetEnabledOverlayPaths(packageName, userId));
++                }
++                allPaths.put(packageName,
++                    paths.isEmpty() ? null : paths.toArray(new String[paths.size()]));
++            }
++        }
++
++        for (String packageName : targetPackageNames) {
++            pm.setResourceDirs(userId, packageName, allPaths.get(packageName));
++        }
++
++        final IActivityManager am = ActivityManagerNative.getDefault();
++        try {
++            am.updateAssets(userId, targetPackageNames);
++        } 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 3892f8f..f700522 100644
+--- a/services/core/java/com/android/server/pm/PackageManagerService.java
++++ b/services/core/java/com/android/server/pm/PackageManagerService.java
+@@ -399,17 +399,16 @@ public class PackageManagerService extends IPackageManager.Stub {
+     static final int SCAN_UPDATE_TIME = 1<<6;
+     static final int SCAN_DEFER_DEX = 1<<7;
+     static final int SCAN_BOOTING = 1<<8;
+-    static final int SCAN_TRUSTED_OVERLAY = 1<<9;
+-    static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
+-    static final int SCAN_REPLACING = 1<<11;
+-    static final int SCAN_REQUIRE_KNOWN = 1<<12;
+-    static final int SCAN_MOVE = 1<<13;
+-    static final int SCAN_INITIAL = 1<<14;
+-    static final int SCAN_CHECK_ONLY = 1<<15;
+-    static final int SCAN_DONT_KILL_APP = 1<<17;
+-    static final int SCAN_IGNORE_FROZEN = 1<<18;
+-
+-    static final int REMOVE_CHATTY = 1<<16;
++    static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<9;
++    static final int SCAN_REPLACING = 1<<10;
++    static final int SCAN_REQUIRE_KNOWN = 1<<11;
++    static final int SCAN_MOVE = 1<<12;
++    static final int SCAN_INITIAL = 1<<13;
++    static final int SCAN_CHECK_ONLY = 1<<14;
++    static final int SCAN_DONT_KILL_APP = 1<<15;
++    static final int SCAN_IGNORE_FROZEN = 1<<16;
++
++    static final int REMOVE_CHATTY = 1<<17;
+     private static final int[] EMPTY_INT_ARRAY = new int[0];
+@@ -600,10 +599,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+     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>>();
+-
+     /**
+      * Tracks new system packages [received in an OTA] that we expect to
+      * find updated user-installed versions. Keys are package name, values
+@@ -2342,8 +2337,8 @@ public class PackageManagerService extends IPackageManager.Stub {
+             File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
+             scanDirTracedLI(vendorOverlayDir, mDefParseFlags
+                     | PackageParser.PARSE_IS_SYSTEM
+-                    | PackageParser.PARSE_IS_SYSTEM_DIR
+-                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
++                    | PackageParser.PARSE_IS_SYSTEM_DIR,
++                    scanFlags, 0);
+             // Find base frameworks (resource packages without code).
+             scanDirTracedLI(frameworkDir, mDefParseFlags
+@@ -2400,7 +2395,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+                     // Collect overlay in <Package>/system/vendor
+                     scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
+                             PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
+-                            scanFlags | SCAN_TRUSTED_OVERLAY, 0);
++                            scanFlags, 0);
+                 }
+             }
+@@ -6723,60 +6718,6 @@ 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");
+         try {
+@@ -6964,10 +6905,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+         pp.setOnlyPowerOffAlarmApps(mOnlyPowerOffAlarm);
+         pp.setDisplayMetrics(mMetrics);
+-        if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
+-            parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
+-        }
+-
+         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
+         final PackageParser.Package pkg;
+         try {
+@@ -8200,7 +8137,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+             pkg.applicationInfo.privateFlags &=
+                     ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+         }
+-        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
+         if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
+             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+@@ -8795,7 +8731,6 @@ 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
+@@ -9142,36 +9077,10 @@ public class PackageManagerService extends IPackageManager.Stub {
+             }
+             pkgSetting.setTimeStamp(scanFileTime);
+-
+-            // 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");
+-        }
+         return pkg;
+     }
+@@ -16618,7 +16527,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+                     false /*hidden*/, false /*suspended*/, null, null, null,
+                     false /*blockUninstall*/,
+                     ps.readUserState(nextUserId).domainVerificationStatus, 0,
+-                    null, null);
++                    null, null, null);
+         }
+     }
+@@ -21476,14 +21385,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
+         @Override
+         public void setResourceDirs(int userId, String packageName, String[] resourceDirs) {
+-            // TODO: uncomment when we integrate OMS properly
+-            // synchronized (mPackages) {
+-            //     PackageSetting ps = mSettings.mPackages.get(packageName);
+-            //     if (ps == null) {
+-            //         return;
+-            //     }
+-            //     ps.setResourceDirs(resourceDirs, userId);
+-            // }
++            synchronized (mPackages) {
++                final PackageSetting ps = mSettings.mPackages.get(packageName);
++                if (ps == null) {
++                    return;
++                }
++                ps.setResourceDirs(resourceDirs, userId);
++            }
+         }
+     }
+diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
+index 75427a8..18c79cd 100644
+--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
++++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
+@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ import static android.content.pm.PackageManager.COMPONENT_VISIBLE_STATUS;
++import android.annotation.NonNull;
+ import android.content.pm.IntentFilterVerificationInfo;
+ import android.content.pm.PackageManager;
+ import android.content.pm.PackageUserState;
+@@ -379,7 +380,7 @@ abstract class PackageSettingBase extends SettingBase {
+             boolean notLaunched, boolean hidden, boolean suspended,
+             String lastDisableAppCaller, ArraySet<String> enabledComponents,
+             ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
+-            int linkGeneration,
++            int linkGeneration, String[] resourceDirs,
+             ArraySet<String> protectedComponents, ArraySet<String> visibleComponents) {
+         PackageUserState state = modifyUserState(userId);
+         state.ceDataInode = ceDataInode;
+@@ -395,6 +396,7 @@ abstract class PackageSettingBase extends SettingBase {
+         state.blockUninstall = blockUninstall;
+         state.domainVerificationStatus = domainVerifState;
+         state.appLinkGeneration = linkGeneration;
++        state.resourceDirs = resourceDirs;
+         state.protectedComponents = protectedComponents;
+         state.visibleComponents = visibleComponents;
+     }
+@@ -455,6 +457,10 @@ abstract class PackageSettingBase extends SettingBase {
+         modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
+     }
++    void setResourceDirs(@NonNull final String[] resourceDirs, final int userId) {
++        modifyUserState(userId).resourceDirs = resourceDirs;
++    }
++
+     boolean enableComponentLPw(String componentClassName, int userId) {
+         PackageUserState state = modifyUserStateComponents(userId, false, true);
+         boolean changed = state.disabledComponents != null
+diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
+index 285b5bb..2b36e0e 100755
+--- a/services/core/java/com/android/server/pm/Settings.java
++++ b/services/core/java/com/android/server/pm/Settings.java
+@@ -813,6 +813,7 @@ final class Settings {
+                                     false, // blockUninstall
+                                     INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+                                     null,
++                                    null,
+                                     null
+                                     );
+                             writePackageRestrictionsLPr(user.id);
+@@ -1617,6 +1618,7 @@ final class Settings {
+                                 false, // blockUninstall
+                                 INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+                                 null,
++                                null,
+                                 null
+                                 );
+                     }
+@@ -1726,7 +1728,7 @@ final class Settings {
+                     ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
+                             hidden, suspended, enabledCaller, enabledComponents, disabledComponents,
+-                            blockUninstall, verifState, linkGeneration,
++                            blockUninstall, verifState, linkGeneration, null,
+                             protectedComponents, visibleComponents);
+                 } else if (tagName.equals("preferred-activities")) {
+                     readPreferredActivitiesLPw(parser, userId);
+diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
+index 3e16338..010aaa1 100644
+--- a/services/java/com/android/server/SystemServer.java
++++ b/services/java/com/android/server/SystemServer.java
+@@ -84,6 +84,7 @@ 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.RegionalizationService;
+ import com.android.server.os.SchedulingPolicyService;
+ import com.android.server.pm.BackgroundDexOptService;
+@@ -530,6 +531,9 @@ public final class SystemServer {
+         // Set up the Application instance for the system process and get started.
+         mActivityManagerService.setSystemProcess();
++        // Manages Overlay packages
++        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
++
+         // The sensor service needs access to package manager service, app ops
+         // service, and permissions service, therefore we start it after them.
+         startSensorService();
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch b/patches/frameworks/base/0004-OMS7-N-Set-EXTRA_REPLACING-correctly-in-ACTION_PACKA.patch
new file mode 100644 (file)
index 0000000..5ce4094
--- /dev/null
@@ -0,0 +1,51 @@
+From 06912868733feadee85507d9f40ede2468a9a496 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Mon, 25 Apr 2016 16:29:22 +0200
+Subject: [PATCH 04/38] OMS7-N: Set EXTRA_REPLACING correctly in
+ ACTION_PACKAGE_ADDED [4/11]
+
+When broadcasting ACTION_PACKAGE_ADDED the recipients of the Intent are
+split into two groups: the first group hasn't seen the new package
+before and the Intent should have EXTRA_REPLACING set to false; and vice
+versa for the second group.
+
+The package manager schedules these Intent broadcasts on a background
+thread by posting Runnable objects to a handler. Each Runnable holds
+references to objects used to construct the Intents, one of which is a
+Bundle used to create the Intent extras.
+
+If the same Bundle object is used for both recipient groups, any
+modification to the object made for one group will unintentionally
+propagate to the other. To prevent this a separate Bundle is now created
+for each group.
+
+Prior to this patch, the following scenario would fail:
+
+  1. Install a package P for user owner
+  2. Create and switch to a secondary user
+  3. Install a new version of package P (for all users)
+
+In step 3, the secondary user was expected to receive
+ACTION_PACKAGE_ADDED with EXTRA_REPLACING set to false, but instead it
+was set to true. The bug was initially introduced in commit bd0e9e49.
+
+Change-Id: Icf869013d5d652de4bf0f6df4529b7a68d35a25c
+---
+ services/core/java/com/android/server/pm/PackageManagerService.java | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
+index f700522..7277f6a 100644
+--- a/services/core/java/com/android/server/pm/PackageManagerService.java
++++ b/services/core/java/com/android/server/pm/PackageManagerService.java
+@@ -1714,6 +1714,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+                 // Send added for users that don't see the package for the first time
+                 if (update) {
++                    extras = new Bundle(extras);
+                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
+                 }
+                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch b/patches/frameworks/base/0005-OMS7-N-idmap-suppress-print-for-padded-resources-5-1.patch
new file mode 100644 (file)
index 0000000..31ebb89
--- /dev/null
@@ -0,0 +1,29 @@
+From ee6f42041d3c77be1151d82898ee5626633cf9fa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Mon, 29 Feb 2016 14:12:35 +0100
+Subject: [PATCH 05/38] OMS7-N: idmap: suppress print for padded resources
+ [5/11]
+
+Change-Id: I565ccf515068b96927e4317cc9c06543415bb324
+---
+ cmds/idmap/inspect.cpp | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
+index 924090f..cb52a39 100644
+--- a/cmds/idmap/inspect.cpp
++++ b/cmds/idmap/inspect.cpp
+@@ -289,7 +289,9 @@ namespace {
+                 if (err != NO_ERROR) {
+                     return err;
+                 }
+-                print("", "entry", data32, "%s/%s", type.string(), name.string());
++                if (data32 != ResTable_type::NO_ENTRY) {
++                    print("", "entry", data32, "%s/%s", type.string(), name.string());
++                }
+             }
+         }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch b/patches/frameworks/base/0006-OMS7-N-Fix-memory-leak-during-idmap-creation-6-11.patch
new file mode 100644 (file)
index 0000000..9eb37d8
--- /dev/null
@@ -0,0 +1,67 @@
+From a2ce720b5bfca010dc28ab9cd79e9a8d94f981b3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Thu, 2 Jun 2016 09:34:36 +0200
+Subject: [PATCH 06/38] OMS7-N: Fix memory leak during idmap creation [6/11]
+
+Plug a memory leak in AssetManager::createIdmap.
+
+Change-Id: Ieed805c596df931e2167ebb47c1b2907d6bf67f4
+---
+ libs/androidfw/AssetManager.cpp | 38 +++++++++++++++++++++++++-------------
+ 1 file changed, 25 insertions(+), 13 deletions(-)
+
+diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
+index 924b230..c501e8b 100644
+--- a/libs/androidfw/AssetManager.cpp
++++ b/libs/androidfw/AssetManager.cpp
+@@ -291,22 +291,34 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk
+ {
+     AutoMutex _l(mLock);
+     const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
+-    ResTable tables[2];
+-
+-    for (int i = 0; i < 2; ++i) {
+-        asset_path ap;
+-        ap.type = kFileTypeRegular;
+-        ap.path = paths[i];
+-        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+-        if (ass == NULL) {
+-            ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
+-            return false;
++    Asset* assets[2] = {NULL, NULL};
++    bool ret = false;
++    {
++        ResTable tables[2];
++
++        for (int i = 0; i < 2; ++i) {
++            asset_path ap;
++            ap.type = kFileTypeRegular;
++            ap.path = paths[i];
++            assets[i] = openNonAssetInPathLocked("resources.arsc",
++                    Asset::ACCESS_BUFFER, ap);
++            if (assets[i] == NULL) {
++                ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
++                goto exit;
++            }
++            if (tables[i].add(assets[i]) != NO_ERROR) {
++                ALOGW("failed to add %s to resource table", paths[i].string());
++                goto exit;
++            }
+         }
+-        tables[i].add(ass);
++        ret = tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
++                targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
+     }
+-    return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
+-            targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
++exit:
++    delete assets[0];
++    delete assets[1];
++    return ret;
+ }
+ bool AssetManager::addDefaultAssets()
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch b/patches/frameworks/base/0007-OMS7-N-installd-add-command-rmidmap-7-11.patch
new file mode 100644 (file)
index 0000000..209f9e3
--- /dev/null
@@ -0,0 +1,38 @@
+From b14c245ca8e1b2fa9665ef8cde29eeafaeba282f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Thu, 2 Jun 2016 09:35:09 +0200
+Subject: [PATCH 07/38] OMS7-N: installd: add command 'rmidmap' [7/11]
+
+Add an installd command to remove an idmap file. This is the inverse of
+the 'idmap' command and is intended for clean-up once an idmap file is
+no longer needed because an APK was removed, etc.
+
+This commit depends on a corresponding commit in frameworks/native (with
+the same Change-Id).
+
+Change-Id: I58f55f643da99c0bd69136ee43c1c8c70c352797
+---
+ services/core/java/com/android/server/pm/Installer.java | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
+index 2e18b1c..7f618b8 100644
+--- a/services/core/java/com/android/server/pm/Installer.java
++++ b/services/core/java/com/android/server/pm/Installer.java
+@@ -170,6 +170,13 @@ public final class Installer extends SystemService {
+         mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
+     }
++    public void removeIdmap(String overlayApkPath) throws InstallerException {
++        StringBuilder builder = new StringBuilder("rmidmap");
++        builder.append(' ');
++        builder.append(overlayApkPath);
++        mInstaller.execute(builder.toString());
++    }
++
+     public void rmdex(String codePath, String instructionSet) throws InstallerException {
+         assertValidInstructionSet(instructionSet);
+         mInstaller.execute("rmdex", codePath, instructionSet);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch b/patches/frameworks/base/0008-OMS7-N-Disable-Zygote-preloaded-drawables-8-11.patch
new file mode 100644 (file)
index 0000000..fd22568
--- /dev/null
@@ -0,0 +1,45 @@
+From 5e8fc3854ee67ed15983c460b390d0cff1dde775 Mon Sep 17 00:00:00 2001
+From: Josh Guilfoyle <Josh.Guilfoyle@T-Mobile.com>
+Date: Wed, 26 Jan 2011 23:28:43 -0800
+Subject: [PATCH 08/38] OMS7-N: Disable Zygote preloaded drawables [8/11]
+
+With a theme applied, most of these preloaded drawables go unused.  Any
+assets the theme has redirected will need to be loaded with each app
+process regardless.  Worse, preloads make it impossible to do asset
+redirection for constituent parts of a preloaded drawable (for instance,
+individual states of a StateListDrawable cannot be redirected).
+
+Some day it might be nice to revisit this and see if there's a way to
+reintroduce the drawable cache in a way that can be altered at runtime
+without significant complexity or runtime penalty.
+
+Change-Id: I253b1a22482ac664c196533a4c2fcd88ae84b996
+---
+ core/java/com/android/internal/os/ZygoteInit.java | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
+index 20f84b5..455849e 100644
+--- a/core/java/com/android/internal/os/ZygoteInit.java
++++ b/core/java/com/android/internal/os/ZygoteInit.java
+@@ -108,7 +108,7 @@ public class ZygoteInit {
+     private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
+     /** Controls whether we should preload resources during zygote init. */
+-    public static final boolean PRELOAD_RESOURCES = true;
++    public static final boolean PRELOAD_RESOURCES = false;
+     /**
+      * Registers a server socket for zygote command connections
+@@ -437,6 +437,8 @@ public class ZygoteInit {
+                     Log.i(TAG, "...preloaded " + N + " resource in "
+                             + (SystemClock.uptimeMillis() - startTime) + "ms.");
+                 }
++            } else {
++                Log.i(TAG, "Preload resources disabled, skipped.");
+             }
+             mResources.finishPreloading();
+         } catch (RuntimeException e) {
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch b/patches/frameworks/base/0009-OMS7-N-Persistence-on-boot-through-OverlayManagerSer.patch
new file mode 100644 (file)
index 0000000..16c58d4
--- /dev/null
@@ -0,0 +1,78 @@
+From fc7d694af82449a4d4a3456ffd486a5afa30a2ef Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Sun, 19 Jun 2016 10:37:13 -0400
+Subject: [PATCH 09/38] OMS7-N: Persistence on boot through
+ OverlayManagerServiceImpl [9/11]
+
+Overlays should not be enforced by the traditional OverlayManagerService
+by Sony, but instead, it shouldn't be enforced at all to allow third
+party overlays from the community to boot up with the device.
+
+Change-Id: Ic6eeb38b5e7bcec4211405d4504ba37a75738227
+---
+ .../server/om/OverlayManagerServiceImpl.java       | 31 +++++++++++++++-------
+ 1 file changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+index 2a0d88b..4c61968 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
++++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+@@ -402,34 +402,45 @@ final class OverlayManagerServiceImpl {
+     private int calculateNewState(@Nullable final PackageInfo targetPackage,
+             @NonNull final PackageInfo overlayPackage, final int userId)
+         throws OverlayManagerSettings.BadKeyException {
++
++        // STATE 0 CHECK: Check if the overlay package is disabled by PackageManager
+         if (!overlayPackage.applicationInfo.enabled) {
+             return STATE_NOT_APPROVED_COMPONENT_DISABLED;
+         }
++        // OVERLAY STATE CHECK: Check the current overlay's activation
++        boolean stateCheck = mSettings.getEnabled(overlayPackage.packageName, userId);
++
++        // STATE 1 CHECK: Check if the overlay's target package is missing from the device
+         if (targetPackage == null) {
+             return STATE_NOT_APPROVED_MISSING_TARGET;
+         }
++        // STATE 2 CHECK: Check if the overlay has an existing idmap file created. Perhaps
++        // there were no matching resources between the two packages? (Overlay & Target)
+         if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
+             return STATE_NOT_APPROVED_NO_IDMAP;
+         }
+-        final boolean enableIfApproved = mSettings.getEnabled(overlayPackage.packageName, userId);
+-
+-        if (mPackageManager.signaturesMatching(targetPackage.packageName,
+-                    overlayPackage.packageName, userId)) {
+-            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
+-        }
+-
++        // STATE 6 CHECK: System Overlays, also known as RRO overlay files, work the same
++        // as OMS, but with enable/disable limitations. A system overlay resides in the
++        // directory "/vendor/overlay" depending on your device.
++        //
++        // Team Substratum: Disable this as this is a security vulnerability and a
++        // memory-limited partition.
+         if ((overlayPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+-            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
++            return STATE_NOT_APPROVED_COMPONENT_DISABLED;
+         }
++        // STATE 3 CHECK: If the overlay only modifies resources explicitly granted by the
++        // target, we approve it.
++        //
++        // Team Substratum: Always approve dangerous packages but disabled state
+         if (!mIdmapManager.isDangerous(overlayPackage, userId)) {
+-            return enableIfApproved ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
++            return STATE_APPROVED_DISABLED;
+         }
+-        return STATE_NOT_APPROVED_DANGEROUS_OVERLAY;
++        return stateCheck ? STATE_APPROVED_ENABLED : STATE_APPROVED_DISABLED;
+     }
+     private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch b/patches/frameworks/base/0010-OMS7-N-Do-not-enforce-code-policy-limiting-overlay-i.patch
new file mode 100644 (file)
index 0000000..abf34be
--- /dev/null
@@ -0,0 +1,29 @@
+From c41b5f7552e5ef1f221d1f755b37501037463c66 Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Thu, 27 Oct 2016 07:08:00 +0200
+Subject: [PATCH 10/38] OMS7-N: Do not enforce code policy limiting overlay
+ installation [10/11]
+
+Change-Id: Iea317f3771f25dbfcbf4938e88cace12fd97d7eb
+---
+ services/core/java/com/android/server/pm/PackageManagerService.java | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
+index 7277f6a..46679e5 100644
+--- a/services/core/java/com/android/server/pm/PackageManagerService.java
++++ b/services/core/java/com/android/server/pm/PackageManagerService.java
+@@ -8143,10 +8143,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+         }
+-        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
+-            enforceCodePolicy(pkg);
+-        }
+-
+         if (mCustomResolverComponentName != null &&
+                 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
+             setUpCustomResolverActivity(pkg);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch b/patches/frameworks/base/0011-OMS7-N-Implement-multi-target-enable-disable-and-dis.patch
new file mode 100644 (file)
index 0000000..c155b92
--- /dev/null
@@ -0,0 +1,470 @@
+From 61a04ac0c542521026b925d35faf4244e6ea2810 Mon Sep 17 00:00:00 2001
+From: Jacob McSwain <jacob.a.mcswain@gmail.com>
+Date: Sun, 26 Jun 2016 15:21:52 -0500
+Subject: [PATCH 11/38] OMS7-N: Implement multi-target enable/disable and
+ disable-all [11/11]
+
+Just use the enable option like normal, but you can add more arguments
+for more packages. Also add a feature that allows the client to disable
+all of the current user's overlays.
+
+Multiple targets example:
+    om enable android.AkZent com.android.systemui.AkZent
+
+Works the same as:
+    om enable android.AkZent && om enable com.android.systemui.AkZent
+
+Original implementation for M by @USA-RedDragon
+Current and further development by @nicholaschum
+
+Change-Id: I04a595084a87b8260b5c534c4f5f111adbe154d7
+---
+ core/java/android/content/om/IOverlayManager.aidl  |  10 +-
+ .../android/server/om/OverlayManagerService.java   |  48 ++++++----
+ .../server/om/OverlayManagerServiceImpl.java       |  12 ++-
+ .../android/server/om/OverlayManagerSettings.java  |  31 +++---
+ .../server/om/OverlayManagerShellCommand.java      | 104 +++++++++++++++++++--
+ 5 files changed, 161 insertions(+), 44 deletions(-)
+
+diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
+index 4f5d960..8e349dc 100644
+--- a/core/java/android/content/om/IOverlayManager.aidl
++++ b/core/java/android/content/om/IOverlayManager.aidl
+@@ -83,10 +83,12 @@ interface IOverlayManager {
+      * @param packageName The name of the overlay package.
+      * @param enable true to enable the overlay, false to disable it.
+      * @param userId The user for which to change the overlay.
++     * @param shouldWait true to wait to reload resources until refresh is called
+      * @return true if the system successfully registered the request, false
+      *         otherwise.
+      */
+-    boolean setEnabled(in String packageName, in boolean enable, in int userId);
++    boolean setEnabled(in String packageName, in boolean enable, in int userId,
++                       in boolean shouldWait);
+     /**
+      * Change the priority of the given overlay to be just higher than the
+@@ -126,4 +128,10 @@ interface IOverlayManager {
+      * @param userId The user for which to change the overlay.
+      */
+     boolean setLowestPriority(in String packageName, in int userId);
++
++    /**
++     * Refresh assets
++     * @param uid the user to refresh assets for
++     */
++    void refresh(in int uid);
+ }
+diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
+index 761ef52..deb9046 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerService.java
++++ b/services/core/java/com/android/server/om/OverlayManagerService.java
+@@ -255,7 +255,7 @@ public final class OverlayManagerService extends SystemService {
+         synchronized (mLock) {
+             targets = mImpl.onSwitchUser(newUserId);
+         }
+-        updateAssets(newUserId, targets);
++        updateSelectedAssets(newUserId, targets);
+     }
+     public List<String> getEnabledOverlayPaths(@NonNull final String packageName,
+@@ -451,7 +451,7 @@ public final class OverlayManagerService extends SystemService {
+         @Override
+         public boolean setEnabled(@Nullable final String packageName, final boolean enable,
+-                int userId) throws RemoteException {
++                int userId, final boolean shouldWait) throws RemoteException {
+             enforceChangeConfigurationPermission("setEnabled");
+             userId = handleIncomingUser(userId, "setEnabled");
+             if (packageName == null) {
+@@ -461,7 +461,7 @@ public final class OverlayManagerService extends SystemService {
+             final long ident = Binder.clearCallingIdentity();
+             try {
+                 synchronized (mLock) {
+-                    return mImpl.onSetEnabled(packageName, enable, userId);
++                    return mImpl.onSetEnabled(packageName, enable, userId, shouldWait);
+                 }
+             } finally {
+                 Binder.restoreCallingIdentity(ident);
+@@ -590,6 +590,15 @@ public final class OverlayManagerService extends SystemService {
+                         message);
+             }
+         }
++
++        public void refresh(int uid) {
++            Collection<String> targets;
++            synchronized (mLock) {
++                targets = mImpl.onSwitchUser(uid);
++            }
++            List targeted = new ArrayList(targets);
++            updateSelectedAssets(uid, targeted);
++        }
+     };
+     private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
+@@ -603,45 +612,48 @@ public final class OverlayManagerService extends SystemService {
+         }
+         @Override
+-        public void onOverlayAdded(@NonNull final OverlayInfo oi) {
+-            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
++        public void onOverlayAdded(@NonNull final OverlayInfo oi, final boolean shouldWait) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled(), shouldWait);
+         }
+         @Override
+-        public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
+-            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
++        public void onOverlayRemoved(@NonNull final OverlayInfo oi, final boolean shouldWait) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled(), shouldWait);
+         }
+         @Override
+-        public void onOverlayChanged(@NonNull final OverlayInfo oi,
+-                @NonNull final OverlayInfo oldOi) {
+-            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
++        public void onOverlayChanged(@NonNull final OverlayInfo oi, @NonNull OverlayInfo oldOi,
++                final boolean shouldWait) {
++            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi,
++                    oi.isEnabled() != oldOi.isEnabled(), shouldWait);
+         }
+         @Override
+         public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
+-            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
++            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled(), false);
+         }
+         private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
+-                final boolean doUpdate) {
+-            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
++                final boolean doUpdate, final boolean shouldWait) {
++            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate, shouldWait));
+         }
+         private final class BroadcastRunnable extends Thread {
+             private final String mAction;
+             private final OverlayInfo mOverlayInfo;
+             private final boolean mDoUpdate;
++            private final boolean shouldWait;
+-            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
+-                    final boolean doUpdate) {
++            public BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi, 
++                    final boolean doUpdate, final boolean shouldWait) {
+                 mAction = action;
+                 mOverlayInfo = oi;
+                 mDoUpdate = doUpdate;
++                this.shouldWait = shouldWait;
+             }
+             public void run() {
+-                if (mDoUpdate) {
++                if (mDoUpdate && !shouldWait) {
+                     updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
+                 }
+                 sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
+@@ -672,10 +684,10 @@ public final class OverlayManagerService extends SystemService {
+     private void updateAssets(final int userId, final String targetPackageName) {
+         final List<String> list = new ArrayList<>();
+         list.add(targetPackageName);
+-        updateAssets(userId, list);
++        updateSelectedAssets(userId, list);
+     }
+-    private void updateAssets(final int userId, List<String> targetPackageNames) {
++    private void updateSelectedAssets(final int userId, List<String> targetPackageNames) {
+         final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+         final boolean updateFrameworkRes = targetPackageNames.contains("android");
+         if (updateFrameworkRes) {
+diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+index 4c61968..c515640 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
++++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+@@ -324,7 +324,7 @@ final class OverlayManagerServiceImpl {
+     }
+     boolean onSetEnabled(@NonNull final String packageName, final boolean enable,
+-            final int userId) {
++            final int userId, final boolean shouldWait) {
+         if (DEBUG) {
+             Slog.d(TAG, String.format("onSetEnabled packageName=%s enable=%s userId=%d",
+                         packageName, enable, userId));
+@@ -340,7 +340,7 @@ final class OverlayManagerServiceImpl {
+             final PackageInfo targetPackage =
+                 mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+             mSettings.setEnabled(packageName, userId, enable);
+-            updateState(targetPackage, overlayPackage, userId);
++            updateState(targetPackage, overlayPackage, userId, shouldWait);
+             return true;
+         } catch (OverlayManagerSettings.BadKeyException e) {
+             return false;
+@@ -379,6 +379,12 @@ final class OverlayManagerServiceImpl {
+     private void updateState(@Nullable final PackageInfo targetPackage,
+             @NonNull final PackageInfo overlayPackage, final int userId)
+         throws OverlayManagerSettings.BadKeyException {
++        updateState(targetPackage, overlayPackage, userId, false);
++    }
++
++    private void updateState(@Nullable final PackageInfo targetPackage,
++            @NonNull final PackageInfo overlayPackage, final int userId,
++            final boolean shouldWait) throws OverlayManagerSettings.BadKeyException {
+         if (targetPackage != null) {
+             mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
+         }
+@@ -395,7 +401,7 @@ final class OverlayManagerServiceImpl {
+                             OverlayInfo.stateToString(currentState),
+                             OverlayInfo.stateToString(newState)));
+             }
+-            mSettings.setState(overlayPackage.packageName, userId, newState);
++            mSettings.setState(overlayPackage.packageName, userId, newState, shouldWait);
+         }
+     }
+diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
+index af0bb64..935ea02 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
++++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
+@@ -76,7 +76,7 @@ final class OverlayManagerSettings {
+         final OverlayInfo oi = item.getOverlayInfo();
+         mItems.remove(item);
+         if (oi != null) {
+-            notifyOverlayRemoved(oi);
++            notifyOverlayRemoved(oi, false);
+         }
+     }
+@@ -135,7 +135,7 @@ final class OverlayManagerSettings {
+             final OverlayInfo oi = item.getOverlayInfo();
+             item.setUpgrading(true);
+             item.setState(STATE_NOT_APPROVED_UNKNOWN);
+-            notifyOverlayRemoved(oi);
++            notifyOverlayRemoved(oi, false);
+         } else {
+             item.setUpgrading(false);
+         }
+@@ -172,8 +172,8 @@ final class OverlayManagerSettings {
+         return item.getState();
+     }
+-    void setState(@NonNull final String packageName, final int userId, final int state)
+-            throws BadKeyException {
++    void setState(@NonNull final String packageName, final int userId, final int state,
++            final boolean shouldWait) throws BadKeyException {
+         final SettingsItem item = select(packageName, userId);
+         if (item == null) {
+             throw new BadKeyException(packageName, userId);
+@@ -182,10 +182,10 @@ final class OverlayManagerSettings {
+         item.setState(state);
+         final OverlayInfo current = item.getOverlayInfo();
+         if (previous.state == STATE_NOT_APPROVED_UNKNOWN) {
+-            notifyOverlayAdded(current);
++            notifyOverlayAdded(current, shouldWait);
+             notifySettingsChanged();
+         } else if (current.state != previous.state) {
+-            notifyOverlayChanged(current, previous);
++            notifyOverlayChanged(current, previous, shouldWait);
+             notifySettingsChanged();
+         }
+     }
+@@ -602,32 +602,32 @@ final class OverlayManagerSettings {
+         }
+     }
+-    private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
++    private void notifyOverlayAdded(@NonNull final OverlayInfo oi, final boolean shouldWait) {
+         if (DEBUG) {
+             assertNotNull(oi);
+         }
+         for (final ChangeListener listener : mListeners) {
+-            listener.onOverlayAdded(oi);
++            listener.onOverlayAdded(oi, shouldWait);
+         }
+     }
+-    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
++    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi, final boolean shouldWait) {
+         if (DEBUG) {
+             assertNotNull(oi);
+         }
+         for (final ChangeListener listener : mListeners) {
+-            listener.onOverlayRemoved(oi);
++            listener.onOverlayRemoved(oi, shouldWait);
+         }
+     }
+     private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
+-            @NonNull final OverlayInfo oldOi) {
++            @NonNull final OverlayInfo oldOi, final boolean shouldWait) {
+         if (DEBUG) {
+             assertNotNull(oi);
+             assertNotNull(oldOi);
+         }
+         for (final ChangeListener listener : mListeners) {
+-            listener.onOverlayChanged(oi, oldOi);
++            listener.onOverlayChanged(oi, oldOi, shouldWait);
+         }
+     }
+@@ -642,9 +642,10 @@ final class OverlayManagerSettings {
+     interface ChangeListener {
+         void onSettingsChanged();
+-        void onOverlayAdded(@NonNull OverlayInfo oi);
+-        void onOverlayRemoved(@NonNull OverlayInfo oi);
+-        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
++        void onOverlayAdded(@NonNull OverlayInfo oi, boolean shouldWait);
++        void onOverlayRemoved(@NonNull OverlayInfo oi, boolean shouldWait);
++        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi,
++            boolean shouldWait);
+         void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
+     }
+diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+index d6f5373..44004c1 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
++++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+@@ -25,8 +25,10 @@ import android.os.ShellCommand;
+ import android.os.UserHandle;
+ import java.io.PrintWriter;
++import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Map;
++import java.util.Map.Entry;
+ /**
+  * Implementation of 'cmd overlay' commands.
+@@ -45,7 +47,9 @@ final class OverlayManagerShellCommand extends ShellCommand {
+     @Override
+     public int onCommand(@Nullable final String cmd) {
+         if (cmd == null) {
+-            return handleDefaultCommands(cmd);
++            final PrintWriter out = getOutPrintWriter();
++            out.println("The overlay manager has already been initialized.");
++            return -1;
+         }
+         final PrintWriter err = getErrPrintWriter();
+         try {
+@@ -56,6 +60,8 @@ final class OverlayManagerShellCommand extends ShellCommand {
+                     return runEnableDisable(true);
+                 case "disable":
+                     return runEnableDisable(false);
++                case "disable-all":
++                      return runDisableAll();
+                 case "set-priority":
+                     return runSetPriority();
+                 default:
+@@ -82,10 +88,12 @@ final class OverlayManagerShellCommand extends ShellCommand {
+         out.println("    Overlay packages are printed in priority order. With optional");
+         out.println("    parameters PACKAGEs, limit output to the specified packages");
+         out.println("    but include more information about each package.");
+-        out.println("  enable [--user USER_ID] PACKAGE");
+-        out.println("    Enable overlay package PACKAGE.");
+-        out.println("  disable [--user USER_ID] PACKAGE");
+-        out.println("    Disable overlay package PACKAGE.");
++        out.println("  enable [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
++        out.println("    Enable overlay package PACKAGE or subsequent counts of PACKAGE.");
++        out.println("  disable [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
++        out.println("    Disable overlay package PACKAGE or subsequent counts of PACKAGE.");
++        out.println("  disable-all [--user USER_ID]");
++        out.println("    Disable all overlay packages.");
+         out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
+         out.println("    Change the priority of the overlay PACKAGE to be just higher than");
+         out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
+@@ -145,8 +153,90 @@ final class OverlayManagerShellCommand extends ShellCommand {
+             }
+         }
+-        final String packageName = getNextArgRequired();
+-        return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
++        int argc = 0;
++        String packageName = getNextArgRequired();
++        ArrayList<String> packages = new ArrayList<>();
++        if (packageName == null) {
++            System.err.println("Error: no packages specified");
++            return 1;
++        }
++        while (packageName != null) {
++            argc++;
++            packages.add(packageName);
++            packageName = getNextArg();
++        }
++        if (argc > 1) {
++            for (String pkg : packages) {
++                boolean ret = mInterface.setEnabled(pkg, enable, userId, false);
++                if (!ret) {
++                    System.err.println("Error: Failed to " + ((enable) ? "enable ": "disable ") + pkg);
++                }
++            }
++            return 0;
++        } else if (argc == 1) {
++            return mInterface.setEnabled(packages.get(0), enable, userId, false) ? 0 : 1;
++        } else {
++            System.err.println("Error: A fatal exception has occurred.");
++            return 1;
++        }
++    }
++
++    private int runDisableAll() {
++        int userId = UserHandle.USER_OWNER;
++        String opt;
++        while ((opt = getNextOption()) != null) {
++            switch (opt) {
++                case "--user":
++                    userId = UserHandle.parseUserArg(getNextArgRequired());
++                      break;
++                default:
++                    System.err.println("Error: Unknown option: " + opt);
++                    return 1;
++            }
++        }
++
++        try {
++            Map<String, List<OverlayInfo>> targetsAndOverlays = mInterface.getAllOverlays(userId);
++            int iterator = 0;
++            int overlaySize = targetsAndOverlays.entrySet().size();
++            for (Entry<String, List<OverlayInfo>> targetEntry : targetsAndOverlays.entrySet()) {
++                int iterator_nested = 0;
++                int targetSize_nested = targetEntry.getValue().size();
++                iterator++;
++                for (OverlayInfo oi : targetEntry.getValue()) {
++                    if (iterator_nested < targetSize_nested) {
++                        if (oi.isEnabled()) {
++                            boolean worked = mInterface.setEnabled(oi.packageName, false, userId, true);
++                            if (!worked) {
++                                System.err.println("Failed to disable " + oi.packageName);
++                            }
++                        }
++                    } else {
++                        if (iterator == overlaySize) {
++                            if (oi.isEnabled()) {
++                                boolean worked = mInterface.setEnabled(oi.packageName, false, userId, false);
++                                if (!worked) {
++                                    System.err.println("Failed to disable " + oi.packageName);
++                                }
++                            }
++                        } else {
++                            if (oi.isEnabled()) {
++                                boolean worked = mInterface.setEnabled(oi.packageName, false, userId, true);
++                                if (!worked) {
++                                    System.err.println("Failed to disable " + oi.packageName);
++                                }
++                            }
++                        }
++                    }
++                    iterator_nested++;
++                }
++            }
++            mInterface.refresh(userId);
++        } catch (RemoteException re) {
++            System.err.println(re.toString());
++            System.err.println("Error: A fatal exception has occurred.");
++        }
++        return 0;
+     }
+     private int runSetPriority() throws RemoteException {
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch b/patches/frameworks/base/0012-Themes-Expose-resolver-hardcoded-colors.patch
new file mode 100644 (file)
index 0000000..618f62d
--- /dev/null
@@ -0,0 +1,200 @@
+From 68105cc059781ce4d0948cfe6d34511da24079d2 Mon Sep 17 00:00:00 2001
+From: Dave Kover <dkover@cyngn.com>
+Date: Fri, 9 Dec 2016 10:47:17 -0700
+Subject: [PATCH 12/38] Themes: Expose resolver hardcoded colors
+
+commit dbbd5e70cc65002df41561474b03362022dd6716
+Author: Dave Kover <dkover@cyngn.com>
+Date:   Wed Feb 18 16:11:14 2015 -0800
+
+    Themes: Expose resolver hardcoded colors
+
+    Expose background colors of the resolver list.
+
+    Change-Id: I3a0a460c5ffe0f5057b3b9ec92faa7a3e09c9e01
+
+commit 0343eb126f3901a3857791137f74fa805bb9d75c
+Author: Thyrus11 <thyrus11@gmail.com>
+Date:   Sat Feb 21 07:19:42 2015 +0100
+
+    Themes: Make resolver list fully themeable
+
+    Follow-up on commit cc9e3b8fcba95b911d1cda36f7770c410058aa8b.
+
+    Change-Id: I3f006a1157db9d0b151a4fe8edf50e7edc7a0b9f
+
+commit c7d973809488b801e8c708d740009f1233bb762e
+Author: Nicholas Chum <nicholaschum@gmail.com>
+Date:   Sun Nov 8 05:27:28 2015 -0500
+
+    Themes: Allow Resolver List BG to be fully themed
+
+    We are able to trace the activity of the new resolver/chooser through
+    different
+    methods, thus leading us to the Java file:
+    \com\android\internal\app\ChooserActivity.java
+    Here we see that the exposed "chooser_service_row_background_color" is
+    available, but not the rest of the activity, so we look into R.layout's,
+    and we
+    find chooser_grid to be the only one containing hardcoded
+    "@color/white" values (as this is framework, we assume this is also
+    known as
+    "@android:color/white" to themers).
+
+    Expose all "@color/white" values from this file to resolver_list_bg.
+
+    Change-Id: I286d92b5d1f672c8adb3c0af1951793521536d90
+
+Change-Id: Iec7951147bbbc99aee6b06ae50c1acc7b9c01a7f
+---
+ core/res/res/layout/chooser_grid.xml                 |  6 +++---
+ .../res/layout/resolver_different_item_header.xml    |  2 +-
+ core/res/res/layout/resolver_list.xml                |  8 ++++----
+ core/res/res/layout/resolver_list_with_default.xml   |  6 +++---
+ core/res/res/values/projekt_colors.xml               | 20 ++++++++++++++++++++
+ 5 files changed, 31 insertions(+), 11 deletions(-)
+ create mode 100644 core/res/res/values/projekt_colors.xml
+
+diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
+index d8dd447..78c2e05 100644
+--- a/core/res/res/layout/chooser_grid.xml
++++ b/core/res/res/layout/chooser_grid.xml
+@@ -31,7 +31,7 @@
+             android:layout_alwaysShow="true"
+             android:elevation="8dp"
+             android:paddingStart="16dp"
+-            android:background="@color/white" >
++            android:background="@color/resolver_list_bg" >
+         <TextView android:id="@+id/profile_button"
+                   android:layout_width="wrap_content"
+                   android:layout_height="48dp"
+@@ -74,7 +74,7 @@
+             android:id="@+id/resolver_list"
+             android:clipToPadding="false"
+             android:scrollbarStyle="outsideOverlay"
+-            android:background="@color/white"
++            android:background="@color/resolver_list_bg"
+             android:elevation="8dp"
+             android:listSelector="@color/transparent"
+             android:divider="@null"
+@@ -85,7 +85,7 @@
+               android:layout_width="match_parent"
+               android:layout_height="wrap_content"
+               android:layout_alwaysShow="true"
+-              android:background="@color/white"
++              android:background="@color/resolver_list_bg"
+               android:text="@string/noApplications"
+               android:padding="32dp"
+               android:gravity="center"
+diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
+index 5889136..201c8c6 100644
+--- a/core/res/res/layout/resolver_different_item_header.xml
++++ b/core/res/res/layout/resolver_different_item_header.xml
+@@ -29,6 +29,6 @@
+     android:paddingEnd="16dp"
+     android:paddingTop="8dp"
+     android:paddingBottom="8dp"
+-    android:background="@color/white"
++    android:background="@color/resolver_list_bg"
+     android:elevation="8dp"
+     />
+diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
+index c4e8e9c..1b6230a 100644
+--- a/core/res/res/layout/resolver_list.xml
++++ b/core/res/res/layout/resolver_list.xml
+@@ -30,7 +30,7 @@
+         android:layout_height="wrap_content"
+         android:layout_alwaysShow="true"
+         android:elevation="8dp"
+-        android:background="@color/white">
++        android:background="@color/resolver_list_bg">
+         <TextView
+             android:id="@+id/profile_button"
+@@ -69,7 +69,7 @@
+         android:id="@+id/resolver_list"
+         android:clipToPadding="false"
+         android:scrollbarStyle="outsideOverlay"
+-        android:background="@color/white"
++        android:background="@color/resolver_list_bg"
+         android:elevation="8dp"
+         android:nestedScrollingEnabled="true"
+         android:scrollIndicators="top|bottom"
+@@ -78,7 +78,7 @@
+     <TextView android:id="@+id/empty"
+               android:layout_width="match_parent"
+               android:layout_height="wrap_content"
+-              android:background="@color/white"
++              android:background="@color/resolver_list_bg"
+               android:elevation="8dp"
+               android:layout_alwaysShow="true"
+               android:text="@string/noApplications"
+@@ -99,7 +99,7 @@
+         android:orientation="horizontal"
+         android:layoutDirection="locale"
+         android:measureWithLargestChild="true"
+-        android:background="@color/white"
++        android:background="@color/resolver_list_bg"
+         android:paddingTop="8dp"
+         android:paddingBottom="8dp"
+         android:paddingStart="12dp"
+diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
+index 02dc2ed..d3baf68 100644
+--- a/core/res/res/layout/resolver_list_with_default.xml
++++ b/core/res/res/layout/resolver_list_with_default.xml
+@@ -29,7 +29,7 @@
+         android:layout_height="wrap_content"
+         android:layout_alwaysShow="true"
+         android:orientation="vertical"
+-        android:background="@color/white"
++        android:background="@color/resolver_list_bg"
+         android:elevation="8dp">
+         <LinearLayout
+@@ -110,7 +110,7 @@
+             android:paddingBottom="8dp"
+             android:paddingStart="12dp"
+             android:paddingEnd="12dp"
+-            android:background="@color/white"
++            android:background="@color/resolver_list_bg"
+             android:elevation="8dp">
+             <Button
+@@ -150,7 +150,7 @@
+         android:id="@+id/resolver_list"
+         android:clipToPadding="false"
+         android:scrollbarStyle="outsideOverlay"
+-        android:background="@color/white"
++        android:background="@color/resolver_list_bg"
+         android:elevation="8dp"
+         android:nestedScrollingEnabled="true"
+         android:divider="@null" />
+diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..c6dbc1c
+--- /dev/null
++++ b/core/res/res/values/projekt_colors.xml
+@@ -0,0 +1,20 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Projekt Substratum
++
++    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>
++    <color name="resolver_list_bg">@color/white</color>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch b/patches/frameworks/base/0013-Themes-Allow-Immersive-cling-colors-to-be-fully-them.patch
new file mode 100644 (file)
index 0000000..a5b2fc9
--- /dev/null
@@ -0,0 +1,81 @@
+From 0e81796b338e5009df8049d0ad4c4b2095f4c807 Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Tue, 17 Nov 2015 18:57:11 -0500
+Subject: [PATCH 13/38] Themes: Allow Immersive cling colors to be fully themed
+
+This allows the immersive mode help tooltip to be themed completely by
+removing hardcoded framework calls. Let the themer decide what they want
+the colors to be.
+
+Change-Id: Ia0927fda5e44a3ce8ef699cb018bea9b9e7ace62
+---
+ core/res/res/layout/immersive_mode_cling.xml | 12 ++++++------
+ core/res/res/values/projekt_colors.xml       |  3 +++
+ 2 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
+index b08b0f4..6dbde20 100644
+--- a/core/res/res/layout/immersive_mode_cling.xml
++++ b/core/res/res/layout/immersive_mode_cling.xml
+@@ -16,7 +16,7 @@
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+-        android:background="?android:attr/colorAccent"
++        android:background="@color/immersive_cling_bg_color"
+         android:gravity="center_vertical"
+         android:paddingBottom="24dp">
+@@ -47,7 +47,7 @@
+                 android:paddingTop="8dp"
+                 android:scaleType="center"
+                 android:src="@drawable/ic_expand_more_48dp"
+-                android:tint="?android:attr/colorAccent"/>
++                android:tint="@color/immersive_cling_bg_color"/>
+     </FrameLayout>
+     <TextView
+@@ -59,7 +59,7 @@
+             android:paddingStart="48dp"
+             android:paddingTop="40dp"
+             android:text="@string/immersive_cling_title"
+-            android:textColor="@color/primary_text_default_material_light"
++            android:textColor="@color/immersive_cling_text_color"
+             android:textSize="24sp" />
+     <TextView
+@@ -71,7 +71,7 @@
+             android:paddingStart="48dp"
+             android:paddingTop="12.6dp"
+             android:text="@string/immersive_cling_description"
+-            android:textColor="@color/primary_text_default_material_light"
++            android:textColor="@color/immersive_cling_text_color"
+             android:textSize="16sp" />
+     <Button
+@@ -86,7 +86,7 @@
+             android:paddingEnd="8dp"
+             android:paddingStart="8dp"
+             android:text="@string/immersive_cling_positive"
+-            android:textColor="@android:color/white"
++            android:textColor="@color/immersive_cling_button_text_color"
+             android:textSize="14sp" />
+-</RelativeLayout>
+\ No newline at end of file
++</RelativeLayout>
+diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
+index c6dbc1c..7408ae9 100644
+--- a/core/res/res/values/projekt_colors.xml
++++ b/core/res/res/values/projekt_colors.xml
+@@ -17,4 +17,7 @@
+ <resources>
+     <color name="resolver_list_bg">@color/white</color>
++    <color name="immersive_cling_bg_color">@color/accent_device_default_light</color>
++    <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
++    <color name="immersive_cling_button_text_color">@android:color/white</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch b/patches/frameworks/base/0014-Themes-Allow-Permission-Icons-to-be-fully-themed.patch
new file mode 100644 (file)
index 0000000..64aa7f6
--- /dev/null
@@ -0,0 +1,44 @@
+From 16db866f5fdb07a80c87e733af4952ff2484a4f3 Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Mon, 23 Nov 2015 23:49:15 -0500
+Subject: [PATCH 14/38] Themes: Allow Permission Icons to be fully themed
+
+This removes the forced @android:color/black tint on the permission
+icons during app sideload through PackageInstaller.
+
+These icons are able to be changed through framework XMLs, but this line
+forces a black tint (invisible on dark themes) on the icons. Let's
+remove this.
+
+Change-Id: I31eb5021a6d297997dbba156f98cbf47f2102b6c
+---
+ core/res/res/layout/app_permission_item.xml | 2 +-
+ core/res/res/values/projekt_colors.xml      | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
+index 383d771..a80d40e 100644
+--- a/core/res/res/layout/app_permission_item.xml
++++ b/core/res/res/layout/app_permission_item.xml
+@@ -32,7 +32,7 @@
+         android:layout_marginStart="16dp"
+         android:layout_marginEnd="8dp"
+         android:scaleType="fitCenter"
+-        android:tint="@android:color/black"/>
++        android:tint="@color/app_permission_icon_tint"/>
+     <ImageView
+         android:layout_width="wrap_content"
+diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
+index 7408ae9..a7316ab 100644
+--- a/core/res/res/values/projekt_colors.xml
++++ b/core/res/res/values/projekt_colors.xml
+@@ -20,4 +20,5 @@
+     <color name="immersive_cling_bg_color">@color/accent_device_default_light</color>
+     <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
+     <color name="immersive_cling_button_text_color">@android:color/white</color>
++    <color name="app_permission_icon_tint">@android:color/black</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch b/patches/frameworks/base/0015-Themes-Allow-Navbar-ripple-color-to-be-themed.patch
new file mode 100644 (file)
index 0000000..52cfce0
--- /dev/null
@@ -0,0 +1,73 @@
+From 91025c7450fc618d35d40d6581172a262d73bd22 Mon Sep 17 00:00:00 2001
+From: Dave Kover <dkover@cyngn.com>
+Date: Thu, 14 Apr 2016 10:19:13 +0700
+Subject: [PATCH 15/38] Themes: Allow Navbar ripple color to be themed
+
+PS1:
+Layers Commit by @setiawanjimmy
+Rewrite of commit by: KreAch3R
+Original commit by: Dave Kover
+Distilled from: https://github.com/CyanogenMod/android_frameworks_base/commit/05ce0a6f5651743add398556d557a5f4c40c2503
+
+Change-Id: I7969e952d7e08f1d12e89291512312421585b70f
+---
+ packages/SystemUI/res/values/projekt_colors.xml     | 21 +++++++++++++++++++++
+ .../systemui/statusbar/policy/KeyButtonRipple.java  |  5 ++++-
+ 2 files changed, 25 insertions(+), 1 deletion(-)
+ create mode 100644 packages/SystemUI/res/values/projekt_colors.xml
+
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..a0f1df0
+--- /dev/null
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -0,0 +1,21 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Projekt Substratum
++
++    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>
++    <!-- Navigation button ripple color -->
++    <color name="navbutton_ripple_color">#FFFFFFFF</color>
++</resources>
+diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+index 57e092a..2579579 100644
+--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
++++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+@@ -65,16 +65,19 @@ public class KeyButtonRipple extends Drawable {
+     private final HashSet<Animator> mRunningAnimations = new HashSet<>();
+     private final ArrayList<Animator> mTmpArray = new ArrayList<>();
++    private int mRippleColor;
++
+     public KeyButtonRipple(Context ctx, View targetView) {
+         mMaxWidth =  ctx.getResources().getDimensionPixelSize(R.dimen.key_button_ripple_max_width);
+         mTargetView = targetView;
++        mRippleColor = ctx.getResources().getColor(R.color.navbutton_ripple_color);
+     }
+     private Paint getRipplePaint() {
+         if (mRipplePaint == null) {
+             mRipplePaint = new Paint();
+             mRipplePaint.setAntiAlias(true);
+-            mRipplePaint.setColor(0xffffffff);
++            mRipplePaint.setColor(mRippleColor);
+         }
+         return mRipplePaint;
+     }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch b/patches/frameworks/base/0016-SystemUI-Expose-QS-edit-item-decoration-background-c.patch
new file mode 100644 (file)
index 0000000..c3ad488
--- /dev/null
@@ -0,0 +1,58 @@
+From 2220bc8b7603b3223e73cd4303151d56eda5948b Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Sun, 18 Sep 2016 21:33:18 +0700
+Subject: [PATCH 16/38] SystemUI: Expose QS edit item decoration background
+ color
+
+PS2:
+More descriptive color name
+
+@nathanchance edit: updated for 7.1 Nougat
+
+Change-Id: I9867ca26e7d9dacad37d2b70180a98fede0fb0e8
+---
+ packages/SystemUI/res/values/projekt_colors.xml                     | 2 ++
+ .../SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java | 6 ++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+index a0f1df0..42f4a15 100644
+--- a/packages/SystemUI/res/values/projekt_colors.xml
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -18,4 +18,6 @@
+ <resources>
+     <!-- Navigation button ripple color -->
+     <color name="navbutton_ripple_color">#FFFFFFFF</color>
++    <!-- QS edit page background color -->
++    <color name="qs_edit_item_decoration_bg">@*android:color/secondary_device_default_settings</color>
+ </resources>
+diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+index 8d7f6ee..c7a1441 100644
+--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
++++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+@@ -471,11 +471,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
+         private TileItemDecoration(Context context) {
+             TypedArray ta =
+                     context.obtainStyledAttributes(new int[]{android.R.attr.colorSecondary});
+-            mDrawable = new ColorDrawable(ta.getColor(0, 0));
++            mDrawable = new ColorDrawable();
+             ta.recycle();
+         }
+-
+         @Override
+         public void onDraw(Canvas c, RecyclerView parent, State state) {
+             super.onDraw(c, parent, state);
+@@ -494,6 +493,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
+                         .getLayoutParams();
+                 final int top = child.getTop() + params.topMargin +
+                         Math.round(ViewCompat.getTranslationY(child));
++                // Set drawable color
++                mDrawable.setColor(mContext.getResources().getColor(
++                        R.color.qs_edit_item_decoration_bg));
+                 // Draw full width, in case there aren't tiles all the way across.
+                 mDrawable.setBounds(0, top, width, bottom);
+                 mDrawable.draw(c);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch b/patches/frameworks/base/0017-Allow-custom-alpha-for-notification-shade-bg-color.patch
new file mode 100644 (file)
index 0000000..2f79692
--- /dev/null
@@ -0,0 +1,64 @@
+From 78783e0ed0a5eb8c3676d152892bf5eebf659317 Mon Sep 17 00:00:00 2001
+From: Simao Gomes Viana <xdevs23@outlook.com>
+Date: Fri, 25 Nov 2016 20:50:29 +0100
+Subject: [PATCH 17/38] Allow custom alpha for notification shade bg color
+
+Change-Id: If621df83d994feae0448a734408ba85ac8329325
+---
+ .../stack/NotificationStackScrollLayout.java       | 40 +++++++++++++++-------
+ 1 file changed, 27 insertions(+), 13 deletions(-)
+
+diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+index a6fe438..5cf0e0a 100644
+--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
++++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+@@ -430,19 +430,33 @@ public class NotificationStackScrollLayout extends ViewGroup
+     }
+     private void updateBackgroundDimming() {
+-        float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
+-        alpha *= mBackgroundFadeAmount;
+-        // We need to manually blend in the background color
+-        int scrimColor = mScrimController.getScrimBehindColor();
+-        // SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
+-        float alphaInv = 1 - alpha;
+-        int color = Color.argb((int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
+-                (int) (mBackgroundFadeAmount * Color.red(mBgColor)
+-                        + alphaInv * Color.red(scrimColor)),
+-                (int) (mBackgroundFadeAmount * Color.green(mBgColor)
+-                        + alphaInv * Color.green(scrimColor)),
+-                (int) (mBackgroundFadeAmount * Color.blue(mBgColor)
+-                        + alphaInv * Color.blue(scrimColor)));
++        int color;
++        if(Color.alpha(mBgColor) == 255) {
++            float alpha = BACKGROUND_ALPHA_DIMMED +
++                    (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
++            alpha *= mBackgroundFadeAmount;
++            // We need to manually blend in the background color
++            int scrimColor = mScrimController.getScrimBehindColor();
++            // SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
++            float alphaInv = 1 - alpha;
++            color = Color.argb(
++                    (int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
++                    (int) (mBackgroundFadeAmount * Color.red(mBgColor)
++                            + alphaInv * Color.red(scrimColor)),
++                    (int) (mBackgroundFadeAmount * Color.green(mBgColor)
++                            + alphaInv * Color.green(scrimColor)),
++                    (int) (mBackgroundFadeAmount * Color.blue(mBgColor)
++                            + alphaInv * Color.blue(scrimColor)));
++        } else {
++            int a = Color.alpha(mBgColor) +
++                Color.alpha(mScrimController.getScrimBehindColor());
++            if(a > 255) a = 255;
++            else if(a < 0) /* shouldn't happen */ a = 0;
++            color = Color.argb(
++                a,
++                Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor)
++            );
++        }
+         mBackgroundPaint.setColor(color);
+         invalidate();
+     }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch b/patches/frameworks/base/0018-Themes-Expose-various-QuickSettings-text-colors.patch
new file mode 100644 (file)
index 0000000..3854ba4
--- /dev/null
@@ -0,0 +1,55 @@
+From c6782421d455174ac3b03e994505947471726194 Mon Sep 17 00:00:00 2001
+From: "Niklas Schnettler (Sh4dowSoul)" <niklas.schnettler@gmail.com>
+Date: Wed, 5 Oct 2016 18:07:43 +0200
+Subject: [PATCH 18/38] Themes: Expose various QuickSettings text colors
+
+Change-Id: Iaea71ca83afbc3d8cc6faea6afac16cabb46cfff
+---
+ packages/SystemUI/res/layout/qs_customize_panel_content.xml | 3 ++-
+ packages/SystemUI/res/layout/status_bar_alarm_group.xml     | 2 +-
+ packages/SystemUI/res/values/projekt_colors.xml             | 4 ++++
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+index 04d0e65..9c23250 100644
+--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
++++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+@@ -23,7 +23,8 @@
+         android:layout_height="wrap_content"
+         android:layout_marginTop="28dp"
+         android:navigationContentDescription="@*android:string/action_bar_up_description"
+-        style="?android:attr/toolbarStyle" />
++        style="?android:attr/toolbarStyle"
++        android:titleTextColor="@color/qs_edit_toolbar_text_color"/>
+     <android.support.v7.widget.RecyclerView
+         android:id="@android:id/list"
+diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+index 1b47d4b..dca8afb 100644
+--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
++++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+@@ -73,7 +73,7 @@
+         android:paddingTop="3dp"
+         android:drawablePadding="8dp"
+         android:drawableStart="@drawable/ic_access_alarms_small"
+-        android:textColor="#64ffffff"
++        android:textColor="@color/qs_alarm_status_text_color"
+         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+         android:gravity="top"
+         android:background="?android:attr/selectableItemBackgroundBorderless"
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+index 42f4a15..0f89199 100644
+--- a/packages/SystemUI/res/values/projekt_colors.xml
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -20,4 +20,8 @@
+     <color name="navbutton_ripple_color">#FFFFFFFF</color>
+     <!-- QS edit page background color -->
+     <color name="qs_edit_item_decoration_bg">@*android:color/secondary_device_default_settings</color>
++    <!-- QS alarm status text color -->
++    <color name="qs_alarm_status_text_color">#64ffffff</color>
++    <!-- QS edit page toolbar text color -->
++    <color name="qs_edit_toolbar_text_color">#FFFFFF</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch b/patches/frameworks/base/0019-Notifications-Expose-a-bool-to-disable-dynamic-color.patch
new file mode 100644 (file)
index 0000000..68fa9b3
--- /dev/null
@@ -0,0 +1,162 @@
+From 665ebd4404843764b9a98c3fef7a2e6007695d40 Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Sat, 27 Aug 2016 10:56:46 -0400
+Subject: [PATCH 19/38] Notifications: Expose a bool to disable dynamic colors
+
+This commit allows a themer to overlay a boolean value in config.xml to
+disable dynamic colors applied to the app title and app icon of each
+notification.
+
+PS6:
+Separate app title and small icon colors for more flexibility.
+Expose hardcoded sender text name.
+
+Change-Id: I3c7828118991ec4fc616011caf073c81f75428b4
+---
+ core/java/android/app/Notification.java | 23 ++++++++++++++++++++---
+ core/res/res/values/projekt_colors.xml  |  2 ++
+ core/res/res/values/projekt_config.xml  | 25 +++++++++++++++++++++++++
+ core/res/res/values/projekt_symbols.xml | 25 +++++++++++++++++++++++++
+ 4 files changed, 72 insertions(+), 3 deletions(-)
+ create mode 100644 core/res/res/values/projekt_config.xml
+ create mode 100644 core/res/res/values/projekt_symbols.xml
+
+diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
+index 9f217d4..55029aa 100644
+--- a/core/java/android/app/Notification.java
++++ b/core/java/android/app/Notification.java
+@@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo;
+ import android.content.pm.PackageManager;
+ import android.content.pm.PackageManager.NameNotFoundException;
+ import android.content.res.ColorStateList;
++import android.content.res.Resources;
+ import android.graphics.Bitmap;
+ import android.graphics.Canvas;
+ import android.graphics.Color;
+@@ -3884,7 +3885,7 @@ public class Notification implements Parcelable
+         private void processSmallIconColor(Icon smallIcon, RemoteViews contentView) {
+             boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
+             if (colorable) {
+-                contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
++                contentView.setDrawableParameters(R.id.icon, false, -1, resolveIconContrastColor(),
+                         PorterDuff.Mode.SRC_ATOP, -1);
+             }
+@@ -3901,7 +3902,7 @@ public class Notification implements Parcelable
+             if (largeIcon != null && isLegacy()
+                     && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
+                 // resolve color will fall back to the default when legacy
+-                contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
++                contentView.setDrawableParameters(R.id.icon, false, -1, resolveIconContrastColor(),
+                         PorterDuff.Mode.SRC_ATOP, -1);
+             }
+         }
+@@ -3912,7 +3913,23 @@ public class Notification implements Parcelable
+             }
+         }
++        int getSenderTextColor() {
++            return mContext.getColor(R.color.sender_text_color);
++        }
++
++        int resolveIconContrastColor() {
++            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
++                return mContext.getColor(R.color.notification_icon_default_color);
++            } else {
++                return resolveContrastColor();
++            }
++        }
++
+         int resolveContrastColor() {
++            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
++                return mContext.getColor(R.color.notification_text_default_color);
++            }
++
+             if (mCachedContrastColorIsFor == mN.color && mCachedContrastColor != COLOR_INVALID) {
+                 return mCachedContrastColor;
+             }
+@@ -4915,7 +4932,7 @@ public class Notification implements Parcelable
+                         0 /* flags */);
+             } else {
+                 sb.append(bidi.unicodeWrap(m.mSender),
+-                        makeFontColorSpan(Color.BLACK),
++                        makeFontColorSpan(mBuilder.getSenderTextColor()),
+                         0 /* flags */);
+             }
+             CharSequence text = m.mText == null ? "" : m.mText;
+diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml
+index a7316ab..d17fbba 100644
+--- a/core/res/res/values/projekt_colors.xml
++++ b/core/res/res/values/projekt_colors.xml
+@@ -21,4 +21,6 @@
+     <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
+     <color name="immersive_cling_button_text_color">@android:color/white</color>
+     <color name="app_permission_icon_tint">@android:color/black</color>
++    <color name="notification_text_default_color">@android:color/notification_default_color</color>
++    <color name="sender_text_color">@android:color/black</color>
+ </resources>
+diff --git a/core/res/res/values/projekt_config.xml b/core/res/res/values/projekt_config.xml
+new file mode 100644
+index 0000000..f6eb90a
+--- /dev/null
++++ b/core/res/res/values/projekt_config.xml
+@@ -0,0 +1,25 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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.
++-->
++
++<!-- These resources are around just to allow their values to be customized
++     for different hardware and product builds.  Do not translate. -->
++<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
++
++    <!-- True if the notifications should dynamically tint the app icon and app title -->
++    <bool name="config_allowNotificationIconTextTinting">true</bool>
++
++</resources>
+diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml
+new file mode 100644
+index 0000000..f597a5f
+--- /dev/null
++++ b/core/res/res/values/projekt_symbols.xml
+@@ -0,0 +1,25 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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>
++
++  <!-- Notification icon/text dynamic tint -->
++  <java-symbol type="bool" name="config_allowNotificationIconTextTinting" />
++  <java-symbol type="color" name="notification_text_default_color" />
++  <java-symbol type="color" name="sender_text_color" />
++
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch b/patches/frameworks/base/0020-Notification-dynamic-colors-bool-compatible-with-OMS.patch
new file mode 100644 (file)
index 0000000..6df4637
--- /dev/null
@@ -0,0 +1,48 @@
+From 85f0110784ed2b55e062ca3c35d05480dc78ab8a Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Mon, 14 Nov 2016 14:49:47 +0200
+Subject: [PATCH 20/38] Notification dynamic colors bool compatible with OMS7
+
+OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
+
+// Resources.getSystem Resources are created on request and aren't tracked by
+// mResourceReferences.
+//
+// If overlays targeting "android" are to be used, we must create the system
+// resources regardless of whether they already exist, since otherwise the
+// information on what overlays to use would be lost. This is wasteful for most
+// applications, so limit this operation to the system user only. (This means
+// Resources.getSystem() will *not* use overlays for applications.)
+
+Replaced deprecated Resources.getSystem() with compatible method.
+
+Change-Id: I02efe27de3cc7067552964ffbaf079f9e9b5bc3e
+---
+ core/java/android/app/Notification.java | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
+index 55029aa..67c2132 100644
+--- a/core/java/android/app/Notification.java
++++ b/core/java/android/app/Notification.java
+@@ -3918,7 +3918,7 @@ public class Notification implements Parcelable
+         }
+         int resolveIconContrastColor() {
+-            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
++            if (!mContext.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
+                 return mContext.getColor(R.color.notification_icon_default_color);
+             } else {
+                 return resolveContrastColor();
+@@ -3926,7 +3926,7 @@ public class Notification implements Parcelable
+         }
+         int resolveContrastColor() {
+-            if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
++            if (!mContext.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) {
+                 return mContext.getColor(R.color.notification_text_default_color);
+             }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch b/patches/frameworks/base/0021-Allow-prevention-of-doze-notification-color-inversio.patch
new file mode 100644 (file)
index 0000000..0014548
--- /dev/null
@@ -0,0 +1,66 @@
+From a5c8355f8999d9c4868bb22018ed8d6d9e25ad48 Mon Sep 17 00:00:00 2001
+From: Daniel Koman <dankoman30@gmail.com>
+Date: Fri, 17 Apr 2015 11:56:28 -0600
+Subject: [PATCH 21/38] Allow prevention of doze notification color inversion
+
+Removed empty newline at the end -- KreAch3R
+Removed slims files for aosp roms -- Bgill55
+
+Change-Id: I2d361c34904f3d168894b8b1741456319fd68456
+---
+ core/res/res/values/projekt_config.xml                           | 5 +++++
+ core/res/res/values/projekt_symbols.xml                          | 3 +++
+ packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 4 +++-
+ 3 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/core/res/res/values/projekt_config.xml b/core/res/res/values/projekt_config.xml
+index f6eb90a..5234959 100644
+--- a/core/res/res/values/projekt_config.xml
++++ b/core/res/res/values/projekt_config.xml
+@@ -22,4 +22,9 @@
+     <!-- True if the notifications should dynamically tint the app icon and app title -->
+     <bool name="config_allowNotificationIconTextTinting">true</bool>
++    <!-- Whether doze should invert colors for notifications. If the RRO theme causes
++    the NORMAL notification background to be dark and the text to be light, this boolean
++    needs to be set to false, to prevent the doze notifications from being light -->
++    <bool name="config_invert_colors_on_doze">true</bool>
++
+ </resources>
+diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml
+index f597a5f..16a5728 100644
+--- a/core/res/res/values/projekt_symbols.xml
++++ b/core/res/res/values/projekt_symbols.xml
+@@ -22,4 +22,7 @@
+   <java-symbol type="color" name="notification_text_default_color" />
+   <java-symbol type="color" name="sender_text_color" />
++  <!-- Doze invert -->
++  <java-symbol type="bool" name="config_invert_colors_on_doze" />
++
+ </resources>
+diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+index 2c96e31..65fd115 100644
+--- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
++++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+@@ -20,6 +20,7 @@ import android.animation.Animator;
+ import android.animation.AnimatorListenerAdapter;
+ import android.animation.ValueAnimator;
+ import android.content.Context;
++import android.content.res.Resources;
+ import android.graphics.ColorMatrix;
+ import android.graphics.ColorMatrixColorFilter;
+ import android.graphics.Paint;
+@@ -90,7 +91,8 @@ public class ViewInvertHelper {
+     }
+     public void update(boolean invert) {
+-        if (invert) {
++        if (invert && Resources.getSystem().getBoolean(
++                com.android.internal.R.bool.config_invert_colors_on_doze)) {
+             updateInvertPaint(1f);
+             for (int i = 0; i < mTargets.size(); i++) {
+                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch b/patches/frameworks/base/0022-OMS7-compatible-Ambient-notification-inversion.patch
new file mode 100644 (file)
index 0000000..3768431
--- /dev/null
@@ -0,0 +1,64 @@
+From 367e7476f68b80c265bedb92a019cb5fd7c8dfc7 Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Mon, 14 Nov 2016 14:44:17 +0200
+Subject: [PATCH 22/38] OMS7 compatible 'Ambient notification inversion'
+
+OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
+
+// Resources.getSystem Resources are created on request and aren't tracked by
+// mResourceReferences.
+//
+// If overlays targeting "android" are to be used, we must create the system
+// resources regardless of whether they already exist, since otherwise the
+// information on what overlays to use would be lost. This is wasteful for most
+// applications, so limit this operation to the system user only. (This means
+// Resources.getSystem() will *not* use overlays for applications.)
+
+Replaced deprecated Resources.getSystem() with compatible method.
+
+Change-Id: I80ad5d037004f0dc63d9eb746c3af05e59a8834e
+---
+ packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+index 65fd115..605f381 100644
+--- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
++++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+@@ -20,7 +20,6 @@ import android.animation.Animator;
+ import android.animation.AnimatorListenerAdapter;
+ import android.animation.ValueAnimator;
+ import android.content.Context;
+-import android.content.res.Resources;
+ import android.graphics.ColorMatrix;
+ import android.graphics.ColorMatrixColorFilter;
+ import android.graphics.Paint;
+@@ -37,6 +36,7 @@ public class ViewInvertHelper {
+     private final ColorMatrix mMatrix = new ColorMatrix();
+     private final ColorMatrix mGrayscaleMatrix = new ColorMatrix();
+     private final long mFadeDuration;
++    private final boolean mThemeInvert;
+     private final ArrayList<View> mTargets = new ArrayList<>();
+     public ViewInvertHelper(View v, long fadeDuration) {
+@@ -45,6 +45,7 @@ public class ViewInvertHelper {
+     }
+     public ViewInvertHelper(Context context, long fadeDuration) {
+         mFadeDuration = fadeDuration;
++        mThemeInvert = context.getResources().getBoolean(com.android.internal.R.bool.config_invert_colors_on_doze);
+     }
+     private static ArrayList<View> constructArray(View target) {
+@@ -91,8 +92,7 @@ public class ViewInvertHelper {
+     }
+     public void update(boolean invert) {
+-        if (invert && Resources.getSystem().getBoolean(
+-                com.android.internal.R.bool.config_invert_colors_on_doze)) {
++        if (invert && mThemeInvert) {
+             updateInvertPaint(1f);
+             for (int i = 0; i < mTargets.size(); i++) {
+                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch b/patches/frameworks/base/0023-SystemUI-Use-own-drawables-for-QS-expand-icon.patch
new file mode 100644 (file)
index 0000000..4550eb4
--- /dev/null
@@ -0,0 +1,505 @@
+From 415172d6cb86b8608948ebd8d26d5ac8911cb07c Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Mon, 5 Dec 2016 19:00:04 +0700
+Subject: [PATCH 23/38] SystemUI: Use own drawables for QS expand icon
+
+This was using the volume panel drawables used also on volume panel.
+So with this commit themers can give different icon for either QS
+and volume panel expand icon.
+
+Change-Id: Ice8d8a520b9b22ba773cceb885e11c8a4bbf6d5f
+---
+ .../anim/ic_qs_collapse_chevron_02_animation.xml   | 25 +++++++++
+ .../anim/ic_qs_collapse_rectangle_1_animation.xml  | 26 +++++++++
+ .../anim/ic_qs_collapse_rectangle_2_animation.xml  | 26 +++++++++
+ .../res/anim/ic_qs_expand_chevron_01_animation.xml | 25 +++++++++
+ .../anim/ic_qs_expand_rectangle_3_animation.xml    | 26 +++++++++
+ .../anim/ic_qs_expand_rectangle_4_animation.xml    | 26 +++++++++
+ packages/SystemUI/res/drawable/ic_qs_collapse.xml  | 62 ++++++++++++++++++++++
+ .../res/drawable/ic_qs_collapse_animation.xml      | 29 ++++++++++
+ packages/SystemUI/res/drawable/ic_qs_expand.xml    | 62 ++++++++++++++++++++++
+ .../res/drawable/ic_qs_expand_animation.xml        | 29 ++++++++++
+ .../ic_qs_collapse_animation_interpolator_0.xml    | 17 ++++++
+ .../ic_qs_expand_animation_interpolator_0.xml      | 17 ++++++
+ .../statusbar/phone/ExpandableIndicator.java       |  8 +--
+ 13 files changed, 374 insertions(+), 4 deletions(-)
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
+ create mode 100644 packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
+ create mode 100644 packages/SystemUI/res/drawable/ic_qs_collapse.xml
+ create mode 100644 packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
+ create mode 100644 packages/SystemUI/res/drawable/ic_qs_expand.xml
+ create mode 100644 packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
+ create mode 100644 packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
+ create mode 100644 packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
+
+diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
+new file mode 100644
+index 0000000..443f2a6
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_collapse_chevron_02_animation.xml
+@@ -0,0 +1,25 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="250"
++        android:interpolator="@android:interpolator/fast_out_slow_in"
++        android:pathData="M 12.0,9.0 c 0.0,0.66667 0.0,5.0 0.0,6.0"
++        android:propertyXName="translateX"
++        android:propertyYName="translateY" />
++
++</set>
+\ No newline at end of file
+diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
+new file mode 100644
+index 0000000..b73cdca
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_1_animation.xml
+@@ -0,0 +1,26 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="200"
++        android:interpolator="@interpolator/ic_qs_collapse_animation_interpolator_0"
++        android:propertyName="rotation"
++        android:valueFrom="45.0"
++        android:valueTo="-45.0"
++        android:valueType="floatType" />
++
++</set>
+diff --git a/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
+new file mode 100644
+index 0000000..91c83fc
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_collapse_rectangle_2_animation.xml
+@@ -0,0 +1,26 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="200"
++        android:interpolator="@interpolator/ic_qs_collapse_animation_interpolator_0"
++        android:propertyName="rotation"
++        android:valueFrom="-45.0"
++        android:valueTo="45.0"
++        android:valueType="floatType" />
++
++</set>
+diff --git a/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
+new file mode 100644
+index 0000000..e43e645
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_expand_chevron_01_animation.xml
+@@ -0,0 +1,25 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="250"
++        android:interpolator="@android:interpolator/fast_out_slow_in"
++        android:pathData="M 12.0,15.0 c 0.0,-1.0 0.0,-5.33333 0.0,-6.0"
++        android:propertyXName="translateX"
++        android:propertyYName="translateY" />
++
++</set>
+\ No newline at end of file
+diff --git a/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
+new file mode 100644
+index 0000000..493bdae
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_3_animation.xml
+@@ -0,0 +1,26 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="200"
++        android:interpolator="@interpolator/ic_qs_expand_animation_interpolator_0"
++        android:propertyName="rotation"
++        android:valueFrom="45.0"
++        android:valueTo="-45.0"
++        android:valueType="floatType" />
++
++</set>
+diff --git a/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
+new file mode 100644
+index 0000000..58e485c
+--- /dev/null
++++ b/packages/SystemUI/res/anim/ic_qs_expand_rectangle_4_animation.xml
+@@ -0,0 +1,26 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<set xmlns:android="http://schemas.android.com/apk/res/android" >
++
++    <objectAnimator
++        android:duration="200"
++        android:interpolator="@interpolator/ic_qs_expand_animation_interpolator_0"
++        android:propertyName="rotation"
++        android:valueFrom="-45.0"
++        android:valueTo="45.0"
++        android:valueType="floatType" />
++
++</set>
+diff --git a/packages/SystemUI/res/drawable/ic_qs_collapse.xml b/packages/SystemUI/res/drawable/ic_qs_collapse.xml
+new file mode 100644
+index 0000000..bba6b7f
+--- /dev/null
++++ b/packages/SystemUI/res/drawable/ic_qs_collapse.xml
+@@ -0,0 +1,62 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<vector xmlns:android="http://schemas.android.com/apk/res/android"
++    android:name="ic_qs_collapse"
++    android:height="24dp"
++    android:viewportHeight="24"
++    android:viewportWidth="24"
++    android:width="24dp" >
++
++    <group
++        android:name="chevron_02"
++        android:rotation="90"
++        android:translateX="12"
++        android:translateY="9" >
++        <group
++            android:name="rectangle_2"
++            android:rotation="-45" >
++            <group
++                android:name="rectangle_2_pivot"
++                android:translateY="4" >
++                <group
++                    android:name="rectangle_path_2_position"
++                    android:translateY="-1" >
++                    <path
++                        android:name="rectangle_path_2"
++                        android:fillColor="#FFFFFFFF"
++                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
++                </group>
++            </group>
++        </group>
++        <group
++            android:name="rectangle_1"
++            android:rotation="45" >
++            <group
++                android:name="rectangle_1_pivot"
++                android:translateY="-4" >
++                <group
++                    android:name="rectangle_path_1_position"
++                    android:translateY="1" >
++                    <path
++                        android:name="rectangle_path_1"
++                        android:fillColor="#FFFFFFFF"
++                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
++                </group>
++            </group>
++        </group>
++    </group>
++
++</vector>
+diff --git a/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml b/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
+new file mode 100644
+index 0000000..8138b2e
+--- /dev/null
++++ b/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml
+@@ -0,0 +1,29 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
++    android:drawable="@drawable/ic_qs_collapse" >
++
++    <target
++        android:name="chevron_02"
++        android:animation="@anim/ic_qs_collapse_chevron_02_animation" />
++    <target
++        android:name="rectangle_2"
++        android:animation="@anim/ic_qs_collapse_rectangle_2_animation" />
++    <target
++        android:name="rectangle_1"
++        android:animation="@anim/ic_qs_collapse_rectangle_1_animation" />
++
++</animated-vector>
+diff --git a/packages/SystemUI/res/drawable/ic_qs_expand.xml b/packages/SystemUI/res/drawable/ic_qs_expand.xml
+new file mode 100644
+index 0000000..bb22064
+--- /dev/null
++++ b/packages/SystemUI/res/drawable/ic_qs_expand.xml
+@@ -0,0 +1,62 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<vector xmlns:android="http://schemas.android.com/apk/res/android"
++    android:name="ic_qs_expand"
++    android:height="24dp"
++    android:viewportHeight="24"
++    android:viewportWidth="24"
++    android:width="24dp" >
++
++    <group
++        android:name="chevron_01"
++        android:rotation="90"
++        android:translateX="12"
++        android:translateY="15" >
++        <group
++            android:name="rectangle_3"
++            android:rotation="45" >
++            <group
++                android:name="rectangle_2_pivot_0"
++                android:translateY="4" >
++                <group
++                    android:name="rectangle_path_3_position"
++                    android:translateY="-1" >
++                    <path
++                        android:name="rectangle_path_3"
++                        android:fillColor="#FFFFFFFF"
++                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
++                </group>
++            </group>
++        </group>
++        <group
++            android:name="rectangle_4"
++            android:rotation="-45" >
++            <group
++                android:name="rectangle_1_pivot_0"
++                android:translateY="-4" >
++                <group
++                    android:name="rectangle_path_4_position"
++                    android:translateY="1" >
++                    <path
++                        android:name="rectangle_path_4"
++                        android:fillColor="#FFFFFFFF"
++                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
++                </group>
++            </group>
++        </group>
++    </group>
++
++</vector>
+diff --git a/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml b/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
+new file mode 100644
+index 0000000..b561ee0
+--- /dev/null
++++ b/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml
+@@ -0,0 +1,29 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
++    android:drawable="@drawable/ic_qs_expand" >
++
++    <target
++        android:name="chevron_01"
++        android:animation="@anim/ic_qs_expand_chevron_01_animation" />
++    <target
++        android:name="rectangle_3"
++        android:animation="@anim/ic_qs_expand_rectangle_3_animation" />
++    <target
++        android:name="rectangle_4"
++        android:animation="@anim/ic_qs_expand_rectangle_4_animation" />
++
++</animated-vector>
+diff --git a/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
+new file mode 100644
+index 0000000..c3930e4
+--- /dev/null
++++ b/packages/SystemUI/res/interpolator/ic_qs_collapse_animation_interpolator_0.xml
+@@ -0,0 +1,17 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
++    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
+diff --git a/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
+new file mode 100644
+index 0000000..c3930e4
+--- /dev/null
++++ b/packages/SystemUI/res/interpolator/ic_qs_expand_animation_interpolator_0.xml
+@@ -0,0 +1,17 @@
++<!--
++     Copyright (C) 2015 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.
++-->
++<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
++    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
+diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+index a295cfa..0f04c28 100644
+--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
++++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+@@ -57,11 +57,11 @@ public class ExpandableIndicator extends ImageView {
+     private int getDrawableResourceId(boolean expanded) {
+         if (mIsDefaultDirection) {
+-            return expanded ? R.drawable.ic_volume_collapse_animation
+-                    : R.drawable.ic_volume_expand_animation;
++            return expanded ? R.drawable.ic_qs_collapse_animation
++                    : R.drawable.ic_qs_expand_animation;
+         } else {
+-            return expanded ? R.drawable.ic_volume_expand_animation
+-                    : R.drawable.ic_volume_collapse_animation;
++            return expanded ? R.drawable.ic_qs_expand_animation
++                    : R.drawable.ic_qs_collapse_animation;
+         }
+     }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch b/patches/frameworks/base/0024-N-Extras-Add-dynamic-theme-BootAnimation-support.patch
new file mode 100644 (file)
index 0000000..88df6a0
--- /dev/null
@@ -0,0 +1,81 @@
+From 429a491bac8c8e3966f9afa5cc80becdb4677f9e Mon Sep 17 00:00:00 2001
+From: 0xD34D <clark@scheffsblend.com>
+Date: Mon, 9 Jan 2017 07:19:41 +0530
+Subject: [PATCH 24/38] N-Extras: Add dynamic theme BootAnimation support
+
+Extracted from "Themes: Port to CM13 [1/3]"
+http://review.cyanogenmod.org/#/c/113273/14
+
+Change-Id: I394897c10f02695f0416e87e9bf960e840bcb3b7
+---
+ cmds/bootanimation/BootAnimation.cpp | 13 ++++++++++---
+ cmds/bootanimation/BootAnimation.h   |  3 ++-
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
+index c6b2f63..f374ece 100644
+--- a/cmds/bootanimation/BootAnimation.cpp
++++ b/cmds/bootanimation/BootAnimation.cpp
+@@ -68,6 +68,7 @@ namespace android {
+ static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
+ static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
+ static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
++static const char THEME_BOOTANIMATION_FILE[] = "/data/system/theme/bootanimation.zip";
+ static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
+ static const char SYSTEM_TIME_DIR_NAME[] = "time";
+ static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
+@@ -317,13 +318,14 @@ status_t BootAnimation::initTexture(SkBitmap *bitmap)
+ // Get bootup Animation File
+-// Parameter: ImageID: IMG_OEM IMG_SYS IMG_ENC
++// Parameter: ImageID: IMG_OEM IMG_SYS IMG_ENC IMG_THM
+ // Return Value : File path
+ const char *BootAnimation::getAnimationFileName(ImageID image)
+ {
+-    const char *fileName[3] = { OEM_BOOTANIMATION_FILE,
++    const char *fileName[4] = { OEM_BOOTANIMATION_FILE,
+             SYSTEM_BOOTANIMATION_FILE,
+-            SYSTEM_ENCRYPTED_BOOTANIMATION_FILE };
++            SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,
++            THEME_BOOTANIMATION_FILE };
+     // Load animations of Carrier through regionalization environment
+     if (Environment::isSupported()) {
+@@ -408,6 +410,9 @@ status_t BootAnimation::readyToRun() {
+     if (encryptedAnimation && (access(getAnimationFileName(IMG_ENC), R_OK) == 0)) {
+         mZipFileName = getAnimationFileName(IMG_ENC);
+     }
++    else if (access(getAnimationFileName(IMG_THM), R_OK) == 0) {
++        mZipFileName = getAnimationFileName(IMG_THM);
++    }
+     else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0) {
+         mZipFileName = getAnimationFileName(IMG_OEM);
+     }
+@@ -421,6 +426,8 @@ status_t BootAnimation::readyToRun() {
+     FILE* fd;
+     if (encryptedAnimation && access(getAnimationFileName(IMG_ENC), R_OK) == 0)
+         fd = fopen(getAnimationFileName(IMG_ENC), "r");
++    else if (access(getAnimationFileName(IMG_THM), R_OK) == 0)
++        fd = fopen(getAnimationFileName(IMG_THM), "r");
+     else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0)
+         fd = fopen(getAnimationFileName(IMG_OEM), "r");
+     else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0)
+diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
+index b70cc0e..958a022 100644
+--- a/cmds/bootanimation/BootAnimation.h
++++ b/cmds/bootanimation/BootAnimation.h
+@@ -122,8 +122,9 @@ private:
+      *IMG_OEM: bootanimation file from oem/media
+      *IMG_SYS: bootanimation file from system/media
+      *IMG_ENC: encrypted bootanimation file from system/media
++     *IMG_THM: bootanimation file from data/system/theme
+      */
+-    enum ImageID { IMG_OEM = 0, IMG_SYS = 1, IMG_ENC = 2 };
++    enum ImageID { IMG_OEM = 0, IMG_SYS = 1, IMG_ENC = 2, IMG_THM = 3 };
+     const char *getAnimationFileName(ImageID image);
+     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
+     status_t initTexture(const Animation::Frame& frame);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch b/patches/frameworks/base/0025-N-Extras-Add-dynamic-theme-fonts-support.patch
new file mode 100644 (file)
index 0000000..9eb6494
--- /dev/null
@@ -0,0 +1,600 @@
+From fd877629e3a2d8bfdafb1ba1371237396ba176e1 Mon Sep 17 00:00:00 2001
+From: 0xD34D <clark@scheffsblend.com>
+Date: Wed, 22 Jun 2016 23:54:23 +0300
+Subject: [PATCH 25/38] N-Extras: Add dynamic theme fonts support
+
+Due to the nature of the removal of assetSeq in OMS7+, we now use the
+more controllable font scale updating code to update the fonts on
+demand.
+
+Extracted from Themes: Port to CM13 [1/3]
+http://review.cyanogenmod.org/#/c/113273/14
+
+Squashed:
+
+Small adjustment to Font commit
+Author camcory
+https://github.com/SubstratumResources/platform_frameworks_base/commit/a13f088dff70bc52f2053f32acff47a7a377a807
+
+Themes: Ensure themed fonts always have fallbacks
+Author 0xD34D
+https://github.com/CyanogenMod/android_frameworks_base/commit/18b301874e2a658eb01f97defd70da038521f450
+
+Themes: Let garbage collector free up native instances
+Author 0xD34D
+https://github.com/CyanogenMod/android_frameworks_base/commit/b7108ea9ce7ad2226aa6340046d24e069c6e8e21
+
+Themes: Make parse() method in FontListParser public
+Author 0xD34D
+https://github.com/CyanogenMod/android_frameworks_base/commit/b3ae4609f2754fd156e34dfbf39551041e976031
+
+Fonts: add sans-serif fallback fonts first
+Author 0xD34D
+https://github.com/CyanogenMod/android_frameworks_base/commit/f1d7b86dd267ed5b59e51339edc4553d37561a39
+
+Themes: Add config change flag for font change
+Author 0xD34D
+https://github.com/CyanogenMod/android_frameworks_base/commit/2ec1a33b70d3c013daa956696b68167a5eeef70d
+
+Themes: don't recreateDefaults on typeface when locale changes
+Author romanbb
+https://github.com/CyanogenMod/android_frameworks_base/commit/e05ffea4ea55a4eb6b40436a864a570509eb33ac
+
+Change-Id: I1f61bd269b42ab6145482a51d25fe5b1b5308f94
+---
+ core/java/android/app/ActivityThread.java          |   7 +-
+ core/java/android/content/pm/ActivityInfo.java     |   5 +
+ core/java/android/content/res/Configuration.java   |   5 +-
+ core/java/android/os/Process.java                  |   7 +-
+ .../com/android/internal/os/ZygoteConnection.java  |  10 ++
+ graphics/java/android/graphics/FontListParser.java |  48 ++++--
+ graphics/java/android/graphics/Typeface.java       | 174 +++++++++++++++++++--
+ .../android/server/am/ActivityManagerService.java  |  11 +-
+ 8 files changed, 240 insertions(+), 27 deletions(-)
+
+diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
+index 55fc25d..44a900b 100644
+--- a/core/java/android/app/ActivityThread.java
++++ b/core/java/android/app/ActivityThread.java
+@@ -48,6 +48,7 @@ import android.database.sqlite.SQLiteDebug;
+ import android.database.sqlite.SQLiteDebug.DbStats;
+ import android.graphics.Bitmap;
+ import android.graphics.Canvas;
++import android.graphics.Typeface;
+ import android.hardware.display.DisplayManagerGlobal;
+ import android.net.ConnectivityManager;
+ import android.net.IConnectivityManager;
+@@ -4852,8 +4853,12 @@ public final class ActivityThread {
+         if (configDiff != 0) {
+             // Ask text layout engine to free its caches if there is a locale change
+             boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
+-            if (hasLocaleConfigChange) {
++            boolean hasFontConfigChange = ((configDiff & ActivityInfo.CONFIG_THEME_FONT) != 0);
++            if (hasLocaleConfigChange || hasFontConfigChange) {
+                 Canvas.freeTextLayoutCaches();
++                if (hasFontConfigChange) {
++                    Typeface.recreateDefaults();
++                }
+                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
+             }
+         }
+diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
+index 5a09c00..42febcf 100644
+--- a/core/java/android/content/pm/ActivityInfo.java
++++ b/core/java/android/content/pm/ActivityInfo.java
+@@ -624,6 +624,11 @@ public class ActivityInfo extends ComponentInfo
+      */
+     public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
+     /**
++     * Bit in {@link #configChanges} that indicates a font change occurred
++     * @hide
++     */
++    public static final int CONFIG_THEME_FONT = 0x200000;
++    /**
+      * Bit in {@link #configChanges} that indicates that the activity
+      * can itself handle changes to the font scaling factor.  Set from the
+      * {@link android.R.attr#configChanges} attribute.  This is
+diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
+index b2d518c..2f7c3ec 100644
+--- a/core/java/android/content/res/Configuration.java
++++ b/core/java/android/content/res/Configuration.java
+@@ -955,6 +955,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
+         int changed = 0;
+         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
+             changed |= ActivityInfo.CONFIG_FONT_SCALE;
++            changed |= ActivityInfo.CONFIG_THEME_FONT;
+             fontScale = delta.fontScale;
+         }
+         if (delta.mcc != 0 && mcc != delta.mcc) {
+@@ -1121,6 +1122,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
+         int changed = 0;
+         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
+             changed |= ActivityInfo.CONFIG_FONT_SCALE;
++            changed |= ActivityInfo.CONFIG_THEME_FONT;
+         }
+         if (delta.mcc != 0 && mcc != delta.mcc) {
+             changed |= ActivityInfo.CONFIG_MCC;
+@@ -1211,7 +1213,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
+      */
+     public static boolean needNewResources(@Config int configChanges,
+             @Config int interestingChanges) {
+-        return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
++        return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE|
++                    ActivityInfo.CONFIG_THEME_FONT)) != 0;
+     }
+     /**
+diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
+index e1b7fda..6dcd045 100644
+--- a/core/java/android/os/Process.java
++++ b/core/java/android/os/Process.java
+@@ -516,11 +516,12 @@ public class Process {
+                                   String abi,
+                                   String instructionSet,
+                                   String appDataDir,
++                                  boolean refreshTheme,
+                                   String[] zygoteArgs) {
+         try {
+             return startViaZygote(processClass, niceName, uid, gid, gids,
+                     debugFlags, mountExternal, targetSdkVersion, seInfo,
+-                    abi, instructionSet, appDataDir, zygoteArgs);
++                    abi, instructionSet, appDataDir, refreshTheme, zygoteArgs);
+         } catch (ZygoteStartFailedEx ex) {
+             Log.e(LOG_TAG,
+                     "Starting VM process through Zygote failed");
+@@ -648,6 +649,7 @@ public class Process {
+                                   String abi,
+                                   String instructionSet,
+                                   String appDataDir,
++                                  boolean refreshTheme,
+                                   String[] extraArgs)
+                                   throws ZygoteStartFailedEx {
+         synchronized(Process.class) {
+@@ -689,6 +691,9 @@ public class Process {
+             } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
+                 argsForZygote.add("--mount-external-write");
+             }
++            if (refreshTheme) {
++                argsForZygote.add("--refresh_theme");
++            }
+             argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
+             //TODO optionally enable debuger
+diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
+index 85d84bb..81257f0 100644
+--- a/core/java/com/android/internal/os/ZygoteConnection.java
++++ b/core/java/com/android/internal/os/ZygoteConnection.java
+@@ -22,6 +22,7 @@ import static android.system.OsConstants.STDERR_FILENO;
+ import static android.system.OsConstants.STDIN_FILENO;
+ import static android.system.OsConstants.STDOUT_FILENO;
++import android.graphics.Typeface;
+ import android.net.Credentials;
+ import android.net.LocalSocket;
+ import android.os.Process;
+@@ -194,6 +195,10 @@ class ZygoteConnection {
+                 Os.fcntlInt(childPipeFd, F_SETFD, 0);
+             }
++            if (parsedArgs.refreshTheme) {
++                Typeface.recreateDefaults();
++            }
++
+             /**
+              * In order to avoid leaking descriptors to the Zygote child,
+              * the native code must close the two Zygote socket descriptors
+@@ -373,6 +378,9 @@ class ZygoteConnection {
+          */
+         String appDataDir;
++        /** from --refresh_theme */
++        boolean refreshTheme;
++
+         /**
+          * Constructs instance and parses args
+          * @param args zygote command-line args
+@@ -531,6 +539,8 @@ class ZygoteConnection {
+                     instructionSet = arg.substring(arg.indexOf('=') + 1);
+                 } else if (arg.startsWith("--app-data-dir=")) {
+                     appDataDir = arg.substring(arg.indexOf('=') + 1);
++                } else if (arg.equals("--refresh_theme")) {
++                    refreshTheme = true;
+                 } else {
+                     break;
+                 }
+diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
+index 7871aa8..f4590c9 100644
+--- a/graphics/java/android/graphics/FontListParser.java
++++ b/graphics/java/android/graphics/FontListParser.java
+@@ -21,6 +21,9 @@ import android.util.Xml;
+ import org.xmlpull.v1.XmlPullParser;
+ import org.xmlpull.v1.XmlPullParserException;
++import java.io.BufferedInputStream;
++import java.io.File;
++import java.io.FileInputStream;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.util.ArrayList;
+@@ -88,18 +91,41 @@ public class FontListParser {
+     }
+     /* Parse fallback list (no names) */
+-    public static Config parse(InputStream in) throws XmlPullParserException, IOException {
++    public static Config parse(File configFilename, String fontDir)
++            throws XmlPullParserException, IOException {
++        FileInputStream in = null;
++        in = new FileInputStream(configFilename);
++        return FontListParser.parse(in, fontDir);
++    }
++
++    /* Parse fallback list (no names) */
++    public static Config parse(InputStream in, String fontDir)
++            throws XmlPullParserException, IOException {
++        BufferedInputStream bis = null;
+         try {
++            // wrap input stream in a BufferedInputStream, if it's not already, for mark support
++            if (!(in instanceof BufferedInputStream)) {
++                bis = new BufferedInputStream(in);
++            } else {
++                bis = (BufferedInputStream) in;
++            }
++            // mark the beginning so we can reset to this position after checking format
++            bis.mark(in.available());
++            return parseNormalFormat(bis, fontDir);
++        } finally {
++            if (bis != null) bis.close();
++        }
++    }
++
++    public static Config parseNormalFormat(InputStream in, String dirName)
++            throws XmlPullParserException, IOException {
+             XmlPullParser parser = Xml.newPullParser();
+             parser.setInput(in, null);
+             parser.nextTag();
+-            return readFamilies(parser);
+-        } finally {
+-            in.close();
+-        }
++            return readFamilies(parser, dirName);
+     }
+-    private static Config readFamilies(XmlPullParser parser)
++    private static Config readFamilies(XmlPullParser parser, String dirPath)
+             throws XmlPullParserException, IOException {
+         Config config = new Config();
+         parser.require(XmlPullParser.START_TAG, null, "familyset");
+@@ -107,7 +133,7 @@ public class FontListParser {
+             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
+             String tag = parser.getName();
+             if (tag.equals("family")) {
+-                config.families.add(readFamily(parser));
++                config.families.add(readFamily(parser, dirPath));
+             } else if (tag.equals("alias")) {
+                 config.aliases.add(readAlias(parser));
+             } else {
+@@ -117,7 +143,7 @@ public class FontListParser {
+         return config;
+     }
+-    private static Family readFamily(XmlPullParser parser)
++    private static Family readFamily(XmlPullParser parser, String dirPath)
+             throws XmlPullParserException, IOException {
+         String name = parser.getAttributeValue(null, "name");
+         String lang = parser.getAttributeValue(null, "lang");
+@@ -127,7 +153,7 @@ public class FontListParser {
+             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
+             String tag = parser.getName();
+             if (tag.equals("font")) {
+-                fonts.add(readFont(parser));
++                fonts.add(readFont(parser, dirPath));
+             } else {
+                 skip(parser);
+             }
+@@ -139,7 +165,7 @@ public class FontListParser {
+     private static final Pattern FILENAME_WHITESPACE_PATTERN =
+             Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
+-    private static Font readFont(XmlPullParser parser)
++    private static Font readFont(XmlPullParser parser, String dirPath)
+             throws XmlPullParserException, IOException {
+         String indexStr = parser.getAttributeValue(null, "index");
+         int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
+@@ -160,7 +186,7 @@ public class FontListParser {
+                 skip(parser);
+             }
+         }
+-        String fullFilename = "/system/fonts/" +
++        String fullFilename = dirPath + File.separatorChar +
+                 FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
+         return new Font(fullFilename, index, axes, weight, isItalic);
+     }
+diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
+index 2886f0d..990c9bd 100644
+--- a/graphics/java/android/graphics/Typeface.java
++++ b/graphics/java/android/graphics/Typeface.java
+@@ -17,6 +17,7 @@
+ package android.graphics;
+ import android.content.res.AssetManager;
++import android.graphics.FontListParser.Family;
+ import android.util.Log;
+ import android.util.LongSparseArray;
+ import android.util.LruCache;
+@@ -75,6 +76,8 @@ public class Typeface {
+     static final String FONTS_CONFIG = "fonts.xml";
++    static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
++
+     /**
+      * @hide
+      */
+@@ -88,6 +91,13 @@ public class Typeface {
+     private int mStyle = 0;
++    // Typefaces that we can garbage collect when changing fonts, and so we don't break public APIs
++    private static Typeface DEFAULT_INTERNAL;
++    private static Typeface DEFAULT_BOLD_INTERNAL;
++    private static Typeface SANS_SERIF_INTERNAL;
++    private static Typeface SERIF_INTERNAL;
++    private static Typeface MONOSPACE_INTERNAL;
++
+     private static void setDefault(Typeface t) {
+         sDefaultTypeface = t;
+         nativeSetDefault(t.native_instance);
+@@ -263,7 +273,10 @@ public class Typeface {
+         for (int i = 0; i < families.length; i++) {
+             ptrArray[i] = families[i].mNativePtr;
+         }
+-        return new Typeface(nativeCreateFromArray(ptrArray));
++
++
++        Typeface typeface = new Typeface(nativeCreateFromArray(ptrArray));
++        return typeface;
+     }
+     /**
+@@ -318,6 +331,73 @@ public class Typeface {
+         return fontFamily;
+     }
++    /**
++     * Adds the family from src with the name familyName as a fallback font in dst
++     * @param src Source font config
++     * @param dst Destination font config
++     * @param familyName Name of family to add as a fallback
++     */
++    private static void addFallbackFontsForFamilyName(FontListParser.Config src,
++            FontListParser.Config dst, String familyName) {
++        for (Family srcFamily : src.families) {
++            if (familyName.equals(srcFamily.name)) {
++                // set the name to null so that it will be added as a fallback
++                srcFamily.name = null;
++                dst.families.add(srcFamily);
++                return;
++            }
++        }
++    }
++
++    /**
++     * Adds any font families in src that do not exist in dst
++     * @param src Source font config
++     * @param dst Destination font config
++     */
++    private static void addMissingFontFamilies(FontListParser.Config src,
++            FontListParser.Config dst) {
++        final int N = dst.families.size();
++        // add missing families
++        for (Family srcFamily : src.families) {
++            boolean addFamily = true;
++            for (int i = 0; i < N && addFamily; i++) {
++                final Family dstFamily = dst.families.get(i);
++                final String dstFamilyName = dstFamily.name;
++                if (dstFamilyName != null && dstFamilyName.equals(srcFamily.name)) {
++                    addFamily = false;
++                    break;
++                }
++            }
++            if (addFamily) {
++                dst.families.add(srcFamily);
++            }
++        }
++    }
++
++    /**
++     * Adds any aliases in src that do not exist in dst
++     * @param src Source font config
++     * @param dst Destination font config
++     */
++    private static void addMissingFontAliases(FontListParser.Config src,
++            FontListParser.Config dst) {
++        final int N = dst.aliases.size();
++        // add missing aliases
++        for (FontListParser.Alias alias : src.aliases) {
++            boolean addAlias = true;
++            for (int i = 0; i < N && addAlias; i++) {
++                final String dstAliasName = dst.aliases.get(i).name;
++                if (dstAliasName != null && dstAliasName.equals(alias.name)) {
++                    addAlias = false;
++                    break;
++                }
++            }
++            if (addAlias) {
++                dst.aliases.add(alias);
++            }
++        }
++    }
++
+     /*
+      * (non-Javadoc)
+      *
+@@ -326,10 +406,36 @@ public class Typeface {
+     private static void init() {
+         // Load font config and initialize Minikin state
+         File systemFontConfigLocation = getSystemFontConfigLocation();
+-        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
++        File themeFontConfigLocation = getThemeFontConfigLocation();
++
++        File systemConfigFile = new File(systemFontConfigLocation, FONTS_CONFIG);
++        File themeConfigFile = new File(themeFontConfigLocation, FONTS_CONFIG);
++        File configFile = null;
++        File fontDir;
++
++        if (themeConfigFile.exists()) {
++            configFile = themeConfigFile;
++            fontDir = getThemeFontDirLocation();
++        } else {
++            configFile = systemConfigFile;
++            fontDir = getSystemFontDirLocation();
++        }
++
+         try {
+-            FileInputStream fontsIn = new FileInputStream(configFilename);
+-            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
++            FontListParser.Config fontConfig = FontListParser.parse(configFile,
++                    fontDir.getAbsolutePath());
++            FontListParser.Config systemFontConfig = null;
++
++            // If the fonts are coming from a theme, we will need to make sure that we include
++            // any font families from the system fonts that the theme did not include.
++            // NOTE: All the system font families without names ALWAYS get added.
++            if (configFile == themeConfigFile) {
++                systemFontConfig = FontListParser.parse(systemConfigFile,
++                        getSystemFontDirLocation().getAbsolutePath());
++                addFallbackFontsForFamilyName(systemFontConfig, fontConfig, SANS_SERIF_FAMILY_NAME);
++                addMissingFontFamilies(systemFontConfig, fontConfig);
++                addMissingFontAliases(systemFontConfig, fontConfig);
++            }
+             Map<String, ByteBuffer> bufferForPath = new HashMap<String, ByteBuffer>();
+@@ -342,6 +448,7 @@ public class Typeface {
+                     familyList.add(makeFamilyFromParsed(f, bufferForPath));
+                 }
+             }
++
+             sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
+             setDefault(Typeface.createFromFamilies(sFallbackFonts));
+@@ -377,22 +484,53 @@ public class Typeface {
+             Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
+             // TODO: normal in non-Minikin case, remove or make error when Minikin-only
+         } catch (FileNotFoundException e) {
+-            Log.e(TAG, "Error opening " + configFilename, e);
++            Log.e(TAG, "Error opening " + configFile, e);
+         } catch (IOException e) {
+-            Log.e(TAG, "Error reading " + configFilename, e);
++            Log.e(TAG, "Error reading " + configFile, e);
+         } catch (XmlPullParserException e) {
+-            Log.e(TAG, "XML parse exception for " + configFilename, e);
++            Log.e(TAG, "XML parse exception for " + configFile, e);
+         }
+     }
++    /**
++     * Clears caches in java and skia.
++     * Skia will then reparse font config
++     * @hide
++     */
++    public static void recreateDefaults() {
++        sTypefaceCache.clear();
++        sSystemFontMap.clear();
++        init();
++
++        DEFAULT_INTERNAL = create((String) null, 0);
++        DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
++        SANS_SERIF_INTERNAL = create("sans-serif", 0);
++        SERIF_INTERNAL = create("serif", 0);
++        MONOSPACE_INTERNAL = create("monospace", 0);
++
++        DEFAULT.native_instance = DEFAULT_INTERNAL.native_instance;
++        DEFAULT_BOLD.native_instance = DEFAULT_BOLD_INTERNAL.native_instance;
++        SANS_SERIF.native_instance = SANS_SERIF_INTERNAL.native_instance;
++        SERIF.native_instance = SERIF_INTERNAL.native_instance;
++        MONOSPACE.native_instance = MONOSPACE_INTERNAL.native_instance;
++        sDefaults[2] = create((String) null, Typeface.ITALIC);
++        sDefaults[3] = create((String) null, Typeface.BOLD_ITALIC);
++    }
++
+     static {
+         init();
+         // Set up defaults and typefaces exposed in public API
+-        DEFAULT         = create((String) null, 0);
+-        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
+-        SANS_SERIF      = create("sans-serif", 0);
+-        SERIF           = create("serif", 0);
+-        MONOSPACE       = create("monospace", 0);
++        DEFAULT_INTERNAL         = create((String) null, 0);
++        DEFAULT_BOLD_INTERNAL    = create((String) null, Typeface.BOLD);
++        SANS_SERIF_INTERNAL      = create("sans-serif", 0);
++        SERIF_INTERNAL           = create("serif", 0);
++        MONOSPACE_INTERNAL       = create("monospace", 0);
++
++        DEFAULT         = new Typeface(DEFAULT_INTERNAL.native_instance);
++        DEFAULT_BOLD    = new Typeface(DEFAULT_BOLD_INTERNAL.native_instance);
++        SANS_SERIF      = new Typeface(SANS_SERIF_INTERNAL.native_instance);
++        SERIF           = new Typeface(SERIF_INTERNAL.native_instance);
++        MONOSPACE       = new Typeface(MONOSPACE_INTERNAL.native_instance);
+         sDefaults = new Typeface[] {
+             DEFAULT,
+@@ -407,6 +545,18 @@ public class Typeface {
+         return new File("/system/etc/");
+     }
++    private static File getSystemFontDirLocation() {
++        return new File("/system/fonts/");
++    }
++
++    private static File getThemeFontConfigLocation() {
++        return new File("/data/system/theme/fonts/");
++    }
++
++    private static File getThemeFontDirLocation() {
++        return new File("/data/system/theme/fonts/");
++    }
++
+     @Override
+     protected void finalize() throws Throwable {
+         try {
+diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
+index 2822dc9..ab010d4 100644
+--- a/services/core/java/com/android/server/am/ActivityManagerService.java
++++ b/services/core/java/com/android/server/am/ActivityManagerService.java
+@@ -512,6 +512,8 @@ public final class ActivityManagerService extends ActivityManagerNative
+     // as one line, but close enough for now.
+     static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
++    static final String PROP_REFRESH_THEME = "sys.refresh_theme";
++
+     // Access modes for handleIncomingUser.
+     static final int ALLOW_NON_FULL = 0;
+     static final int ALLOW_NON_FULL_IN_PROFILE = 1;
+@@ -3947,6 +3949,13 @@ public final class ActivityManagerService extends ActivityManagerNative
+                 mNativeDebuggingApp = null;
+             }
++            //Check if zygote should refresh its fonts
++            boolean refreshTheme = false;
++            if (SystemProperties.getBoolean(PROP_REFRESH_THEME, false)) {
++                SystemProperties.set(PROP_REFRESH_THEME, "false");
++                refreshTheme = true;
++            }
++
+             String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
+             if (requiredAbi == null) {
+                 requiredAbi = Build.SUPPORTED_ABIS[0];
+@@ -3971,7 +3980,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+             Process.ProcessStartResult startResult = Process.start(entryPoint,
+                     app.processName, uid, uid, gids, debugFlags, mountExternal,
+                     app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+-                    app.info.dataDir, entryPointArgs);
++                    app.info.dataDir, refreshTheme, entryPointArgs);
+             checkTime(startTime, "startProcess: returned from zygote!");
+             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch b/patches/frameworks/base/0026-N-Extras-AudioService-Allow-system-effect-sounds-to-.patch
new file mode 100644 (file)
index 0000000..d0bc5f5
--- /dev/null
@@ -0,0 +1,79 @@
+From f3f83a64481e2abdf561f7c42d7f2e7d5f32012b Mon Sep 17 00:00:00 2001
+From: Nicholas Chum <nicholaschum@gmail.com>
+Date: Sun, 17 Jul 2016 17:56:40 -0400
+Subject: [PATCH 26/38] N-Extras: AudioService: Allow system effect sounds to
+ be themed
+
+This commit checks whether there is a preexisting file in the themed
+directory "/data/system/theme/audio/ui/" and if so, change the base
+file paths for the sound. If the file does not exist in the theme
+directory, then use the default sounds.
+
+At the current moment, this will require a soft reboot to work.
+
+Change-Id: I7666c2bd259443ccec442bf6059786bea3dc069e
+---
+ .../com/android/server/audio/AudioService.java     | 26 +++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
+index cd766af..2e3d5a6 100644
+--- a/services/core/java/com/android/server/audio/AudioService.java
++++ b/services/core/java/com/android/server/audio/AudioService.java
+@@ -123,6 +123,7 @@ import com.android.server.pm.UserManagerService;
+ import org.xmlpull.v1.XmlPullParserException;
++import java.io.File;
+ import java.io.FileDescriptor;
+ import java.io.IOException;
+ import java.io.PrintWriter;
+@@ -281,6 +282,7 @@ public class AudioService extends IAudioService.Stub {
+     /* Sound effect file names  */
+     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
++    private static final String SOUND_EFFECTS_THEMED_PATH = "/data/system/theme/audio/ui/";
+     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
+     /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
+@@ -4679,9 +4681,16 @@ public class AudioService extends IAudioService.Stub {
+                         continue;
+                     }
+                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
+-                        String filePath = Environment.getRootDirectory()
+-                                + SOUND_EFFECTS_PATH
+-                                + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
++                        String filePath = "";
++                        File theme_file = new File(SOUND_EFFECTS_THEMED_PATH +
++                            SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]));
++                        if (theme_file.exists()) {
++                            filePath = theme_file.getAbsolutePath();
++                        } else {
++                            filePath = Environment.getRootDirectory()
++                                    + SOUND_EFFECTS_PATH
++                                    + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
++                        }
+                         int sampleId = mSoundPool.load(filePath, 0);
+                         if (sampleId <= 0) {
+                             Log.w(TAG, "Soundpool could not load file: "+filePath);
+@@ -4787,8 +4796,15 @@ public class AudioService extends IAudioService.Stub {
+                 } else {
+                     MediaPlayer mediaPlayer = new MediaPlayer();
+                     try {
+-                        String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
+-                                    SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
++                        String filePath = "";
++                        File theme_file = new File(SOUND_EFFECTS_THEMED_PATH +
++                                    SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]));
++                        if (theme_file.exists()) {
++                            filePath = theme_file.getAbsolutePath();
++                        } else {
++                            filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
++                                        SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
++                        }
+                         mediaPlayer.setDataSource(filePath);
+                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
+                         mediaPlayer.prepare();
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch b/patches/frameworks/base/0027-OMS7-N-ApplicationsState-add-filter-for-Substratum-o.patch
new file mode 100644 (file)
index 0000000..8e1dad6
--- /dev/null
@@ -0,0 +1,53 @@
+From 0b5d2c23c6f07c09a0181c76cc83cbb61da4d495 Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Mon, 4 Jul 2016 06:25:15 +0300
+Subject: [PATCH 27/38] OMS7-N: ApplicationsState: add filter for Substratum
+ overlays [1/2]
+
+This commit allows the framework to handle the filtering of the
+overlays found for OMS.
+
+Change-Id: I7646115e8f73494d726728fac58cc47aafd69d5d
+---
+ .../settingslib/applications/ApplicationsState.java     | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+index f0ec107..6fecd40 100644
+--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
++++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+@@ -137,9 +137,11 @@ public class ApplicationsState {
+         // Only the owner can see all apps.
+         mAdminRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
+                 PackageManager.GET_DISABLED_COMPONENTS |
+-                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
++                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
++                PackageManager.GET_META_DATA;
+         mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
+-                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
++                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
++                PackageManager.GET_META_DATA;
+         /**
+          * This is a trick to prevent the foreground thread from being delayed.
+@@ -1312,6 +1314,17 @@ public class ApplicationsState {
+         }
+     };
++    public static final AppFilter FILTER_SUBSTRATUM = new AppFilter() {
++        public void init() {
++        }
++
++        @Override
++        public boolean filterApp(AppEntry entry) {
++            return !((entry.info.metaData != null) &&
++                    (entry.info.metaData.getString("Substratum_Parent") != null));
++        }
++    };
++
+     public static final AppFilter FILTER_WORK = new AppFilter() {
+         private int mCurrentUser;
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch b/patches/frameworks/base/0028-OMS7-N-ApplicationsState-add-filter-for-Substratum-i.patch
new file mode 100644 (file)
index 0000000..8734985
--- /dev/null
@@ -0,0 +1,41 @@
+From db55a4020f8942389b3862ddb7442c5f50d62f15 Mon Sep 17 00:00:00 2001
+From: Kuba Schenk <abukcz@gmail.com>
+Date: Thu, 1 Dec 2016 21:48:26 +0100
+Subject: [PATCH 28/38] OMS7-N: ApplicationsState: add filter for Substratum
+ icon overlays [1/2]
+
+This commit allows the framework to handle the filtering of the icon overlays found for OMS.
+
+Base this off the work from @KreAch3R
+
+Change-Id: I594c993977733e67f566ac65df50ad2e1bbdbdd3
+(cherry picked from commit 4d682464550f71e72e491934c78b8a42fdfc0348)
+---
+ .../android/settingslib/applications/ApplicationsState.java   | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+index 6fecd40..d3a6e21 100644
+--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
++++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+@@ -1325,6 +1325,17 @@ public class ApplicationsState {
+         }
+     };
++    public static final AppFilter FILTER_SUBSTRATUM_ICONS = new AppFilter() {
++        public void init() {
++        }
++
++        @Override
++        public boolean filterApp(AppEntry entry) {
++            return !((entry.info.metaData != null) &&
++                    (entry.info.metaData.getString("Substratum_IconPack") != null));
++        }
++    };
++
+     public static final AppFilter FILTER_WORK = new AppFilter() {
+         private int mCurrentUser;
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0029-Themes-Expose-QS-battery.patch b/patches/frameworks/base/0029-Themes-Expose-QS-battery.patch
new file mode 100644 (file)
index 0000000..fe79dc3
--- /dev/null
@@ -0,0 +1,55 @@
+From da38273a4dc66c1f259b89430ffcb3c58db0e39c Mon Sep 17 00:00:00 2001
+From: Abdulwahab Isam <abdoi94.iq@gmail.com>
+Date: Fri, 7 Oct 2016 08:30:11 +0300
+Subject: [PATCH 29/38] Themes: Expose QS battery
+
+This is needed for white themes like Belo. Should function the same with dark themes as well.
+
+Change-Id: I65e3f777a2a2605a06260705f92f8617407d9005
+---
+ packages/SystemUI/res/layout/battery_detail.xml | 6 +++---
+ packages/SystemUI/res/values/projekt_colors.xml | 6 ++++++
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
+index 8abfcf6..af3acdc 100644
+--- a/packages/SystemUI/res/layout/battery_detail.xml
++++ b/packages/SystemUI/res/layout/battery_detail.xml
+@@ -27,7 +27,7 @@
+         android:layout_height="wrap_content"
+         android:paddingStart="16dp"
+         android:textAppearance="?android:attr/textAppearanceSmall"
+-        android:textColor="?android:attr/colorAccent" />
++        android:textColor="@color/qs_battery_text_color" />
+     <com.android.systemui.ResizingSpace
+         android:layout_width="match_parent"
+@@ -40,8 +40,8 @@
+         android:layout_marginStart="16dp"
+         android:layout_marginEnd="24dp"
+         systemui:sideLabels="@array/battery_labels"
+-        android:colorAccent="?android:attr/colorAccent"
+-        systemui:textColor="#66FFFFFF" />
++        android:colorAccent="@color/qs_battery_accent"
++        systemui:textColor="@color/qs_battery_graph_text_color" />
+     <com.android.systemui.ResizingSpace
+         android:layout_width="match_parent"
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+index 0f89199..83b8524 100644
+--- a/packages/SystemUI/res/values/projekt_colors.xml
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -24,4 +24,10 @@
+     <color name="qs_alarm_status_text_color">#64ffffff</color>
+     <!-- QS edit page toolbar text color -->
+     <color name="qs_edit_toolbar_text_color">#FFFFFF</color>
++    <!-- QS battery % text color -->
++    <color name="qs_battery_text_color">@*android:color/accent_device_default_light</color>
++    <!-- QS battery graph text color -->
++    <color name="qs_battery_graph_text_color">#66FFFFFF</color>
++    <!-- QS battery accent color -->
++    <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch b/patches/frameworks/base/0030-OMS-Introduce-MODIFY_OVERLAYS-permission-for-user-ap.patch
new file mode 100644 (file)
index 0000000..6756897
--- /dev/null
@@ -0,0 +1,120 @@
+From 4045dd2c0cbb895e8d430a9388d33b5596a9fd2b Mon Sep 17 00:00:00 2001
+From: bigrushdog <randall.rushing@gmail.com>
+Date: Mon, 19 Dec 2016 04:33:31 -0800
+Subject: [PATCH 30/38] OMS: Introduce MODIFY_OVERLAYS permission for user apps
+
+This permission will grant the app read and write permissions
+to access OverlayManagerService. If caller does not posess
+this permissions, OMS falls back to default permission checks
+
+Change-Id: Ib6b10b516577f338aee31e759bfd16278f902c20
+(cherry picked from commit 8e59c96513c573a4912492c005b076cb2a972332)
+---
+ core/res/AndroidManifest.xml                       |  6 +++++
+ core/res/res/values/strings.xml                    |  5 +++++
+ .../android/server/om/OverlayManagerService.java   | 26 +++++++++++++++-------
+ 3 files changed, 29 insertions(+), 8 deletions(-)
+
+diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
+index 986be28..abed0df 100644
+--- a/core/res/AndroidManifest.xml
++++ b/core/res/AndroidManifest.xml
+@@ -3160,6 +3160,12 @@
+     <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
+                 android:protectionLevel="signature|privileged" />
++    <!-- Allows an application to make calls to OverlayManagerService.-->
++    <permission android:name="android.permission.MODIFY_OVERLAYS"
++        android:label="@string/permlab_modifyOverlays"
++        android:description="@string/permdesc_modifyOverlays"
++        android:protectionLevel="normal" />
++
+     <application android:process="system"
+                  android:persistent="true"
+                  android:hasCode="false"
+diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
+index 8f5f8cf..8313d5d 100644
+--- a/core/res/res/values/strings.xml
++++ b/core/res/res/values/strings.xml
+@@ -1411,6 +1411,11 @@
+     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+     <string name="permdesc_access_notification_policy">Allows the app to read and write Do Not Disturb configuration.</string>
++    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
++    <string name="permlab_modifyOverlays">modify theme overlays</string>
++    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
++    <string name="permdesc_modifyOverlays">Allows the app to make modifications to theme overlays using OverlayManagerService</string>
++
+     <!-- Policy administration -->
+     <!-- Title of policy access to limiting the user's password choices -->
+diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
+index deb9046..e205ce1 100644
+--- a/services/core/java/com/android/server/om/OverlayManagerService.java
++++ b/services/core/java/com/android/server/om/OverlayManagerService.java
+@@ -36,6 +36,7 @@ import android.content.om.IOverlayManager;
+ import android.content.om.OverlayInfo;
+ import android.content.pm.IPackageManager;
+ import android.content.pm.PackageInfo;
++import android.content.pm.PackageManager;
+ import android.content.pm.PackageManagerInternal;
+ import android.content.pm.UserInfo;
+ import android.net.Uri;
+@@ -114,7 +115,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
+  *     the caller runs as, or if the caller holds the
+  *     INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
+  *     caller is granted read-access and additionaly holds the
+- *     CHANGE_CONFIGURATION permission.</li>
++ *     CHANGE_CONFIGURATION permission. Additionally, read and write access
++ *     is granted by the MODIFY_OVERLAYS permission.</li>
+  * </ul>
+  *
+  * <p>The AIDL interface works with String package names, int user IDs, and
+@@ -549,19 +551,24 @@ public final class OverlayManagerService extends SystemService {
+         /**
+          * Ensure that the caller has permission to interact with the given userId.
+          * If the calling user is not the same as the provided user, the caller needs
+-         * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
++         * to hold the INTERACT_ACROSS_USERS_FULL permission or MODIFY_OVERLAYS permission (or be system uid or
+          * root).
+          *
+          * @param userId the user to interact with
+          * @param message message for any SecurityException
+          */
+         private int handleIncomingUser(final int userId, @NonNull final String message) {
+-            return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+-                    Binder.getCallingUid(), userId, false, true, message, null);
++            if (getContext().checkCallingOrSelfPermission(
++                    android.Manifest.permission.MODIFY_OVERLAYS) == PackageManager.PERMISSION_GRANTED) {
++                return userId;
++            } else {
++                return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
++                        Binder.getCallingUid(), userId, false, true, message, null);
++            }
+         }
+         /**
+-         * Enforce that the caller holds the CHANGE_CONFIGURATION permission (or is
++         * Enforce that the caller holds the CHANGE_CONFIGURATION permission or MODIFY_OVERLAYS permission (or is
+          * system or root).
+          *
+          * @param message used as message if SecurityException is thrown
+@@ -570,9 +577,12 @@ public final class OverlayManagerService extends SystemService {
+         private void enforceChangeConfigurationPermission(@NonNull final String message) {
+             final int callingUid = Binder.getCallingUid();
+-            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+-                getContext().enforceCallingOrSelfPermission(
+-                        android.Manifest.permission.CHANGE_CONFIGURATION, message);
++            if (getContext().checkCallingOrSelfPermission(
++                    android.Manifest.permission.MODIFY_OVERLAYS) != PackageManager.PERMISSION_GRANTED) {
++                if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
++                    getContext().enforceCallingOrSelfPermission(
++                            android.Manifest.permission.CHANGE_CONFIGURATION, message);
++                }
+             }
+         }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch b/patches/frameworks/base/0031-SystemUI-Expose-switch-bar-title.patch
new file mode 100644 (file)
index 0000000..91c2989
--- /dev/null
@@ -0,0 +1,61 @@
+From ee6b990018d29a124adc51e273d1fe0cf5fa66bc Mon Sep 17 00:00:00 2001
+From: daveyannihilation <daveyannihilation@hotmail.com>
+Date: Sun, 1 Jan 2017 01:47:53 -0700
+Subject: [PATCH 31/38] SystemUI: Expose switch bar title
+
+This is needed for the power notifications switchbar in SystemUI Tuner, amongst other things.
+
+Change-Id: I86f04840c2be46519509556b8d0061cefe26f631
+---
+ packages/SystemUI/res/layout/switch_bar.xml     |  3 +--
+ packages/SystemUI/res/values/projekt_styles.xml | 24 ++++++++++++++++++++++++
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+ create mode 100644 packages/SystemUI/res/values/projekt_styles.xml
+
+diff --git a/packages/SystemUI/res/layout/switch_bar.xml b/packages/SystemUI/res/layout/switch_bar.xml
+index 41cdb78..344c5aa 100644
+--- a/packages/SystemUI/res/layout/switch_bar.xml
++++ b/packages/SystemUI/res/layout/switch_bar.xml
+@@ -33,8 +33,7 @@
+         android:paddingStart="48dp"
+         android:maxLines="2"
+         android:ellipsize="end"
+-        android:textAppearance="@android:style/TextAppearance.Material.Title"
+-        android:textColor="?android:attr/textColorPrimaryInverse"
++        android:textAppearance="@style/TextAppearance.SwitchBar"
+         android:textAlignment="viewStart"
+         android:text="@string/switch_bar_on" />
+diff --git a/packages/SystemUI/res/values/projekt_styles.xml b/packages/SystemUI/res/values/projekt_styles.xml
+new file mode 100644
+index 0000000..f49834b
+--- /dev/null
++++ b/packages/SystemUI/res/values/projekt_styles.xml
+@@ -0,0 +1,24 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Projekt Substratum
++
++    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>
++    <!-- Switch bar text appearance -->
++    <style name="TextAppearance.SwitchBar" parent="@android:style/TextAppearance.Material.Title">
++        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
++    </style>
++</resources>
++
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch b/patches/frameworks/base/0032-Themes-Expose-manifest-styles-for-themes.patch
new file mode 100644 (file)
index 0000000..a682146
--- /dev/null
@@ -0,0 +1,151 @@
+From b865d57f51ef8545a434dfdfee32055954ce952b Mon Sep 17 00:00:00 2001
+From: Bryan Owens <djbryan3540@gmail.com>
+Date: Fri, 6 Jan 2017 21:12:15 +0800
+Subject: [PATCH 32/38] Themes: Expose manifest styles for themes
+
+Change-Id: Ie3a4fdead4f4fa1c121018b38de1c86a05bbcff2
+---
+ core/res/AndroidManifest.xml           | 20 ++++++++---------
+ core/res/res/values/projekt_styles.xml | 41 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 51 insertions(+), 10 deletions(-)
+ create mode 100644 core/res/res/values/projekt_styles.xml
+
+diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
+index abed0df..6ac87ca 100644
+--- a/core/res/AndroidManifest.xml
++++ b/core/res/AndroidManifest.xml
+@@ -3212,7 +3212,7 @@
+                 android:label="@string/managed_profile_label">
+         </activity-alias>
+         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
++                android:theme="@style/HeavyWeightSwitcherActivityTheme"
+                 android:label="@string/heavy_weight_switcher_title"
+                 android:finishOnCloseSystemDialogs="true"
+                 android:excludeFromRecents="true"
+@@ -3245,7 +3245,7 @@
+         <activity android:name="android.accounts.ChooseAccountActivity"
+                 android:excludeFromRecents="true"
+                 android:exported="true"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
++                android:theme="@style/ChooseAccountActivityTheme"
+                 android:label="@string/choose_account_label"
+                 android:process=":ui">
+         </activity>
+@@ -3253,14 +3253,14 @@
+         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
+                 android:excludeFromRecents="true"
+                 android:exported="true"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
++                android:theme="@style/ChooseTypeAndAccountActivityTheme"
+                 android:label="@string/choose_account_label"
+                 android:process=":ui">
+         </activity>
+         <activity android:name="android.accounts.ChooseAccountTypeActivity"
+                 android:excludeFromRecents="true"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
++                android:theme="@style/ChooseAccountTypeActivityTheme"
+                 android:label="@string/choose_account_label"
+                 android:process=":ui">
+         </activity>
+@@ -3268,19 +3268,19 @@
+         <activity android:name="android.accounts.CantAddAccountActivity"
+                 android:excludeFromRecents="true"
+                 android:exported="true"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
++                android:theme="@style/CantAddAccountActivityTheme"
+                 android:process=":ui">
+         </activity>
+         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
+                 android:excludeFromRecents="true"
+                 android:exported="true"
+-                android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
++                android:theme="@style/GrantCredentialsPermissionActivityTheme"
+                 android:process=":ui">
+         </activity>
+         <activity android:name="android.content.SyncActivityTooManyDeletes"
+-               android:theme="@style/Theme.DeviceDefault.Light.Dialog"
++               android:theme="@style/SyncActivityTooManyDeletesTheme"
+                android:label="@string/sync_too_many_deletes"
+                android:process=":ui">
+         </activity>
+@@ -3300,7 +3300,7 @@
+         </activity>
+         <activity android:name="com.android.internal.app.NetInitiatedActivity"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
++                android:theme="@style/NetInitiatedActivityTheme"
+                 android:excludeFromRecents="true"
+                 android:process=":ui">
+         </activity>
+@@ -3321,7 +3321,7 @@
+         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
+                 android:excludeFromRecents="true"
+                 android:process=":ui"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
++                android:theme="@style/ConfirmUserCreationActivityTheme">
+             <intent-filter android:priority="1000">
+                 <action android:name="android.os.action.CREATE_USER" />
+                 <category android:name="android.intent.category.DEFAULT" />
+@@ -3329,7 +3329,7 @@
+         </activity>
+         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
+-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
++                android:theme="@style/UnlaunchableAppActivityTheme"
+                 android:excludeFromRecents="true"
+                 android:process=":ui">
+         </activity>
+diff --git a/core/res/res/values/projekt_styles.xml b/core/res/res/values/projekt_styles.xml
+new file mode 100644
+index 0000000..e5fe635
+--- /dev/null
++++ b/core/res/res/values/projekt_styles.xml
+@@ -0,0 +1,41 @@
++<?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>
++
++    <!-- Exposed manifest styles -->
++
++    <style name="HeavyWeightSwitcherActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
++
++    <style name="ChooseAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
++
++    <style name="ChooseTypeAndAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
++
++    <style name="ChooseAccountTypeActivityTheme" parent="Theme.DeviceDefault.Light.Dialog" />
++
++    <style name="CantAddAccountActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
++
++    <style name="GrantCredentialsPermissionActivityTheme" parent="Theme.DeviceDefault.Light.DialogWhenLarge" />
++
++    <style name="SyncActivityTooManyDeletesTheme" parent="Theme.DeviceDefault.Light.Dialog" />
++
++    <style name="NetInitiatedActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
++
++    <style name="ConfirmUserCreationActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
++
++    <style name="UnlaunchableAppActivityTheme" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
++
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch b/patches/frameworks/base/0033-OMS-StrictMode-and-files-under-data-system-theme.patch
new file mode 100644 (file)
index 0000000..8be7278
--- /dev/null
@@ -0,0 +1,40 @@
+From a33286e7a15b13bf4d8ac2aa9a779b8b888c9d2a Mon Sep 17 00:00:00 2001
+From: mickybart <mickybart@pygoscelis.org>
+Date: Sat, 19 Nov 2016 19:05:05 -0500
+Subject: [PATCH 33/38] OMS: StrictMode and files under /data/system/theme/
+
+Themes are using /data/system/theme/ to push some files like LowBattery.ogg (audio notification)
+When the device battery trigger the low battery state, the sound is not played due
+to StrictMode and SystemUI is crashing.
+
+So we need that StrictMode authorize files under /system OR /data/system/theme
+
+Logcat of the issue:
+
+E AndroidRuntime: Caused by: android.os.FileUriExposedException: file:///data/system/theme/audio/ui/LowBattery.ogg exposed beyond app through Notification.sound
+E AndroidRuntime:        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
+E AndroidRuntime:        at android.net.Uri.checkFileUriExposed(Uri.java:2346)
+E AndroidRuntime:        at android.app.NotificationManager.notifyAsUser(NotificationManager.java:300)
+
+Change-Id: I154dc4280de8eaf891772a9632283e9f547f5718
+---
+ core/java/android/net/Uri.java | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
+index 67378bd..4fb189e 100644
+--- a/core/java/android/net/Uri.java
++++ b/core/java/android/net/Uri.java
+@@ -2342,7 +2342,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
+      * @hide
+      */
+     public void checkFileUriExposed(String location) {
+-        if ("file".equals(getScheme()) && !getPath().startsWith("/system/")) {
++        if ("file".equals(getScheme()) && !(getPath().startsWith("/system/")
++                || getPath().startsWith("/data/system/theme/"))) {
+             StrictMode.onFileUriExposed(this, location);
+         }
+     }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch b/patches/frameworks/base/0034-doze-allow-grayscale-even-if-invert-boolean-is-false.patch
new file mode 100644 (file)
index 0000000..30f3445
--- /dev/null
@@ -0,0 +1,45 @@
+From 82244aeb8e03cec7e5cbbcd89fef918ea3d151d2 Mon Sep 17 00:00:00 2001
+From: Daniel Koman <dankoman30@gmail.com>
+Date: Wed, 28 Sep 2016 15:28:26 +0200
+Subject: [PATCH 34/38] doze: allow grayscale even if invert boolean is false
+
+for dark themes, we are setting the config boolean for inverting
+    doze notifications to false.  in addition to preventing
+    color inversion, this was also preventing the notification
+    from grayscaling.  as a result, on dark themes (boolean false), we
+    were seeing color icons on doze notifications.  this commit fixes
+    the grayscaling, and brings back the very aesthetically pleasing
+    (imo) grayscale-to-color fade-in for the notifications' app icons.
+
+Change-Id: Ifc5efbccbeb02910684b76793721b10f1d64f870
+---
+ packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+index 605f381..16d46c0 100644
+--- a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
++++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
+@@ -92,7 +92,7 @@ public class ViewInvertHelper {
+     }
+     public void update(boolean invert) {
+-        if (invert && mThemeInvert) {
++        if (invert) {
+             updateInvertPaint(1f);
+             for (int i = 0; i < mTargets.size(); i++) {
+                 mTargets.get(i).setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+@@ -115,7 +115,9 @@ public class ViewInvertHelper {
+         mMatrix.set(invert);
+         mGrayscaleMatrix.setSaturation(1 - intensity);
+         mMatrix.preConcat(mGrayscaleMatrix);
+-        mDarkPaint.setColorFilter(new ColorMatrixColorFilter(mMatrix));
++        mDarkPaint.setColorFilter(new ColorMatrixColorFilter(
++                mThemeInvert ? mMatrix : mGrayscaleMatrix));
++
+     }
+     public void setInverted(boolean invert, boolean fade, long delay) {
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0035-Expose-external-qs-tile-tint-color.patch b/patches/frameworks/base/0035-Expose-external-qs-tile-tint-color.patch
new file mode 100644 (file)
index 0000000..7bc7c43
--- /dev/null
@@ -0,0 +1,42 @@
+From a71d0e0ea46b7d910dea2f9c0eafbab2b1e3ef24 Mon Sep 17 00:00:00 2001
+From: Alex Cruz <mazdarider23@gmail.com>
+Date: Tue, 24 Jan 2017 11:14:46 +0100
+Subject: [PATCH 35/38] Expose external qs tile tint color
+
+This should allow themers to get around issues like this (see pic below)
+
+https://i.imgur.com/cG2OzRT.jpg
+
+Change-Id: If6dbf9ab29f8007d85a3c45524b1cf4ba1b032fb
+---
+ packages/SystemUI/res/values/projekt_colors.xml                         | 2 ++
+ .../SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+index 83b8524..e31d124 100644
+--- a/packages/SystemUI/res/values/projekt_colors.xml
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -30,4 +30,6 @@
+     <color name="qs_battery_graph_text_color">#66FFFFFF</color>
+     <!-- QS battery accent color -->
+     <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
++    <!-- External QS tile tint color -->
++    <color name="external_qs_tile_tint_color">@android:color/white</color>
+ </resources>
+diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+index 0cd6490..6fabc61 100644
+--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
++++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+@@ -177,7 +177,7 @@ public class TileQueryHelper {
+                     continue;
+                 }
+                 icon.mutate();
+-                icon.setTint(mContext.getColor(android.R.color.white));
++                icon.setTint(mContext.getColor(R.color.external_qs_tile_tint_color));
+                 CharSequence label = info.serviceInfo.loadLabel(pm);
+                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
+             }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch b/patches/frameworks/base/0036-graphics-ADB-N-icon-compatible-with-OMS7.patch
new file mode 100644 (file)
index 0000000..c3b926f
--- /dev/null
@@ -0,0 +1,45 @@
+From cd5423a1a675a6ac3986ac9960a6c9db8a386b0b Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Thu, 2 Feb 2017 01:52:27 +0200
+Subject: [PATCH 36/38] graphics: ADB "N" icon compatible with OMS7
+
+It's the same problem as the booleans again. This time, it affected the adb "N" icon in the statusbar.
+This commit should fix this.
+
+After: http://i.imgur.com/RPh6WKK.jpg
+
+Previous commits on the same matter:
+OMS7 introduced this fine piece of code: https://github.com/SubstratumResources/platform_frameworks_base/blob/n-oms7/core/java/android/app/ResourcesManager.java#L897..#L904
+
+// Resources.getSystem Resources are created on request and aren't tracked by
+// mResourceReferences.
+//
+// If overlays targeting "android" are to be used, we must create the system
+// resources regardless of whether they already exist, since otherwise the
+// information on what overlays to use would be lost. This is wasteful for most
+// applications, so limit this operation to the system user only. (This means
+// Resources.getSystem() will *not* use overlays for applications.)
+
+Replaced deprecated Resources.getSystem() with compatible method.
+
+Change-Id: Ibab2ce1571360a9e03043d1bf3144c89e54e1947
+---
+ graphics/java/android/graphics/drawable/Icon.java | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
+index 2b950d3..fb26bee 100644
+--- a/graphics/java/android/graphics/drawable/Icon.java
++++ b/graphics/java/android/graphics/drawable/Icon.java
+@@ -294,7 +294,7 @@ public final class Icon implements Parcelable {
+                         resPackage = context.getPackageName();
+                     }
+                     if ("android".equals(resPackage)) {
+-                        mObj1 = Resources.getSystem();
++                        mObj1 = context.getResources();
+                     } else {
+                         final PackageManager pm = context.getPackageManager();
+                         try {
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch b/patches/frameworks/base/0037-Set-external-QS-tiles-tint-mode-to-SRC_ATOP.patch
new file mode 100644 (file)
index 0000000..347da96
--- /dev/null
@@ -0,0 +1,43 @@
+From 1a4d5be7f78b87480be19243ae88e543a1b9db58 Mon Sep 17 00:00:00 2001
+From: Alex Cruz <mazdarider23@gmail.com>
+Date: Sat, 4 Feb 2017 14:13:26 +0100
+Subject: [PATCH 37/38] Set external QS tiles tint mode to SRC_ATOP
+
+While the external qs tile tint color was exposed, we had the same problem
+we had with the external icons in Settings which is if a themer set the color
+to transparent, they were SOL.
+
+This mirrors what @iskandar1023 did in the commit below
+http://review.projektsubstratum.com/#/c/286/
+
+Before - https://i.imgur.com/trpefmZ.png
+After - https://i.imgur.com/ugAqrju.png
+
+Change-Id: I6d577573dd494d61a3e87abebd919b02a481db56
+---
+ .../SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+index 6fabc61..dbdb614 100644
+--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
++++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+@@ -23,6 +23,7 @@ import android.content.Context;
+ import android.content.Intent;
+ import android.content.pm.PackageManager;
+ import android.content.pm.ResolveInfo;
++import android.graphics.PorterDuff.Mode;
+ import android.graphics.drawable.Drawable;
+ import android.os.AsyncTask;
+ import android.os.Handler;
+@@ -178,6 +179,7 @@ public class TileQueryHelper {
+                 }
+                 icon.mutate();
+                 icon.setTint(mContext.getColor(R.color.external_qs_tile_tint_color));
++                icon.setTintMode(Mode.SRC_ATOP);
+                 CharSequence label = info.serviceInfo.loadLabel(pm);
+                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
+             }
+-- 
+2.9.3
+
diff --git a/patches/frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch b/patches/frameworks/base/0038-Themes-Expose-Keyguard-affordance-circle-background.patch
new file mode 100644 (file)
index 0000000..9abb843
--- /dev/null
@@ -0,0 +1,38 @@
+From c06669d9a78ed88300a59d9cb1e6f9555086e569 Mon Sep 17 00:00:00 2001
+From: Branden M <wasabi.dev@gmail.com>
+Date: Wed, 1 Feb 2017 22:22:45 -0600
+Subject: [PATCH 38/38] Themes: Expose Keyguard affordance circle background
+
+Change-Id: Id4a078cdbc944fa0c0736103045a0382d49ecb80
+---
+ packages/SystemUI/res/values/projekt_colors.xml                         | 2 ++
+ .../src/com/android/systemui/statusbar/KeyguardAffordanceView.java      | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/packages/SystemUI/res/values/projekt_colors.xml b/packages/SystemUI/res/values/projekt_colors.xml
+index e31d124..e8f8e50 100644
+--- a/packages/SystemUI/res/values/projekt_colors.xml
++++ b/packages/SystemUI/res/values/projekt_colors.xml
+@@ -32,4 +32,6 @@
+     <color name="qs_battery_accent">@*android:color/accent_device_default_light</color>
+     <!-- External QS tile tint color -->
+     <color name="external_qs_tile_tint_color">@android:color/white</color>
++    <!-- Keyguard affordance circle background -->
++    <color name="keyguard_affordance_circle_background">@android:color/white</color>
+ </resources>
+diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+index b94df1d..3d661b7 100644
+--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
++++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+@@ -131,7 +131,7 @@ public class KeyguardAffordanceView extends ImageView implements Palette.Palette
+         super(context, attrs, defStyleAttr, defStyleRes);
+         mCirclePaint = new Paint();
+         mCirclePaint.setAntiAlias(true);
+-        mCircleColor = 0xffffffff;
++        mCircleColor = mContext.getResources().getColor(R.color.keyguard_affordance_circle_background);
+         mCirclePaint.setColor(mCircleColor);
+         mNormalColor = 0xffffffff;
+-- 
+2.9.3
+
diff --git a/patches/frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch b/patches/frameworks/native/0001-OMS-N-installd-add-command-rmidmap.patch
new file mode 100644 (file)
index 0000000..ec1ad89
--- /dev/null
@@ -0,0 +1,87 @@
+From 70dc365c2877d443aebb7da11f061fa3d69dd2a4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Tue, 15 Dec 2015 14:02:30 +0100
+Subject: [PATCH] OMS-N: installd: add command 'rmidmap'
+
+Add an installd command to remove an idmap file. This is the inverse of
+the 'idmap' command and is intended for clean-up once an idmap file is
+no longer needed because an APK was removed, etc.
+
+This commit depends on a corresponding commit in frameworks/base
+(with the same Change-Id).
+
+Bug: 31052947
+
+Change-Id: Iae19a519803f0c172b02a32faa283ef36f43863c
+---
+ cmds/installd/commands.cpp | 16 ++++++++++++++++
+ cmds/installd/commands.h   |  1 +
+ cmds/installd/installd.cpp |  6 ++++++
+ 3 files changed, 23 insertions(+)
+
+diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
+index cadcd1e..0b25da1 100644
+--- a/cmds/installd/commands.cpp
++++ b/cmds/installd/commands.cpp
+@@ -2047,6 +2047,22 @@ fail:
+     return -1;
+ }
++int rm_idmap(const char *overlay_apk)
++{
++    char idmap_path[PATH_MAX];
++
++    if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
++                idmap_path, sizeof(idmap_path)) == -1) {
++        ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
++        return -1;
++    }
++    if (unlink(idmap_path) < 0) {
++        ALOGE("couldn't unlink idmap file %s\n", idmap_path);
++        return -1;
++    }
++    return 0;
++}
++
+ int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
+         appid_t appid, const char* seinfo) {
+     int res = 0;
+diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
+index ba27517..2da80dd 100644
+--- a/cmds/installd/commands.h
++++ b/cmds/installd/commands.h
+@@ -76,6 +76,7 @@ int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
+ int mark_boot_complete(const char *instruction_set);
+ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
+ int idmap(const char *target_path, const char *overlay_path, uid_t uid);
++int rm_idmap(const char *overlay_path);
+ int create_oat_dir(const char* oat_dir, const char *instruction_set);
+ int rm_package_dir(const char* apk_path);
+ int clear_app_profiles(const char* pkgname);
+diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
+index 8f883db..93388ce 100644
+--- a/cmds/installd/installd.cpp
++++ b/cmds/installd/installd.cpp
+@@ -383,6 +383,11 @@ static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+     return idmap(arg[0], arg[1], atoi(arg[2]));
+ }
++static int do_rm_idmap(char **arg, char reply[REPLY_MAX] __unused)
++{
++    return rm_idmap(arg[0]);
++}
++
+ static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+ {
+     /* oat_dir, instruction_set */
+@@ -450,6 +455,7 @@ struct cmdinfo cmds[] = {
+     { "freecache",            2, do_free_cache },
+     { "linklib",              4, do_linklib },
+     { "idmap",                3, do_idmap },
++    { "rmidmap",              1, do_rm_idmap },
+     { "createoatdir",         2, do_create_oat_dir },
+     { "rmpackagedir",         1, do_rm_package_dir },
+     { "clear_app_profiles",   1, do_clear_app_profiles },
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch b/patches/packages/apps/Contacts/0001-Themes-Expose-hardcoded-layout-and-styles-colors.patch
new file mode 100644 (file)
index 0000000..ac7993f
--- /dev/null
@@ -0,0 +1,188 @@
+From 136516428b86786251449bf2e008d126d9690691 Mon Sep 17 00:00:00 2001
+From: beanstown106 <nbenis106@gmail.com>
+Date: Fri, 20 Nov 2015 17:27:43 -0500
+Subject: [PATCH] Themes: Expose hardcoded layout and styles colors
+
+Exposed text and background colors for themes to be compatible with themeable
+google dialer. Split PeopleTheme in styles.
+
+Change-Id: I4ca0347470333508e399bfae7ed5291a1a704410
+---
+ res/layout/confirm_add_detail_activity.xml |  6 +++---
+ res/layout/editor_account_header.xml       |  2 +-
+ res/values/projekt_colors.xml              | 29 +++++++++++++++++++++++++++++
+ res/values/styles.xml                      | 27 ++++++++++++++++-----------
+ 4 files changed, 49 insertions(+), 15 deletions(-)
+ create mode 100644 res/values/projekt_colors.xml
+
+diff --git a/res/layout/confirm_add_detail_activity.xml b/res/layout/confirm_add_detail_activity.xml
+index 1fa6236..eb54b8a 100644
+--- a/res/layout/confirm_add_detail_activity.xml
++++ b/res/layout/confirm_add_detail_activity.xml
+@@ -55,7 +55,7 @@
+             android:layout_alignRight="@id/photo"
+             android:layout_alignStart="@id/photo"
+             android:layout_alignEnd="@id/photo"
+-            android:background="#7F000000" />
++            android:background="@color/photo_text_bar_bg" />
+         <ImageButton
+             android:id="@+id/open_details_button"
+@@ -92,7 +92,7 @@
+                 android:paddingLeft="8dip"
+                 android:paddingStart="8dip"
+                 android:gravity="center_vertical"
+-                android:textColor="@android:color/white"
++                android:textColor="@color/text_color_white"
+                 android:textSize="16sp"
+                 android:singleLine="true" />
+@@ -105,7 +105,7 @@
+                 android:paddingStart="8dip"
+                 android:gravity="center_vertical"
+                 android:textAppearance="?android:attr/textAppearanceSmall"
+-                android:textColor="@android:color/white"
++                android:textColor="@color/text_color_white"
+                 android:singleLine="true"
+                 android:paddingBottom="4dip"
+                 android:visibility="gone" />
+diff --git a/res/layout/editor_account_header.xml b/res/layout/editor_account_header.xml
+index 59ae3b1..a7d0c62 100644
+--- a/res/layout/editor_account_header.xml
++++ b/res/layout/editor_account_header.xml
+@@ -20,7 +20,7 @@
+     android:layout_height="wrap_content"
+     android:layout_width="match_parent"
+     android:minHeight="48dip"
+-    android:background="#EEEEEE"
++    android:background="@color/editor_account_header_bg"
+     android:orientation="horizontal"
+     android:paddingTop="8dip"
+     android:paddingBottom="8dip"
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..d258c86
+--- /dev/null
++++ b/res/values/projekt_colors.xml
+@@ -0,0 +1,29 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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>
++    <color name="photo_text_bar_bg">#7F000000</color>
++    <color name="text_color_white">@android:color/white</color>
++    <color name="editor_account_header_bg">#EEEEEE</color>
++    <color name="list_item_name_text_color">#ff212121</color>
++    <color name="white">@android:color/white</color>
++    <color name="contacts_action_bar_text_color_hint">#CCCCCC</color>
++    <color name="contacts_action_bar_text_color">@android:color/black</color>
++    <color name="section_divider_background_color">#7e7e87</color>
++    <color name="edit_kind_text_appearance_text_color">#363636</color>
++    <color name="account_type_name_text_color">#363636</color>
++</resources>
+diff --git a/res/values/styles.xml b/res/values/styles.xml
+index 95641e3..69d79ea 100644
+--- a/res/values/styles.xml
++++ b/res/values/styles.xml
+@@ -44,7 +44,13 @@
+         <item name="android:actionBarItemBackground">@drawable/item_background_material_borderless_dark</item>
+     </style>
+-    <style name="PeopleTheme" parent="@android:style/Theme.Material.Light">
++    <style name="PeopleTheme1" parent="@android:style/Theme.Material.Light">
++        <item name="android:colorPrimary">@color/primary_color</item>
++        <item name="android:colorPrimaryDark">@color/primary_color_dark</item>
++        <item name="android:colorAccent">@color/primary_color</item>
++    </style>
++
++    <style name="PeopleTheme" parent="@style/PeopleTheme1">
+         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+         <!-- Style for the tab bar (for the divider between tabs) -->
+         <item name="android:actionBarTabBarStyle">@style/ContactsActionBarTabBarStyle</item>
+@@ -62,9 +68,6 @@
+         <item name="android:icon">@android:color/transparent</item>
+         <item name="android:listViewStyle">@style/ListViewStyle</item>
+         <item name="android:windowBackground">@color/background_primary</item>
+-        <item name="android:colorPrimaryDark">@color/primary_color_dark</item>
+-        <item name="android:colorPrimary">@color/primary_color</item>
+-        <item name="android:colorAccent">@color/primary_color</item>
+         <item name="android:alertDialogTheme">@style/ContactsAlertDialogTheme</item>
+         <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
+         <item name="activated_background">@drawable/list_item_activated_background</item>
+@@ -98,6 +101,8 @@
+         <item name="contact_browser_list_padding_right">0dip</item>
+         <item name="contact_browser_background">@color/background_primary</item>
+         <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
++        <item name="list_item_name_text_color">@color/list_item_name_text_color</item>
++        <item name="list_item_name_text_size">16.0sp</item>
+         <!-- Favorites -->
+         <item name="favorites_padding_bottom">0dip</item>
+     </style>
+@@ -129,10 +134,10 @@
+     </style>
+     <style name="ContactPickerSearchTheme" parent="@style/PeopleTheme">
+-        <item name="android:textColorPrimary">@android:color/white</item>
++        <item name="android:textColorPrimary">@color/text_color_white</item>
+         <item name="android:textColorHint">?android:textColorHintInverse</item>
+         <item name="android:colorControlActivated">?android:textColorHintInverse</item>
+-        <item name="android:colorControlNormal">@android:color/white</item>
++        <item name="android:colorControlNormal">@color/white</item>
+     </style>
+     <!-- Text in the action bar at the top of the screen -->
+@@ -174,8 +179,8 @@
+     </style>
+     <style name="ContactsActionBarTheme" parent="@android:style/Theme.Material.Light">
+-        <item name="android:textColorHint">#CCCCCC</item>
+-        <item name="android:textColor">@android:color/black</item>
++        <item name="android:textColorHint">@color/contacts_action_bar_text_color_hint</item>
++        <item name="android:textColor">@color/contacts_action_bar_text_color</item>
+         <item name="android:popupMenuStyle">@android:style/Widget.Holo.Light.PopupMenu</item>
+         <item name="android:dropDownListViewStyle">@style/ListViewDropdownStyle</item>
+     </style>
+@@ -220,7 +225,7 @@
+     </style>
+     <style name="SectionDivider">
+-        <item name="android:background">#7e7e87</item>
++        <item name="android:background">@color/section_divider_background_color</item>
+         <item name="android:layout_height">1dip</item>
+         <item name="android:layout_width">match_parent</item>
+     </style>
+@@ -302,7 +307,7 @@
+         <item name="android:textSize">14sp</item>
+         <item name="android:textStyle">bold</item>
+         <item name="android:textAllCaps">true</item>
+-        <item name="android:textColor">#363636</item>
++        <item name="android:textColor">@color/edit_kind_text_appearance_text_color</item>
+         <item name="android:fontFamily">sans-serif</item>
+     </style>
+@@ -342,7 +347,7 @@
+     <style name="AccountTypeNameStyle">
+         <item name="android:textSize">10sp</item>
+-        <item name="android:textColor">#363636</item>
++        <item name="android:textColor">@color/account_type_name_text_color</item>
+         <item name="android:fontFamily">sans-serif</item>
+     </style>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch b/patches/packages/apps/ContactsCommon/0001-Themes-Expose-hardcoded-contact-tile-text-colors.patch
new file mode 100644 (file)
index 0000000..f1febe4
--- /dev/null
@@ -0,0 +1,87 @@
+From 1f53add2077b2573b7d6b4d761b48f8505bb3701 Mon Sep 17 00:00:00 2001
+From: bgill55 <bricam55@gmail.com>
+Date: Sat, 24 Jan 2015 18:12:39 -0700
+Subject: [PATCH] Themes: Expose hardcoded contact tile text colors
+
+Naming conventions in line with @daveyannihilation's commit
+https://github.com/daveyannihilation/Theme-Ready-Google-Contacts/commit/dedf7925f52bec3896b138fa3d9f3754218abb2d
+
+Change-Id: I85aa4349ece8a9821d9443523b13f2234edd4af7
+---
+ res/layout/contact_tile_frequent.xml              |  2 +-
+ res/layout/contact_tile_starred.xml               |  2 +-
+ res/layout/contact_tile_starred_quick_contact.xml |  2 +-
+ res/values/projekt_colors.xml                     | 22 ++++++++++++++++++++++
+ 4 files changed, 25 insertions(+), 3 deletions(-)
+ create mode 100644 res/values/projekt_colors.xml
+
+diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
+index b1e83ce..8c718fb 100644
+--- a/res/layout/contact_tile_frequent.xml
++++ b/res/layout/contact_tile_frequent.xml
+@@ -38,7 +38,7 @@
+             android:id="@+id/contact_tile_name"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+-            android:textColor="@android:color/black"
++            android:textColor="@color/frequent_contact_text_color"
+             android:textSize="@dimen/contact_browser_list_item_text_size"
+             android:singleLine="true"
+             android:fadingEdge="horizontal"
+diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
+index 777cc05..88aa1e8 100644
+--- a/res/layout/contact_tile_starred.xml
++++ b/res/layout/contact_tile_starred.xml
+@@ -43,7 +43,7 @@
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:paddingTop="7dp"
+-            android:textColor="#202020"
++            android:textColor="@color/contact_tile_text_color"
+             android:textSize="@dimen/contact_browser_list_item_text_size"
+             android:singleLine="true"
+             android:fadingEdge="horizontal"
+diff --git a/res/layout/contact_tile_starred_quick_contact.xml b/res/layout/contact_tile_starred_quick_contact.xml
+index ecbe583..2134ffc 100644
+--- a/res/layout/contact_tile_starred_quick_contact.xml
++++ b/res/layout/contact_tile_starred_quick_contact.xml
+@@ -47,7 +47,7 @@
+                 android:id="@+id/contact_tile_name"
+                 android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+-                android:textColor="@android:color/white"
++                android:textColor="@color/starred_quick_contact_name_text_color"
+                 android:textSize="16sp"
+                 android:singleLine="true"
+                 android:fadingEdge="horizontal"
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..a5d6bd3
+--- /dev/null
++++ b/res/values/projekt_colors.xml
+@@ -0,0 +1,22 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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>
++    <color name="frequent_contact_text_color">@android:color/black</color>
++    <color name="contact_tile_text_color">#ff202020</color>
++    <color name="starred_quick_contact_name_text_color">@android:color/white</color>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch b/patches/packages/apps/ExactCalculator/0001-Themes-Expose-hard-coded-background-in-java.patch
new file mode 100644 (file)
index 0000000..4418b9a
--- /dev/null
@@ -0,0 +1,53 @@
+From 1ff4ff6484428cd4b80aacaf1a619c3e3ea78667 Mon Sep 17 00:00:00 2001
+From: Bryan Owens <djbryan3540@gmail.com>
+Date: Tue, 29 Dec 2015 22:25:10 -0600
+Subject: [PATCH 1/2] Themes: Expose hard coded background in java
+
+Change-Id: I30bade7c82f29767c6659c8a75bb402d245e49f1
+---
+ res/values/projekt_colors.xml                         | 19 +++++++++++++++++++
+ .../android/calculator2/CalculatorPadViewPager.java   |  2 +-
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+ create mode 100644 res/values/projekt_colors.xml
+
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..9e15ffc
+--- /dev/null
++++ b/res/values/projekt_colors.xml
+@@ -0,0 +1,19 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++     Copyright (C) 2016 Projekt Substratum
++
++     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>
++    <color name="pad_view_pager_background">#ff000000</color>
++</resources>
+diff --git a/src/com/android/calculator2/CalculatorPadViewPager.java b/src/com/android/calculator2/CalculatorPadViewPager.java
+index d4520c5..5b02e4b 100644
+--- a/src/com/android/calculator2/CalculatorPadViewPager.java
++++ b/src/com/android/calculator2/CalculatorPadViewPager.java
+@@ -92,7 +92,7 @@ public class CalculatorPadViewPager extends ViewPager {
+         super(context, attrs);
+         setAdapter(mStaticPagerAdapter);
+-        setBackgroundColor(Color.BLACK);
++        setBackgroundColor(context.getColor(R.color.pad_view_pager_background));
+         setPageMargin(getResources().getDimensionPixelSize(R.dimen.pad_page_margin));
+         setPageTransformer(false, mPageTransformer);
+         addOnPageChangeListener(mOnPageChangeListener);
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch b/patches/packages/apps/ExactCalculator/0002-Themes-Expose-all-elevations.patch
new file mode 100644 (file)
index 0000000..b2a3277
--- /dev/null
@@ -0,0 +1,53 @@
+From b6b4eaf6df434964f0c3147d4363664096a5c947 Mon Sep 17 00:00:00 2001
+From: Abdulwahab Isam <abdoi94.iq@gmail.com>
+Date: Mon, 19 Sep 2016 18:42:06 +0300
+Subject: [PATCH 2/2] Themes: Expose all elevations
+
+Change-Id: I7d161c1fce17ac3b8a468e1597a3a1632433224b
+---
+ res/layout/display.xml     | 2 +-
+ res/values-port/styles.xml | 2 +-
+ res/values/dimens.xml      | 5 +++++
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+ create mode 100644 res/values/dimens.xml
+
+diff --git a/res/layout/display.xml b/res/layout/display.xml
+index 638f0d2..043b531 100644
+--- a/res/layout/display.xml
++++ b/res/layout/display.xml
+@@ -21,7 +21,7 @@
+     android:layout_width="match_parent"
+     android:layout_height="wrap_content"
+     android:background="@color/display_background_color"
+-    android:elevation="4dip">
++    android:elevation="@dimen/display_elevation">
+     <Toolbar
+         android:id="@+id/toolbar"
+diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
+index a6d2013..9e7e1df 100644
+--- a/res/values-port/styles.xml
++++ b/res/values-port/styles.xml
+@@ -65,7 +65,7 @@
+     </style>
+     <style name="PadLayoutStyle.Advanced">
+-        <item name="android:elevation">4dip</item>
++        <item name="android:elevation">@dimen/pad_elevation</item>
+         <item name="android:paddingTop">12dip</item>
+         <item name="android:paddingBottom">20dip</item>
+         <item name="android:paddingStart">20dip</item>
+diff --git a/res/values/dimens.xml b/res/values/dimens.xml
+new file mode 100644
+index 0000000..065de72
+--- /dev/null
++++ b/res/values/dimens.xml
+@@ -0,0 +1,5 @@
++<?xml version="1.0" encoding="utf-8"?>
++<resources>
++    <dimen name="display_elevation">4.0dip</dimen>
++    <dimen name="pad_elevation">4.0dip</dimen>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch b/patches/packages/apps/PhoneCommon/0001-Themes-Make-dialpad-seperator-line-theme-able.patch
new file mode 100644 (file)
index 0000000..5896c2d
--- /dev/null
@@ -0,0 +1,69 @@
+From e1c858c77863d951ceab42213cb0df56d36b2ef6 Mon Sep 17 00:00:00 2001
+From: Thyrus11 <thyrus11@gmail.com>
+Date: Sat, 21 Feb 2015 10:41:01 +0100
+Subject: [PATCH] Themes: Make dialpad seperator line theme-able
+
+Using an existing value in colors is defined
+(dialpad_seperator_line_color) in AOSP, but overwritten in layout
+
+Changed the original commit's color name due to layout was #e3e3e3 and
+dialpad_seperator_line_color is #dadada
+
+Change-Id: Ia4b610185bac6c34e0f6bd1b00a6f0c0480d5ee0
+---
+ res/layout/dialpad_view_unthemed.xml |  4 ++--
+ res/values/projekt_colors.xml        | 20 ++++++++++++++++++++
+ 2 files changed, 22 insertions(+), 2 deletions(-)
+ create mode 100644 res/values/projekt_colors.xml
+
+diff --git a/res/layout/dialpad_view_unthemed.xml b/res/layout/dialpad_view_unthemed.xml
+index 7bc4536..3fcf0da 100644
+--- a/res/layout/dialpad_view_unthemed.xml
++++ b/res/layout/dialpad_view_unthemed.xml
+@@ -56,7 +56,7 @@
+         <View
+             android:layout_width="match_parent"
+             android:layout_height="1dp"
+-            android:background="#e3e3e3" />
++            android:background="@color/dialpad_separator_color" />
+     </LinearLayout>
+@@ -148,7 +148,7 @@
+     <View
+         android:layout_width="match_parent"
+         android:layout_height="1dp"
+-        android:background="#e3e3e3" />
++        android:background="@color/dialpad_separator_color" />
+     <Space
+         android:layout_width="match_parent"
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..468ca5c
+--- /dev/null
++++ b/res/values/projekt_colors.xml
+@@ -0,0 +1,20 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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>
++    <color name="dialpad_separator_color">#e3e3e3</color>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch b/patches/packages/apps/Settings/0001-Settings-Expose-dashboard-category-and-tile-color.patch
new file mode 100644 (file)
index 0000000..282a0e7
--- /dev/null
@@ -0,0 +1,127 @@
+From 121e37c0c3fe7cc8ac35793777e247ccb812de6b Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Sun, 18 Sep 2016 10:12:05 +0700
+Subject: [PATCH 01/15] Settings: Expose dashboard category and tile color
+
+Change-Id: Ia9c83eb9b8360923ed52e03641b4179681a80330
+---
+ res/drawable/dashboard_category_title_bg.xml | 21 +++++++++++++++++++++
+ res/drawable/dashboard_tile_bg.xml           | 21 +++++++++++++++++++++
+ res/drawable/selectable_card.xml             |  4 ++--
+ res/layout/dashboard_category.xml            |  2 +-
+ res/values/projekt_colors.xml                | 21 +++++++++++++++++++++
+ 5 files changed, 66 insertions(+), 3 deletions(-)
+ create mode 100644 res/drawable/dashboard_category_title_bg.xml
+ create mode 100644 res/drawable/dashboard_tile_bg.xml
+ create mode 100644 res/values/projekt_colors.xml
+
+diff --git a/res/drawable/dashboard_category_title_bg.xml b/res/drawable/dashboard_category_title_bg.xml
+new file mode 100644
+index 0000000..0e9604d
+--- /dev/null
++++ b/res/drawable/dashboard_category_title_bg.xml
+@@ -0,0 +1,21 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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.
++-->
++
++<shape xmlns:android="http://schemas.android.com/apk/res/android"
++       android:shape="rectangle">
++   <solid android:color="@color/dashboard_category_title_background" />
++</shape>
+diff --git a/res/drawable/dashboard_tile_bg.xml b/res/drawable/dashboard_tile_bg.xml
+new file mode 100644
+index 0000000..61d113d
+--- /dev/null
++++ b/res/drawable/dashboard_tile_bg.xml
+@@ -0,0 +1,21 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Project Substratum
++
++    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.
++-->
++
++<shape xmlns:android="http://schemas.android.com/apk/res/android"
++       android:shape="rectangle">
++   <solid android:color="@color/selectable_card_background" />
++</shape>
+diff --git a/res/drawable/selectable_card.xml b/res/drawable/selectable_card.xml
+index df9ddb1..74018b2 100644
+--- a/res/drawable/selectable_card.xml
++++ b/res/drawable/selectable_card.xml
+@@ -18,5 +18,5 @@
+ <ripple
+     xmlns:android="http://schemas.android.com/apk/res/android"
+     android:color="?android:attr/colorControlHighlight">
+-    <item android:drawable="@color/card_background"/>
+-</ripple>
+\ No newline at end of file
++    <item android:drawable="@drawable/dashboard_tile_bg"/>
++</ripple>
+diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
+index 2e5dd5c..7836644 100644
+--- a/res/layout/dashboard_category.xml
++++ b/res/layout/dashboard_category.xml
+@@ -20,7 +20,7 @@
+     android:layout_height="@dimen/dashboard_category_height"
+     android:orientation="vertical"
+     android:paddingBottom="8dip"
+-    android:background="@color/card_background">
++    android:background="@drawable/dashboard_category_title_bg">
+     <TextView android:id="@android:id/title"
+         android:layout_width="match_parent"
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+new file mode 100644
+index 0000000..60419bd
+--- /dev/null
++++ b/res/values/projekt_colors.xml
+@@ -0,0 +1,21 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2016 Projekt Substratum
++
++    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>
++    <!-- Dashboard category and tile background -->
++    <color name="dashboard_category_title_background">@color/card_background</color>
++    <color name="selectable_card_background">@color/card_background</color>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch b/patches/packages/apps/Settings/0002-Settings-Expose-condition-card-colors.patch
new file mode 100644 (file)
index 0000000..8a0c90c
--- /dev/null
@@ -0,0 +1,118 @@
+From fde00a322179ec03d9232001da19a3284e65b807 Mon Sep 17 00:00:00 2001
+From: daveyannihilation <daveyannihilation@hotmail.com>
+Date: Tue, 20 Sep 2016 23:35:04 +0800
+Subject: [PATCH 02/15] Settings: Expose condition card colors
+
+PS2 Change to the actual colors in fwb that these attrs call to.
+
+@nathanchance edit: updated for Nougat 7.1
+
+Change-Id: I8de2e2a4f79a28c0fe1f025b4d23937931fe293a
+---
+ res/layout/condition_card.xml | 18 +++++++++---------
+ res/values/projekt_colors.xml |  9 +++++++++
+ 2 files changed, 18 insertions(+), 9 deletions(-)
+
+diff --git a/res/layout/condition_card.xml b/res/layout/condition_card.xml
+index 7c9e46d..88277c2 100644
+--- a/res/layout/condition_card.xml
++++ b/res/layout/condition_card.xml
+@@ -1,6 +1,6 @@
+ <?xml version="1.0" encoding="utf-8"?>
+ <!--
+-     Copyright (C) 2015 The Android Open Source Project
++     Copyright (C) 2016 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.
+@@ -25,7 +25,7 @@
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+         android:orientation="vertical"
+-        android:background="?android:attr/colorAccent"
++        android:background="@color/condition_card_background_color"
+         android:elevation="2dp"
+         android:clickable="true"
+         android:focusable="true">
+@@ -44,7 +44,7 @@
+                 android:layout_height="wrap_content"
+                 android:layout_marginStart="16dp"
+                 android:layout_marginEnd="32dp"
+-                android:tint="?android:attr/textColorPrimaryInverse" />
++                android:tint="@color/condition_card_icon_color" />
+             <TextView
+                 android:id="@android:id/title"
+@@ -52,14 +52,14 @@
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:textAppearance="?android:attr/textAppearanceMedium"
+-                android:textColor="?android:attr/textColorPrimaryInverse" />
++                android:textColor="@color/condition_card_title_text_color" />
+             <ImageView
+                 android:id="@+id/expand_indicator"
+                 android:layout_width="wrap_content"
+                 android:layout_height="match_parent"
+                 android:padding="16dp"
+-                android:tint="?android:attr/textColorPrimaryInverse"/>
++                android:tint="@color/condition_card_expander_color" />
+         </LinearLayout>
+@@ -81,14 +81,14 @@
+                 android:paddingBottom="16dp"
+                 android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+                 android:alpha=".7"
+-                android:textColor="?android:attr/textColorPrimaryInverse" />
++                android:textColor="@color/condition_card_summary_text_color" />
+             <!-- TODO: Better background -->
+             <View
+                 android:id="@+id/divider"
+                 android:layout_width="match_parent"
+                 android:layout_height=".25dp"
+-                android:background="@android:color/white" />
++                android:background="@color/condition_card_divider_color" />
+             <com.android.internal.widget.ButtonBarLayout
+                 android:id="@+id/buttonBar"
+@@ -107,7 +107,7 @@
+                     android:paddingStart="0dp"
+                     android:alpha=".8"
+                     android:textAlignment="viewStart"
+-                    android:textColor="?android:attr/textColorPrimaryInverse"
++                    android:textColor="@color/condition_card_first_button_text_color"
+                     style="?android:attr/buttonBarButtonStyle" />
+                 <Button
+@@ -117,7 +117,7 @@
+                     android:layout_weight="1"
+                     android:alpha=".8"
+                     android:textAlignment="viewStart"
+-                    android:textColor="?android:attr/textColorPrimaryInverse"
++                    android:textColor="@color/condition_card_second_button_text_color"
+                     style="?android:attr/buttonBarButtonStyle" />
+             </com.android.internal.widget.ButtonBarLayout>
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index 60419bd..9340830 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -18,4 +18,13 @@
+     <!-- Dashboard category and tile background -->
+     <color name="dashboard_category_title_background">@color/card_background</color>
+     <color name="selectable_card_background">@color/card_background</color>
++    <!-- Condition card colors -->
++    <color name="condition_card_background_color">@*android:color/accent_device_default_light</color>
++    <color name="condition_card_icon_color">@*android:color/primary_text_default_material_dark</color>
++    <color name="condition_card_title_text_color">@*android:color/primary_text_default_material_dark</color>
++    <color name="condition_card_expander_color">@*android:color/primary_text_default_material_dark</color>
++    <color name="condition_card_summary_text_color">@*android:color/primary_text_default_material_dark</color>
++    <color name="condition_card_divider_color">@android:color/white</color>
++    <color name="condition_card_first_button_text_color">@*android:color/primary_text_default_material_dark</color>
++    <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch b/patches/packages/apps/Settings/0003-Settings-Expose-storage-summary-text.patch
new file mode 100644 (file)
index 0000000..52d06de
--- /dev/null
@@ -0,0 +1,124 @@
+From 81f82e54029690d530fc32b31a2a2e77d80bbf18 Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Tue, 3 Nov 2015 23:57:22 +0200
+Subject: [PATCH 03/15] Settings: Expose storage summary text
+
+This commit simply exposes the storage summary text hardcodes to allow
+themers to theme them without issue.
+
+@nathanchance edit: updated for Nougat 7.1
+
+Change-Id: I10c124b6a1516a1be7ac234c1dd7dbe2cbe05bb2
+---
+ res/layout/storage_summary.xml                                    | 2 +-
+ res/values/projekt_colors.xml                                     | 2 ++
+ src/com/android/settings/deviceinfo/StorageSummaryPreference.java | 8 +++++++-
+ src/com/android/settings/deviceinfo/StorageVolumePreference.java  | 8 +++++++-
+ 4 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/res/layout/storage_summary.xml b/res/layout/storage_summary.xml
+index 7bc51df..c01d2da 100644
+--- a/res/layout/storage_summary.xml
++++ b/res/layout/storage_summary.xml
+@@ -33,7 +33,7 @@
+         android:singleLine="true"
+         android:textAlignment="viewStart"
+         android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+-        android:textColor="?android:attr/colorAccent"
++        android:textColor="@color/storage_summary_title_color"
+         android:textSize="36sp"
+         android:ellipsize="marquee"
+         android:fadingEdge="horizontal" />
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index 9340830..fb0d99e 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -27,4 +27,6 @@
+     <color name="condition_card_divider_color">@android:color/white</color>
+     <color name="condition_card_first_button_text_color">@*android:color/primary_text_default_material_dark</color>
+     <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
++    <!-- Storage Summary Title -->
++    <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
+ </resources>
+diff --git a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
+index e1cf774..2741798 100644
+--- a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
++++ b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
+@@ -21,6 +21,7 @@ import android.graphics.Color;
+ import android.support.v7.preference.Preference;
+ import android.support.v7.preference.PreferenceViewHolder;
+ import android.view.View;
++import android.util.TypedValue;
+ import android.widget.ProgressBar;
+ import android.widget.TextView;
+@@ -28,12 +29,17 @@ import com.android.settings.R;
+ public class StorageSummaryPreference extends Preference {
+     private int mPercent = -1;
++    private int mSecondaryColor;
+     public StorageSummaryPreference(Context context) {
+         super(context);
+         setLayoutResource(R.layout.storage_summary);
+         setEnabled(false);
++
++        TypedValue typedValue = new TypedValue();
++        context.getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
++        mSecondaryColor = context.getResources().getColor(typedValue.resourceId);
+     }
+     public void setPercent(int percent) {
+@@ -52,7 +58,7 @@ public class StorageSummaryPreference extends Preference {
+         }
+         final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+-        summary.setTextColor(Color.parseColor("#8a000000"));
++        summary.setTextColor(mSecondaryColor);
+         super.onBindViewHolder(view);
+     }
+diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+index 6389075..9d3c7dc 100644
+--- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
++++ b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+@@ -27,6 +27,7 @@ import android.support.v7.preference.PreferenceViewHolder;
+ import android.text.format.Formatter;
+ import android.view.View;
+ import android.view.View.OnClickListener;
++import android.util.TypedValue;
+ import android.widget.ImageView;
+ import android.widget.ProgressBar;
+@@ -44,6 +45,7 @@ public class StorageVolumePreference extends Preference {
+     private final VolumeInfo mVolume;
+     private int mColor;
++    private int mSecondaryColor;
+     private int mUsedPercent = -1;
+     // TODO: ideally, VolumeInfo should have a total physical size.
+@@ -54,6 +56,10 @@ public class StorageVolumePreference extends Preference {
+         mVolume = volume;
+         mColor = color;
++        TypedValue typedValue = new TypedValue();
++        context.getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
++        mSecondaryColor = context.getResources().getColor(typedValue.resourceId);
++
+         setLayoutResource(R.layout.storage_volume);
+         setKey(volume.getId());
+@@ -107,7 +113,7 @@ public class StorageVolumePreference extends Preference {
+     public void onBindViewHolder(PreferenceViewHolder view) {
+         final ImageView unmount = (ImageView) view.findViewById(R.id.unmount);
+         if (unmount != null) {
+-            unmount.setImageTintList(ColorStateList.valueOf(Color.parseColor("#8a000000")));
++            unmount.setImageTintList(ColorStateList.valueOf(mSecondaryColor));
+             unmount.setOnClickListener(mUnmountListener);
+         }
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch b/patches/packages/apps/Settings/0004-Settings-Expose-gesture-settings-switchbar.patch
new file mode 100644 (file)
index 0000000..c742a8f
--- /dev/null
@@ -0,0 +1,44 @@
+From f4e4000d09321bf4425201b039d5c2054d2fadad Mon Sep 17 00:00:00 2001
+From: daveyannihilation <daveyannihilation@hotmail.com>
+Date: Fri, 25 Nov 2016 15:20:04 -0700
+Subject: [PATCH 04/15] Settings: Expose gesture settings switchbar
+
+In Settings > Gestures, there is a hardcoded white background above each switch. Link to a colors.xml value instead.
+
+Commit written by @nathanchance, idea by @daveyannihilation
+
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Change-Id: I9857c10ee4e54d27ca1287c80a7d8e420adc9a61
+---
+ res/layout/gesture_preference.xml | 2 +-
+ res/values/projekt_colors.xml     | 3 +++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/res/layout/gesture_preference.xml b/res/layout/gesture_preference.xml
+index ccbc42a..9fcd14f 100644
+--- a/res/layout/gesture_preference.xml
++++ b/res/layout/gesture_preference.xml
+@@ -31,7 +31,7 @@
+         android:paddingBottom="16dp"
+         android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+         android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+-        android:background="@android:color/white">
++        android:background="@color/gestures_switchbar_color">
+         <TextView
+             android:id="@android:id/title"
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index fb0d99e..00252332 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -29,4 +29,7 @@
+     <color name="condition_card_second_button_text_color">@*android:color/primary_text_default_material_dark</color>
+     <!-- Storage Summary Title -->
+     <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
++    <!-- Gesture settings switchbar background -->
++    <color name="gestures_switchbar_color">@android:color/white</color>
++
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch b/patches/packages/apps/Settings/0005-Settings-Expose-storage-icon-colors.patch
new file mode 100644 (file)
index 0000000..360da46
--- /dev/null
@@ -0,0 +1,121 @@
+From d4beb2fe4bbf5105446f23735674a48a0bff5b59 Mon Sep 17 00:00:00 2001
+From: SpiritCroc <spiritcroc@gmail.com>
+Date: Thu, 8 Dec 2016 20:40:16 +0100
+Subject: [PATCH 05/15] Settings: Expose storage icon colors
+
+Change-Id: I97ce427f0683791670f1bbf82eaef66152fe4961
+---
+ res/values/projekt_colors.xml                      |  9 +++++-
+ .../settings/deviceinfo/StorageSettings.java       | 32 ++++++++++++++--------
+ .../deviceinfo/StorageVolumePreference.java        |  2 +-
+ 3 files changed, 29 insertions(+), 14 deletions(-)
+
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index 00252332..bb6099b 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -31,5 +31,12 @@
+     <color name="storage_summary_title_color">@*android:color/accent_device_default_light</color>
+     <!-- Gesture settings switchbar background -->
+     <color name="gestures_switchbar_color">@android:color/white</color>
+-
++    <!-- Storage icons -->
++    <color name="storage_public">#ff9e9e9e</color>
++    <color name="storage_warning">#fff4511e</color>
++    <color name="storage_private_1">#ff26a69a</color>
++    <color name="storage_private_2">#ffab47bc</color>
++    <color name="storage_private_3">#fff2a600</color>
++    <color name="storage_private_4">#ffec407a</color>
++    <color name="storage_private_5">#ffc0ca33</color>
+ </resources>
+diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
+index 7757efc..b01013b 100644
+--- a/src/com/android/settings/deviceinfo/StorageSettings.java
++++ b/src/com/android/settings/deviceinfo/StorageSettings.java
+@@ -24,6 +24,7 @@ import android.app.Fragment;
+ import android.content.Context;
+ import android.content.DialogInterface;
+ import android.content.Intent;
++import android.content.res.Resources ;
+ import android.graphics.Color;
+ import android.graphics.drawable.Drawable;
+ import android.os.AsyncTask;
+@@ -73,16 +74,22 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
+     private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
+     private static final String TAG_DISK_INIT = "disk_init";
+-    static final int COLOR_PUBLIC = Color.parseColor("#ff9e9e9e");
+-    static final int COLOR_WARNING = Color.parseColor("#fff4511e");
++    static int getColorPublic(Resources resources) {
++        return resources.getColor(R.color.storage_public);
++    }
++    static int getColorWarning(Resources resources) {
++        return resources.getColor(R.color.storage_warning);
++    }
+-    static final int[] COLOR_PRIVATE = new int[] {
+-            Color.parseColor("#ff26a69a"),
+-            Color.parseColor("#ffab47bc"),
+-            Color.parseColor("#fff2a600"),
+-            Color.parseColor("#ffec407a"),
+-            Color.parseColor("#ffc0ca33"),
+-    };
++    static int[] getColorPrivate(Resources resources) {
++        return new int[] {
++                resources.getColor(R.color.storage_private_1),
++                resources.getColor(R.color.storage_private_2),
++                resources.getColor(R.color.storage_private_3),
++                resources.getColor(R.color.storage_private_4),
++                resources.getColor(R.color.storage_private_5),
++        };
++    }
+     private StorageManager mStorageManager;
+@@ -165,10 +172,11 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
+         final List<VolumeInfo> volumes = mStorageManager.getVolumes();
+         Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
++        int[] colorPrivate = getColorPrivate(getResources());
+         for (VolumeInfo vol : volumes) {
+             if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
+                 final long volumeTotalBytes = getTotalSize(vol);
+-                final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
++                final int color = colorPrivate[privateCount++ % colorPrivate.length];
+                 mInternalCategory.addPreference(
+                         new StorageVolumePreference(context, vol, color, volumeTotalBytes));
+                 if (vol.isMountedReadable()) {
+@@ -178,7 +186,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
+                 }
+             } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
+                 mExternalCategory.addPreference(
+-                        new StorageVolumePreference(context, vol, COLOR_PUBLIC, 0));
++                        new StorageVolumePreference(context, vol, getColorPublic(getResources()), 0));
+             }
+         }
+@@ -190,7 +198,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
+                 // TODO: add actual storage type to record
+                 final Drawable icon = context.getDrawable(R.drawable.ic_sim_sd);
+                 icon.mutate();
+-                icon.setTint(COLOR_PUBLIC);
++                icon.setTint(getColorPublic(getResources()));
+                 final Preference pref = new Preference(context);
+                 pref.setKey(rec.getFsUuid());
+diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+index 9d3c7dc..8a2780a 100644
+--- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
++++ b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+@@ -89,7 +89,7 @@ public class StorageVolumePreference extends Preference {
+             }
+             if (freeBytes < mStorageManager.getStorageLowBytes(path)) {
+-                mColor = StorageSettings.COLOR_WARNING;
++                mColor = StorageSettings.getColorWarning(context.getResources());
+                 icon = context.getDrawable(R.drawable.ic_warning_24dp);
+             }
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch b/patches/packages/apps/Settings/0006-Settings-Expose-LinearColorBar-default-colors.patch
new file mode 100644 (file)
index 0000000..93b9c32
--- /dev/null
@@ -0,0 +1,68 @@
+From c52f89f21eade3f277963374f3c5cf34cad3bdd7 Mon Sep 17 00:00:00 2001
+From: SpiritCroc <spiritcroc@gmail.com>
+Date: Fri, 9 Dec 2016 12:47:54 +0100
+Subject: [PATCH 06/15] Settings: Expose LinearColorBar default colors
+
+Change-Id: I8e63f10f9e4079d1a03eaece18e8343102f4a755
+---
+ res/values/projekt_colors.xml                             |  5 +++++
+ src/com/android/settings/applications/LinearColorBar.java | 10 +++++++---
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index bb6099b..e1977f9 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -39,4 +39,9 @@
+     <color name="storage_private_3">#fff2a600</color>
+     <color name="storage_private_4">#ffec407a</color>
+     <color name="storage_private_5">#ffc0ca33</color>
++
++    <!-- Linear color bar -->
++    <color name="linear_color_bar_left">@*android:color/accent_device_default_light</color>
++    <color name="linear_color_bar_middle">@*android:color/accent_device_default_light</color>
++    <color name="linear_color_bar_right">#ffced7db</color>
+ </resources>
+diff --git a/src/com/android/settings/applications/LinearColorBar.java b/src/com/android/settings/applications/LinearColorBar.java
+index b637671..b0b8b82 100644
+--- a/src/com/android/settings/applications/LinearColorBar.java
++++ b/src/com/android/settings/applications/LinearColorBar.java
+@@ -15,6 +15,7 @@ import android.util.DisplayMetrics;
+ import android.view.MotionEvent;
+ import android.widget.LinearLayout;
+ import com.android.settings.Utils;
++import com.android.settings.R;
+ public class LinearColorBar extends LinearLayout {
+@@ -28,7 +29,7 @@ public class LinearColorBar extends LinearLayout {
+     private int mLeftColor;
+     private int mMiddleColor;
+-    private int mRightColor = RIGHT_COLOR;
++    private int mRightColor;
+     private boolean mShowIndicator = true;
+     private boolean mShowingGreen;
+@@ -70,7 +71,10 @@ public class LinearColorBar extends LinearLayout {
+                 ? 2 : 1;
+         mEdgeGradientPaint.setStrokeWidth(mLineWidth);
+         mEdgeGradientPaint.setAntiAlias(true);
+-        mLeftColor = mMiddleColor = Utils.getColorAccent(context);
++
++        mLeftColor = context.getResources().getColor(R.color.linear_color_bar_left);
++        mMiddleColor = context.getResources().getColor(R.color.linear_color_bar_middle);
++        mRightColor = context.getResources().getColor(R.color.linear_color_bar_right);
+     }
+     public void setOnRegionTappedListener(OnRegionTappedListener listener) {
+@@ -271,4 +275,4 @@ public class LinearColorBar extends LinearLayout {
+             canvas.drawRect(mRect, mPaint);
+         }
+     }
+-}
+\ No newline at end of file
++}
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch b/patches/packages/apps/Settings/0007-OMS7-N-Apps-show-hide-Substratum-overlays-2-2.patch
new file mode 100644 (file)
index 0000000..8a03910
--- /dev/null
@@ -0,0 +1,159 @@
+From 952537ca209dd20a4bc98ea192aa78032a665b10 Mon Sep 17 00:00:00 2001
+From: George G <kreach3r@users.noreply.github.com>
+Date: Mon, 4 Jul 2016 12:07:11 +0300
+Subject: [PATCH 07/15] OMS7-N: Apps: show/hide Substratum overlays [2/2]
+
+Default behavior is "hidden" substratum overlays,
+as they pollute the screen, and you can't notice the
+actual apps.
+So we follow the current trend set by Android with
+"show system" and make it "show overlays" on default.
+
+Change-Id: I1cd4d4d3acd767a87fe402c325a872a4c04e0438
+---
+ res/menu/manage_apps.xml                           |  8 +++++++
+ res/values/projekt_strings.xml                     | 23 ++++++++++++++++++
+ .../settings/applications/ManageApplications.java  | 27 +++++++++++++++++++++-
+ 3 files changed, 57 insertions(+), 1 deletion(-)
+ create mode 100644 res/values/projekt_strings.xml
+
+diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
+index 02ee2bb..67f09e5 100644
+--- a/res/menu/manage_apps.xml
++++ b/res/menu/manage_apps.xml
+@@ -30,6 +30,14 @@
+         android:title="@string/menu_hide_system"
+         android:showAsAction="never" />
+     <item
++        android:id="@+id/show_substratum"
++        android:title="@string/menu_show_substratum"
++        android:showAsAction="never" />
++    <item
++        android:id="@+id/hide_substratum"
++        android:title="@string/menu_hide_substratum"
++        android:showAsAction="never" />
++    <item
+         android:id="@+id/sort_order_alpha"
+         android:title="@string/sort_order_alpha"
+         android:showAsAction="never" />
+diff --git a/res/values/projekt_strings.xml b/res/values/projekt_strings.xml
+new file mode 100644
+index 0000000..177e78c
+--- /dev/null
++++ b/res/values/projekt_strings.xml
+@@ -0,0 +1,23 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!-- Copyright (c) 2016 Project Substratum
++
++     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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
++
++   <!-- Manage applications: show substratum overlays -->
++   <string name="filter_substratum_apps">Substratum overlays</string>
++   <string name="menu_show_substratum">Show overlays</string>
++   <string name="menu_hide_substratum">Hide overlays</string>
++
++</resources>
+diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
+index 8b1dd27..070754a 100644
+--- a/src/com/android/settings/applications/ManageApplications.java
++++ b/src/com/android/settings/applications/ManageApplications.java
+@@ -107,6 +107,7 @@ public class ManageApplications extends InstrumentedFragment
+     private static final String EXTRA_SORT_ORDER = "sortOrder";
+     private static final String EXTRA_SHOW_SYSTEM = "showSystem";
++    private static final String EXTRA_SHOW_SUBSTRATUM = "showSubstratum";
+     private static final String EXTRA_HAS_ENTRIES = "hasEntries";
+     private static final String EXTRA_HAS_BRIDGE = "hasBridge";
+@@ -138,6 +139,7 @@ public class ManageApplications extends InstrumentedFragment
+     public static final int FILTER_APPS_USAGE_ACCESS = 13;
+     public static final int FILTER_APPS_WITH_OVERLAY = 14;
+     public static final int FILTER_APPS_WRITE_SETTINGS = 15;
++    public static final int FILTER_APPS_SUBSTRATUM = 16;
+     // This is the string labels for the filter modes above, the order must be kept in sync.
+     public static final int[] FILTER_LABELS = new int[]{
+@@ -187,6 +189,9 @@ public class ManageApplications extends InstrumentedFragment
+     // whether showing system apps.
+     private boolean mShowSystem;
++    // whether showing substratum overlays.
++    private boolean mShowSubstratum;
++
+     private ApplicationsState mApplicationsState;
+     public int mListType;
+@@ -276,6 +281,7 @@ public class ManageApplications extends InstrumentedFragment
+         if (savedInstanceState != null) {
+             mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
+             mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
++            mShowSubstratum = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
+         }
+         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
+@@ -440,6 +446,7 @@ public class ManageApplications extends InstrumentedFragment
+         mResetAppsHelper.onSaveInstanceState(outState);
+         outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
+         outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
++        outState.putBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
+         outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
+         outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
+     }
+@@ -558,6 +565,11 @@ public class ManageApplications extends InstrumentedFragment
+                 && mListType != LIST_TYPE_HIGH_POWER);
+         mOptionsMenu.findItem(R.id.hide_system).setVisible(mShowSystem
+                 && mListType != LIST_TYPE_HIGH_POWER);
++
++        mOptionsMenu.findItem(R.id.show_substratum).setVisible(!mShowSubstratum
++                && mListType != LIST_TYPE_HIGH_POWER);
++        mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
++                && mListType != LIST_TYPE_HIGH_POWER);
+     }
+     @Override
+@@ -577,6 +589,11 @@ public class ManageApplications extends InstrumentedFragment
+                 mShowSystem = !mShowSystem;
+                 mApplications.rebuild(false);
+                 break;
++            case R.id.show_substratum:
++            case R.id.hide_substratum:
++                mShowSubstratum = !mShowSubstratum;
++                mApplications.rebuild(false);
++                break;
+             case R.id.reset_app_preferences:
+                 mResetAppsHelper.buildResetDialog();
+                 return true;
+@@ -865,9 +882,17 @@ public class ManageApplications extends InstrumentedFragment
+             if (mOverrideFilter != null) {
+                 filterObj = mOverrideFilter;
+             }
+-            if (!mManageApplications.mShowSystem) {
++            if (!mManageApplications.mShowSystem && !mManageApplications.mShowSubstratum) {
+                 filterObj = new CompoundFilter(filterObj,
+                         ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
++                filterObj = new CompoundFilter(filterObj,
++                        ApplicationsState.FILTER_SUBSTRATUM);
++            } else if (!mManageApplications.mShowSystem) {
++                filterObj = new CompoundFilter(filterObj,
++                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
++            } else if (!mManageApplications.mShowSubstratum) {
++                filterObj = new CompoundFilter(filterObj,
++                        ApplicationsState.FILTER_SUBSTRATUM);
+             }
+             switch (mLastSortMode) {
+                 case R.id.sort_order_size:
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch b/patches/packages/apps/Settings/0008-OMS7-N-Apps-show-hide-Substratum-icon-overlays-2-2.patch
new file mode 100644 (file)
index 0000000..d6f0870
--- /dev/null
@@ -0,0 +1,151 @@
+From 3fcc8bc49ffb6dc7d35e4ba460e932857bff721b Mon Sep 17 00:00:00 2001
+From: Kuba Schenk <abukcz@gmail.com>
+Date: Thu, 1 Dec 2016 22:00:31 +0100
+Subject: [PATCH 08/15] OMS7-N: Apps: show/hide Substratum icon overlays [2/2]
+
+Default behavior is "hidden" substratum icon overlays,
+as they pollute the screen, and you can't notice the
+actual apps.
+So we follow the current trend set by Android with
+"show system" and make it "show icon overlays" on default.
+
+Change-Id: Ib6dd011f821f21bee6da1979615f2eb4658c9f52
+(cherry picked from commit a01b70568db202255fbf7f62d87c3e89e91f933d)
+---
+ res/menu/manage_apps.xml                           |  8 ++++++
+ res/values/projekt_strings.xml                     |  5 ++++
+ .../settings/applications/ManageApplications.java  | 33 ++++++++++++++++------
+ 3 files changed, 37 insertions(+), 9 deletions(-)
+
+diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
+index 67f09e5..267cff8 100644
+--- a/res/menu/manage_apps.xml
++++ b/res/menu/manage_apps.xml
+@@ -38,6 +38,14 @@
+         android:title="@string/menu_hide_substratum"
+         android:showAsAction="never" />
+     <item
++        android:id="@+id/show_substratum_icons"
++        android:title="@string/menu_show_substratum_icons"
++        android:showAsAction="never" />
++    <item
++        android:id="@+id/hide_substratum_icons"
++        android:title="@string/menu_hide_substratum_icons"
++        android:showAsAction="never" />
++    <item
+         android:id="@+id/sort_order_alpha"
+         android:title="@string/sort_order_alpha"
+         android:showAsAction="never" />
+diff --git a/res/values/projekt_strings.xml b/res/values/projekt_strings.xml
+index 177e78c..4c45544 100644
+--- a/res/values/projekt_strings.xml
++++ b/res/values/projekt_strings.xml
+@@ -20,4 +20,9 @@
+    <string name="menu_show_substratum">Show overlays</string>
+    <string name="menu_hide_substratum">Hide overlays</string>
++   <!-- Manage applications: show substratum icon overlays -->
++   <string name="filter_substratum_icons">Substratum icon overlays</string>
++   <string name="menu_show_substratum_icons">Show icon overlays</string>
++   <string name="menu_hide_substratum_icons">Hide icon overlays</string>
++
+ </resources>
+diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
+index 070754a..5d3b353 100644
+--- a/src/com/android/settings/applications/ManageApplications.java
++++ b/src/com/android/settings/applications/ManageApplications.java
+@@ -108,6 +108,7 @@ public class ManageApplications extends InstrumentedFragment
+     private static final String EXTRA_SORT_ORDER = "sortOrder";
+     private static final String EXTRA_SHOW_SYSTEM = "showSystem";
+     private static final String EXTRA_SHOW_SUBSTRATUM = "showSubstratum";
++    private static final String EXTRA_SHOW_SUBSTRATUM_ICONS = "showSubstratumIcons";
+     private static final String EXTRA_HAS_ENTRIES = "hasEntries";
+     private static final String EXTRA_HAS_BRIDGE = "hasBridge";
+@@ -139,7 +140,8 @@ public class ManageApplications extends InstrumentedFragment
+     public static final int FILTER_APPS_USAGE_ACCESS = 13;
+     public static final int FILTER_APPS_WITH_OVERLAY = 14;
+     public static final int FILTER_APPS_WRITE_SETTINGS = 15;
+-    public static final int FILTER_APPS_SUBSTRATUM = 16;
++    public static final int FILTER_APPS_SUBSTRATUM_ICONS = 16;
++    public static final int FILTER_APPS_SUBSTRATUM = 17;
+     // This is the string labels for the filter modes above, the order must be kept in sync.
+     public static final int[] FILTER_LABELS = new int[]{
+@@ -191,6 +193,7 @@ public class ManageApplications extends InstrumentedFragment
+     // whether showing substratum overlays.
+     private boolean mShowSubstratum;
++    private boolean mShowSubstratumIcons;
+     private ApplicationsState mApplicationsState;
+@@ -282,6 +285,8 @@ public class ManageApplications extends InstrumentedFragment
+             mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
+             mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
+             mShowSubstratum = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
++            mShowSubstratumIcons = savedInstanceState.getBoolean(EXTRA_SHOW_SUBSTRATUM_ICONS,
++                                                                 mShowSubstratumIcons);
+         }
+         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
+@@ -447,6 +452,7 @@ public class ManageApplications extends InstrumentedFragment
+         outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
+         outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
+         outState.putBoolean(EXTRA_SHOW_SUBSTRATUM, mShowSubstratum);
++        outState.putBoolean(EXTRA_SHOW_SUBSTRATUM_ICONS, mShowSubstratumIcons);
+         outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
+         outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
+     }
+@@ -570,6 +576,10 @@ public class ManageApplications extends InstrumentedFragment
+                 && mListType != LIST_TYPE_HIGH_POWER);
+         mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
+                 && mListType != LIST_TYPE_HIGH_POWER);
++        mOptionsMenu.findItem(R.id.show_substratum_icons).setVisible(!mShowSubstratumIcons
++                && mListType != LIST_TYPE_HIGH_POWER);
++        mOptionsMenu.findItem(R.id.hide_substratum_icons).setVisible(mShowSubstratumIcons
++                && mListType != LIST_TYPE_HIGH_POWER);
+     }
+     @Override
+@@ -594,6 +604,11 @@ public class ManageApplications extends InstrumentedFragment
+                 mShowSubstratum = !mShowSubstratum;
+                 mApplications.rebuild(false);
+                 break;
++            case R.id.show_substratum_icons:
++            case R.id.hide_substratum_icons:
++                mShowSubstratumIcons = !mShowSubstratumIcons;
++                mApplications.rebuild(false);
++                break;
+             case R.id.reset_app_preferences:
+                 mResetAppsHelper.buildResetDialog();
+                 return true;
+@@ -882,17 +897,17 @@ public class ManageApplications extends InstrumentedFragment
+             if (mOverrideFilter != null) {
+                 filterObj = mOverrideFilter;
+             }
+-            if (!mManageApplications.mShowSystem && !mManageApplications.mShowSubstratum) {
+-                filterObj = new CompoundFilter(filterObj,
+-                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
++            if (!mManageApplications.mShowSystem) {
+                 filterObj = new CompoundFilter(filterObj,
+-                        ApplicationsState.FILTER_SUBSTRATUM);
+-            } else if (!mManageApplications.mShowSystem) {
++                                               ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
++            }
++            if (!mManageApplications.mShowSubstratum) {
+                 filterObj = new CompoundFilter(filterObj,
+-                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
+-            } else if (!mManageApplications.mShowSubstratum) {
++                                               ApplicationsState.FILTER_SUBSTRATUM);
++            }
++            if (!mManageApplications.mShowSubstratumIcons) {
+                 filterObj = new CompoundFilter(filterObj,
+-                        ApplicationsState.FILTER_SUBSTRATUM);
++                                               ApplicationsState.FILTER_SUBSTRATUM_ICONS);
+             }
+             switch (mLastSortMode) {
+                 case R.id.sort_order_size:
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch b/patches/packages/apps/Settings/0009-Exclude-overlays-from-the-app-counter.patch
new file mode 100644 (file)
index 0000000..f140374
--- /dev/null
@@ -0,0 +1,49 @@
+From 9e3533dad0365c72196f773688d54061572943ca Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Fri, 9 Dec 2016 02:19:20 +0100
+Subject: [PATCH 09/15] Exclude overlays from the app counter
+
+This exclude overlays from the app counter that shows
+in manage app summary.
+
+idea from @KreAch3R
+
+Change-Id: I8cd591dc89eb87057e8c2ae3b2cca2c76c34534b
+(cherry picked from commit 990eeb53387bbd52e76ce7e7b45c171d1e01e7a1)
+---
+ src/com/android/settings/applications/AppCounter.java         | 1 +
+ src/com/android/settings/applications/ManageApplications.java | 6 ++++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
+index fb8d580..852358d 100644
+--- a/src/com/android/settings/applications/AppCounter.java
++++ b/src/com/android/settings/applications/AppCounter.java
+@@ -47,6 +47,7 @@ public abstract class AppCounter extends AsyncTask<Void, Void, Integer> {
+                 ParceledListSlice<ApplicationInfo> list =
+                         mIpm.getInstalledApplications(PackageManager.GET_DISABLED_COMPONENTS
+                                 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
++                                | PackageManager.GET_META_DATA
+                                 | (user.isAdmin() ? PackageManager.GET_UNINSTALLED_PACKAGES : 0),
+                                 user.id);
+                 for (ApplicationInfo info : list.getList()) {
+diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
+index 5d3b353..ed61781 100644
+--- a/src/com/android/settings/applications/ManageApplications.java
++++ b/src/com/android/settings/applications/ManageApplications.java
+@@ -1297,6 +1297,12 @@ public class ManageApplications extends InstrumentedFragment
+                         if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+                             return true;
+                         } else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
++                            if (info.metaData != null) {
++                                if (info.metaData.getString("Substratum_Parent") != null
++                                        || info.metaData.getString("Substratum_IconPack") != null) {
++                                    return false;
++                                }
++                            }
+                             return true;
+                         }
+                         Intent launchIntent = new Intent(Intent.ACTION_MAIN, null)
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch b/patches/packages/apps/Settings/0010-Hide-the-show-hide-overlays-when-no-overlay-installe.patch
new file mode 100644 (file)
index 0000000..6c5bcb3
--- /dev/null
@@ -0,0 +1,86 @@
+From 6e982674f97c80b325d739c417c95734991f1eaa Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Wed, 14 Dec 2016 14:58:54 +0100
+Subject: [PATCH 10/15] Hide the "show/hide overlays" when no overlay installed
+
+Change-Id: I54088d27c9492e0992992de59bf340fe2465260a
+---
+ .../settings/applications/ManageApplications.java  | 38 +++++++++++++++++++---
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
+index ed61781..c3bc4d4 100644
+--- a/src/com/android/settings/applications/ManageApplications.java
++++ b/src/com/android/settings/applications/ManageApplications.java
+@@ -195,6 +195,10 @@ public class ManageApplications extends InstrumentedFragment
+     private boolean mShowSubstratum;
+     private boolean mShowSubstratumIcons;
++    // if app and icon overlay installed
++    private boolean mAppOverlayInstalled;
++    private boolean mIconOverlayInstalled;
++
+     private ApplicationsState mApplicationsState;
+     public int mListType;
+@@ -556,6 +560,9 @@ public class ManageApplications extends InstrumentedFragment
+     }
+     void updateOptionsMenu() {
++        mAppOverlayInstalled = isOverlayInstalled("app");
++        mIconOverlayInstalled = isOverlayInstalled("icon");
++
+         if (mOptionsMenu == null) {
+             return;
+         }
+@@ -573,13 +580,13 @@ public class ManageApplications extends InstrumentedFragment
+                 && mListType != LIST_TYPE_HIGH_POWER);
+         mOptionsMenu.findItem(R.id.show_substratum).setVisible(!mShowSubstratum
+-                && mListType != LIST_TYPE_HIGH_POWER);
++                && mListType != LIST_TYPE_HIGH_POWER && mAppOverlayInstalled);
+         mOptionsMenu.findItem(R.id.hide_substratum).setVisible(mShowSubstratum
+-                && mListType != LIST_TYPE_HIGH_POWER);
++                && mListType != LIST_TYPE_HIGH_POWER && mAppOverlayInstalled);
+         mOptionsMenu.findItem(R.id.show_substratum_icons).setVisible(!mShowSubstratumIcons
+-                && mListType != LIST_TYPE_HIGH_POWER);
++                && mListType != LIST_TYPE_HIGH_POWER && mIconOverlayInstalled);
+         mOptionsMenu.findItem(R.id.hide_substratum_icons).setVisible(mShowSubstratumIcons
+-                && mListType != LIST_TYPE_HIGH_POWER);
++                && mListType != LIST_TYPE_HIGH_POWER && mIconOverlayInstalled);
+     }
+     @Override
+@@ -668,6 +675,29 @@ public class ManageApplications extends InstrumentedFragment
+         mFilterAdapter.setFilterEnabled(FILTER_APPS_DISABLED, hasDisabledApps);
+     }
++    boolean isOverlayInstalled(String type) {
++        List<ApplicationInfo> packages = getActivity().getPackageManager()
++                .getInstalledApplications(PackageManager.GET_META_DATA);
++
++        for (ApplicationInfo packageInfo : packages) {
++            if (packageInfo.metaData != null) {
++                if (type.equals("app")) {
++                    if (packageInfo.metaData
++                                    .getString("Substratum_Parent") != null) {
++                        return true;
++                    }
++                }
++                if (type.equals("icon")) {
++                    if (packageInfo.metaData
++                                    .getString("Substratum_IconPack") != null) {
++                        return true;
++                    }
++                }
++            }
++        }
++        return false;
++    }
++
+     static class FilterSpinnerAdapter extends ArrayAdapter<CharSequence> {
+         private final ManageApplications mManageApplications;
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch b/patches/packages/apps/Settings/0011-Expose-color-for-external-settings-icons.patch
new file mode 100644 (file)
index 0000000..67df099
--- /dev/null
@@ -0,0 +1,77 @@
+From f50ef9c89b3cd4ae9d66e885b2d406fdad3931be Mon Sep 17 00:00:00 2001
+From: Clark Scheff <clark@scheffsblend.com>
+Date: Fri, 23 Dec 2016 09:52:57 -0500
+Subject: [PATCH 11/15] Expose color for external settings icons
+
+Marhsmallow now allows for system apps to add settings.  An icon is
+loaded from the external package and a tint is applied to the icon
+so that it matches other icons in the dashboard.  The tint color
+uses the colorAccent attribute from the currently applied style.
+Themes can overlay the colorAccent but this color is also used for
+other elements of the UI which may not be ideal.
+
+This patch adds a new color external_tile_icon_tint_color which
+points to the attribute ?android:attr/colorAccent when not themed.
+This retains the original look but offers better flexibility for
+theme designers.
+
+- Ported up to 7.1.1
+
+Change-Id: Ifb4a99a315271cdcf978a796e3dea0eaef8d7750
+---
+ res/values/projekt_colors.xml                            |  4 +++-
+ src/com/android/settings/dashboard/DashboardAdapter.java | 14 +++++++++-----
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index e1977f9..4ecd1b2 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -39,9 +39,11 @@
+     <color name="storage_private_3">#fff2a600</color>
+     <color name="storage_private_4">#ffec407a</color>
+     <color name="storage_private_5">#ffc0ca33</color>
+-
+     <!-- Linear color bar -->
+     <color name="linear_color_bar_left">@*android:color/accent_device_default_light</color>
+     <color name="linear_color_bar_middle">@*android:color/accent_device_default_light</color>
+     <color name="linear_color_bar_right">#ffced7db</color>
++
++    <!-- External Icon Tint -->
++    <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
+ </resources>
+diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
+index 6b2e145..c29da43 100644
+--- a/src/com/android/settings/dashboard/DashboardAdapter.java
++++ b/src/com/android/settings/dashboard/DashboardAdapter.java
+@@ -114,10 +114,10 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
+         mSuggestions = suggestions;
+         mCategories = categories;
+-        // TODO: Better place for tinting?
+-        TypedValue tintColor = new TypedValue();
+-        mContext.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
+-                tintColor, true);
++        TypedValue tintColorValue = new TypedValue();
++        mContext.getResources().getValue(R.color.external_tile_icon_tint_color,
++                tintColorValue, true);
++
+         for (int i = 0; i < categories.size(); i++) {
+             for (int j = 0; j < categories.get(i).tiles.size(); j++) {
+                 Tile tile = categories.get(i).tiles.get(j);
+@@ -126,7 +126,11 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
+                         tile.intent.getComponent().getPackageName())) {
+                     // If this drawable is coming from outside Settings, tint it to match the
+                     // color.
+-                    tile.icon.setTint(tintColor.data);
++                    if (tintColorValue.type == TypedValue.TYPE_ATTRIBUTE) {
++                        mContext.getTheme().resolveAttribute(tintColorValue.data,
++                                tintColorValue, true);
++                    }
++                    tile.icon.setTint(tintColorValue.data);
+                 }
+             }
+         }
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch b/patches/packages/apps/Settings/0012-Expose-dashboard-category-padding-bottom.patch
new file mode 100644 (file)
index 0000000..192868c
--- /dev/null
@@ -0,0 +1,50 @@
+From 0d488d0698cb80ee8236743a8be9300c7c807917 Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Sun, 8 Jan 2017 00:18:47 +0100
+Subject: [PATCH 12/15] Expose dashboard category padding bottom
+
+Change-Id: I5a0d3266bbe96dbe6a136f78ed84cb1ee0a6a19b
+---
+ res/layout/dashboard_category.xml |  2 +-
+ res/values/projekt_dimens.xml     | 16 ++++++++++++++++
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+ create mode 100644 res/values/projekt_dimens.xml
+
+diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
+index 7836644..86dac35 100644
+--- a/res/layout/dashboard_category.xml
++++ b/res/layout/dashboard_category.xml
+@@ -19,7 +19,7 @@
+     android:layout_width="match_parent"
+     android:layout_height="@dimen/dashboard_category_height"
+     android:orientation="vertical"
+-    android:paddingBottom="8dip"
++    android:paddingBottom="@dimen/dashboard_category_padding_bottom"
+     android:background="@drawable/dashboard_category_title_bg">
+     <TextView android:id="@android:id/title"
+diff --git a/res/values/projekt_dimens.xml b/res/values/projekt_dimens.xml
+new file mode 100644
+index 0000000..a5aae4e
+--- /dev/null
++++ b/res/values/projekt_dimens.xml
+@@ -0,0 +1,16 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!--
++    Copyright (c) 2017 Projekt Substratum
++    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>
++    <dimen name="dashboard_category_padding_bottom">8dip</dimen>
++</resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0013-Expose-switchbar-background-color.patch b/patches/packages/apps/Settings/0013-Expose-switchbar-background-color.patch
new file mode 100644 (file)
index 0000000..4609b94
--- /dev/null
@@ -0,0 +1,77 @@
+From 1fd8e4207626877ebf22d1c6b258fade0790a704 Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Sun, 8 Jan 2017 01:22:47 +0100
+Subject: [PATCH 13/15] Expose switchbar background color
+
+Change-Id: Idc8b09c921bb57c9464d6ea956cfdd9b2b95e6a8
+---
+ res/values/projekt_colors.xml                  |  2 ++
+ res/values/themes.xml                          |  4 ++--
+ src/com/android/settings/widget/SwitchBar.java | 11 ++++++++++-
+ 3 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index 4ecd1b2..f37cc54 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -46,4 +46,6 @@
+     <!-- External Icon Tint -->
+     <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
++    <!-- Settings switchbar background -->
++    <color name="switchbar_background_color">?android:attr/colorSecondary</color>
+ </resources>
+diff --git a/res/values/themes.xml b/res/values/themes.xml
+index ffe802e..acabe21 100644
+--- a/res/values/themes.xml
++++ b/res/values/themes.xml
+@@ -196,13 +196,13 @@
+     <style name="ThemeOverlay.SwitchBar.Settings" parent="@*android:style/ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent">
+         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
+         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
+-        <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
++        <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
+     </style>
+     <style name="ThemeOverlay.SwitchBar.SubSettings" parent="@android:style/ThemeOverlay.Material.Dark.ActionBar">
+         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
+         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
+-        <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
++        <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
+     </style>
+     <style name="Theme.DialogWhenLarge" parent="@*android:style/Theme.DeviceDefault.Settings.DialogWhenLarge">
+diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
+index 240c062..ce73a39 100644
+--- a/src/com/android/settings/widget/SwitchBar.java
++++ b/src/com/android/settings/widget/SwitchBar.java
+@@ -24,6 +24,7 @@ import android.text.SpannableStringBuilder;
+ import android.text.TextUtils;
+ import android.text.style.TextAppearanceSpan;
+ import android.util.AttributeSet;
++import android.util.TypedValue;
+ import android.view.LayoutInflater;
+ import android.view.View;
+ import android.view.ViewGroup;
+@@ -96,9 +97,17 @@ public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedC
+         final TypedArray a = context.obtainStyledAttributes(attrs, XML_ATTRIBUTES);
+         int switchBarMarginStart = (int) a.getDimension(0, 0);
+         int switchBarMarginEnd = (int) a.getDimension(1, 0);
+-        int switchBarBackgroundColor = (int) a.getColor(2, 0);
+         a.recycle();
++        TypedValue backgroundColorValue = new TypedValue();
++        mContext.getResources().getValue(R.color.switchbar_background_color,
++                backgroundColorValue, true);
++        if (backgroundColorValue.type == TypedValue.TYPE_ATTRIBUTE) {
++            context.getTheme().resolveAttribute(backgroundColorValue.data,
++                    backgroundColorValue, true);
++        }
++        int switchBarBackgroundColor = backgroundColorValue.data;
++
+         mTextView = (TextView) findViewById(R.id.switch_text);
+         mTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+         mLabel = getResources().getString(R.string.switch_off_text);
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch b/patches/packages/apps/Settings/0014-Settings-Expose-bluetooth-pin-confirm-dialog-text-co.patch
new file mode 100644 (file)
index 0000000..b17f145
--- /dev/null
@@ -0,0 +1,60 @@
+From 1edcfb911d77e894086bf88ac47f966a8b88fb22 Mon Sep 17 00:00:00 2001
+From: SpiritCroc <spiritcroc@gmail.com>
+Date: Sun, 22 Jan 2017 20:51:47 +0100
+Subject: [PATCH 14/15] Settings: Expose bluetooth pin confirm dialog text
+ colors
+
+Change-Id: I1e1eb2da23f2470a82574da7ef326d56f770eb95
+---
+ res/layout/bluetooth_pin_confirm.xml | 6 +++---
+ res/values/projekt_colors.xml        | 5 +++++
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/res/layout/bluetooth_pin_confirm.xml b/res/layout/bluetooth_pin_confirm.xml
+index ebdf65d..6609a1b 100644
+--- a/res/layout/bluetooth_pin_confirm.xml
++++ b/res/layout/bluetooth_pin_confirm.xml
+@@ -40,7 +40,7 @@
+             android:text="@string/bluetooth_pairing_key_msg"
+             android:visibility="gone"
+             android:textAppearance="@android:style/TextAppearance.Material.Body1"
+-            android:textColor="@*android:color/secondary_text_material_light"  />
++            android:textColor="@color/bluetooth_pairing_caption"  />
+         <TextView
+             android:id="@+id/pairing_subhead"
+@@ -63,7 +63,7 @@
+             android:gravity="center_vertical"
+             android:text="@string/bluetooth_enter_passkey_msg"
+             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+-            android:textColor="@*android:color/secondary_text_material_light"
++            android:textColor="@color/bluetooth_pairing_code_message"
+             android:visibility="gone" />
+         <CheckBox
+@@ -73,7 +73,7 @@
+             android:layout_marginStart="@dimen/bluetooth_dialog_padding"
+             android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+             android:textAppearance="@android:style/TextAppearance.Material.Body1"
+-            android:textColor="@*android:color/secondary_text_material_light"  />
++            android:textColor="@color/bluetooth_phonebook_sharing_message_confirm_pin"  />
+     </LinearLayout>
+diff --git a/res/values/projekt_colors.xml b/res/values/projekt_colors.xml
+index f37cc54..e0d3ab1 100644
+--- a/res/values/projekt_colors.xml
++++ b/res/values/projekt_colors.xml
+@@ -48,4 +48,9 @@
+     <color name="external_tile_icon_tint_color">?android:attr/colorAccent</color>
+     <!-- Settings switchbar background -->
+     <color name="switchbar_background_color">?android:attr/colorSecondary</color>
++
++    <!-- Bluetooth pairing pin confirm dialog -->
++    <color name="bluetooth_pairing_caption">@*android:color/secondary_text_material_light</color>
++    <color name="bluetooth_pairing_code_message">@*android:color/secondary_text_material_light</color>
++    <color name="bluetooth_phonebook_sharing_message_confirm_pin">@*android:color/secondary_text_material_light</color>
+ </resources>
+-- 
+2.9.3
+
diff --git a/patches/packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch b/patches/packages/apps/Settings/0015-Set-external-settings-icon-tint-mode-to-SRC_ATOP.patch
new file mode 100644 (file)
index 0000000..5cdcb63
--- /dev/null
@@ -0,0 +1,42 @@
+From 9bb5dca50887734bbc12e46254464f1d0734ac6f Mon Sep 17 00:00:00 2001
+From: Ivan Iskandar <iiiiskandar14@gmail.com>
+Date: Sat, 28 Jan 2017 13:40:55 +0100
+Subject: [PATCH 15/15] Set external settings icon tint mode to SRC_ATOP
+
+With "Expose color for external settings icons" commit, themers can change
+the color of the external settings icon to whatever they want except
+transparent. When they set the tint color to transparent the icon will be
+dissapeared, this commits fixed the problem by changing the tint mode.
+
+Before: http://i.imgur.com/ghDPs27.jpg
+After: http://i.imgur.com/AUEFgNO.jpg
+
+Change-Id: I65b710e2abefd1052b3af154a98247de9b4fe98d
+---
+ src/com/android/settings/dashboard/DashboardAdapter.java | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
+index c29da43..8259d39 100644
+--- a/src/com/android/settings/dashboard/DashboardAdapter.java
++++ b/src/com/android/settings/dashboard/DashboardAdapter.java
+@@ -19,6 +19,7 @@ import android.content.Context;
+ import android.content.pm.PackageManager;
+ import android.graphics.drawable.Drawable;
+ import android.graphics.drawable.Icon;
++import android.graphics.PorterDuff.Mode;
+ import android.os.Bundle;
+ import android.support.v7.widget.PopupMenu;
+ import android.support.v7.widget.RecyclerView;
+@@ -130,7 +131,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
+                         mContext.getTheme().resolveAttribute(tintColorValue.data,
+                                 tintColorValue, true);
+                     }
+-                    tile.icon.setTint(tintColorValue.data);
++                    tile.icon.setTint(tintColorValue.data).setTintMode(Mode.SRC_ATOP);
+                 }
+             }
+         }
+-- 
+2.9.3
+
diff --git a/patches/system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch b/patches/system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch
new file mode 100644 (file)
index 0000000..de0c721
--- /dev/null
@@ -0,0 +1,59 @@
+From 1563cb90a0c8268564552bdd068410cd56079599 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
+Date: Mon, 22 Jun 2015 09:31:25 +0200
+Subject: [PATCH] OMS-N: Add service 'overlay' to service_contexts
+
+The 'overlay' service is the Overlay Manager Service, which tracks
+packages and their Runtime Resource Overlay overlay packages.
+
+Bug: 31052947
+
+Co-authored-by: Martin Wallgren <martin.wallgren@sonymobile.com>
+Signed-off-by: Zoran Jovanovic <zoran.jovanovic@sonymobile.com>
+
+Change-Id: Ie996707dd02166325271bee49163ac263e560a1d
+---
+ service.te       | 1 +
+ service_contexts | 1 +
+ system_server.te | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/service.te b/service.te
+index e7a30f9..6f9ab3f 100644
+--- a/service.te
++++ b/service.te
+@@ -81,6 +81,7 @@ type network_score_service, system_api_service, system_server_service, service_m
+ type network_time_update_service, system_server_service, service_manager_type;
+ type notification_service, app_api_service, system_server_service, service_manager_type;
+ type otadexopt_service, system_server_service, service_manager_type;
++type overlay_service, app_api_service, system_server_service, service_manager_type;
+ type package_service, app_api_service, system_server_service, service_manager_type;
+ type permission_service, app_api_service, system_server_service, service_manager_type;
+ type persistent_data_block_service, system_api_service, system_server_service, service_manager_type;
+diff --git a/service_contexts b/service_contexts
+index dd7e49f..b7d7473 100644
+--- a/service_contexts
++++ b/service_contexts
+@@ -93,6 +93,7 @@ network_time_update_service               u:object_r:network_time_update_service
+ nfc                                       u:object_r:nfc_service:s0
+ notification                              u:object_r:notification_service:s0
+ otadexopt                                 u:object_r:otadexopt_service:s0
++overlay                                   u:object_r:overlay_service:s0
+ package                                   u:object_r:package_service:s0
+ permission                                u:object_r:permission_service:s0
+ persistent_data_block                     u:object_r:persistent_data_block_service:s0
+diff --git a/system_server.te b/system_server.te
+index 03a7ef3..3ca8182 100644
+--- a/system_server.te
++++ b/system_server.te
+@@ -441,6 +441,7 @@ allow system_server mediacodec_service:service_manager find;
+ allow system_server mediadrmserver_service:service_manager find;
+ allow system_server netd_service:service_manager find;
+ allow system_server nfc_service:service_manager find;
++allow system_server overlay_service:service_manager find;
+ allow system_server radio_service:service_manager find;
+ allow system_server system_server_service:service_manager { add find };
+ allow system_server surfaceflinger_service:service_manager find;
+-- 
+2.9.3
+
diff --git a/product.mk b/product.mk
new file mode 100644 (file)
index 0000000..74c886d
--- /dev/null
@@ -0,0 +1,3 @@
+# Masquerade
+PRODUCT_PACKAGES += \
+    masquerade
diff --git a/system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch b/system/sepolicy/0001-OMS-N-Add-service-overlay-to-service_contexts.patch
deleted file mode 100644 (file)
index de0c721..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 1563cb90a0c8268564552bdd068410cd56079599 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?M=C3=A5rten=20Kongstad?= <marten.kongstad@sonymobile.com>
-Date: Mon, 22 Jun 2015 09:31:25 +0200
-Subject: [PATCH] OMS-N: Add service 'overlay' to service_contexts
-
-The 'overlay' service is the Overlay Manager Service, which tracks
-packages and their Runtime Resource Overlay overlay packages.
-
-Bug: 31052947
-
-Co-authored-by: Martin Wallgren <martin.wallgren@sonymobile.com>
-Signed-off-by: Zoran Jovanovic <zoran.jovanovic@sonymobile.com>
-
-Change-Id: Ie996707dd02166325271bee49163ac263e560a1d
----
- service.te       | 1 +
- service_contexts | 1 +
- system_server.te | 1 +
- 3 files changed, 3 insertions(+)
-
-diff --git a/service.te b/service.te
-index e7a30f9..6f9ab3f 100644
---- a/service.te
-+++ b/service.te
-@@ -81,6 +81,7 @@ type network_score_service, system_api_service, system_server_service, service_m
- type network_time_update_service, system_server_service, service_manager_type;
- type notification_service, app_api_service, system_server_service, service_manager_type;
- type otadexopt_service, system_server_service, service_manager_type;
-+type overlay_service, app_api_service, system_server_service, service_manager_type;
- type package_service, app_api_service, system_server_service, service_manager_type;
- type permission_service, app_api_service, system_server_service, service_manager_type;
- type persistent_data_block_service, system_api_service, system_server_service, service_manager_type;
-diff --git a/service_contexts b/service_contexts
-index dd7e49f..b7d7473 100644
---- a/service_contexts
-+++ b/service_contexts
-@@ -93,6 +93,7 @@ network_time_update_service               u:object_r:network_time_update_service
- nfc                                       u:object_r:nfc_service:s0
- notification                              u:object_r:notification_service:s0
- otadexopt                                 u:object_r:otadexopt_service:s0
-+overlay                                   u:object_r:overlay_service:s0
- package                                   u:object_r:package_service:s0
- permission                                u:object_r:permission_service:s0
- persistent_data_block                     u:object_r:persistent_data_block_service:s0
-diff --git a/system_server.te b/system_server.te
-index 03a7ef3..3ca8182 100644
---- a/system_server.te
-+++ b/system_server.te
-@@ -441,6 +441,7 @@ allow system_server mediacodec_service:service_manager find;
- allow system_server mediadrmserver_service:service_manager find;
- allow system_server netd_service:service_manager find;
- allow system_server nfc_service:service_manager find;
-+allow system_server overlay_service:service_manager find;
- allow system_server radio_service:service_manager find;
- allow system_server system_server_service:service_manager { add find };
- allow system_server surfaceflinger_service:service_manager find;
--- 
-2.9.3
-