From 5f773b766d27b6766a6cebe53a32ac5d6e47843d Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Tue, 24 Oct 2017 16:07:18 -0700 Subject: [PATCH 01/38] mtp: fix double free of thumbnail data bug: 67864232 Change-Id: I6eb51be839df12317273830521c70a4ed80f9496 (cherry picked from commit e6b98532ee03d0ac1ca93382699893172454a946) --- media/jni/android_mtp_MtpDatabase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index 5b874cd82678..47ec4648f125 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -951,6 +951,7 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) outThumbSize = image_data.thumbnail.length; } else { free(result); + result = NULL; } } break; From c7673337fb3cff3bb994b50f9a7482afcdb4912b Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Tue, 3 Oct 2017 14:00:20 -0400 Subject: [PATCH 02/38] Throw OOME if Bitmap.nativeCreate fails Bug:33846679 Test: I6ab6cb7a3b3151641a9f9b02b0bfc484e0a4524b This matches the old behavior, prior to switching from Java allocated pixel memory to native allocations (b/27762775). It also better matches what has happened - we ran out of memory. (Better than the current behavior - NullPointerException in the Java code, or an alternative solution of returning null, which would likely result in NPEs in the calling code.) Merged-In: I3958ed1106ac94fb1d3f30e044b620d984875211 Change-Id: I3958ed1106ac94fb1d3f30e044b620d984875211 (cherry picked from commit 5906a4869cdf5c39eba1d9a3125aff894c5e804d) --- core/jni/android/graphics/Bitmap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index ad05a5113dff..108fdbce386f 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -682,6 +682,8 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, sk_sp nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap); if (!nativeBitmap) { + ALOGE("OOM allocating Bitmap with dimensions %i x %i", width, height); + doThrowOOME(env); return NULL; } From 949c64bd7044912de4fa9cca1fe869a0e43608c3 Mon Sep 17 00:00:00 2001 From: Adam Vartanian Date: Tue, 7 Nov 2017 12:22:23 +0000 Subject: [PATCH 03/38] Adjust Uri host parsing to use last instead of first @. Malformed authority segments can currently cause the parser to produce a hostname that doesn't match the hostname produced by the WHATWG URL parsing algorithm* used by browsers, which means that a URL could be seen as having a "safe" host when checked by an Android app but actually visit a different host when passed to a browser. The WHATWG URL parsing algorithm always produces a hostname based on the last @ in the authority segment, so we do the same. * https://url.spec.whatwg.org/#authority-state resets the "buffer", which is being used to build up the host name, each time an @ is found, so it has the effect of using the content between the final @ and the end of the authority section as the hostname. Bug: 68341964 Test: vogar android.net.UriTest (on NYC branch) Test: cts -m CtsNetTestCases (on NYC branch) Change-Id: Idca79f35a886de042c94d6ab66787c2e98ac8376 (cherry picked from commit cd6228dd377b2a0caa02a1e6df92f3d9ae702a95) --- core/java/android/net/Uri.java | 6 +++--- core/tests/coretests/src/android/net/UriTest.java | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index d5377c717366..9edcc0e9b8d4 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -1066,7 +1066,7 @@ private String parseUserInfo() { return null; } - int end = authority.indexOf('@'); + int end = authority.lastIndexOf('@'); return end == NOT_FOUND ? null : authority.substring(0, end); } @@ -1090,7 +1090,7 @@ private String parseHost() { } // Parse out user info and then port. - int userInfoSeparator = authority.indexOf('@'); + int userInfoSeparator = authority.lastIndexOf('@'); int portSeparator = authority.indexOf(':', userInfoSeparator); String encodedHost = portSeparator == NOT_FOUND @@ -1116,7 +1116,7 @@ private int parsePort() { // Make sure we look for the port separtor *after* the user info // separator. We have URLs with a ':' in the user info. - int userInfoSeparator = authority.indexOf('@'); + int userInfoSeparator = authority.lastIndexOf('@'); int portSeparator = authority.indexOf(':', userInfoSeparator); if (portSeparator == NOT_FOUND) { diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java index 6fa28b1ccdaa..27b7f9e185bb 100644 --- a/core/tests/coretests/src/android/net/UriTest.java +++ b/core/tests/coretests/src/android/net/UriTest.java @@ -187,6 +187,11 @@ public void testAuthorityParsing() { uri = Uri.parse("http://localhost"); assertEquals("localhost", uri.getHost()); assertEquals(-1, uri.getPort()); + + uri = Uri.parse("http://a:a@example.com:a@example2.com/path"); + assertEquals("a:a@example.com:a@example2.com", uri.getAuthority()); + assertEquals("example2.com", uri.getHost()); + assertEquals(-1, uri.getPort()); } @SmallTest From 5025791ac6d1538224e19189397de8d71dcb1a12 Mon Sep 17 00:00:00 2001 From: Rubin Xu Date: Tue, 31 Oct 2017 15:40:32 +0000 Subject: [PATCH 04/38] Swap the order of synthetic password wrapping Synthetic password is double encrypted by both a random auth-bound keymaster key and a secret derived from user password. In order to avoid a password verification oracle without rate limiting, synthetic password needs to be encrypted by the derived secret first, and then the auth-bound key. This change corrects the order of encryptions, as well as adds an upgrade path to refresh existing credentials. Test: Running an old build with existing password, flash to new build, verify the device unlocks successfully. Bug: 68694819 Change-Id: Ifdaa01f3f4ddd5bb3f3d808d38f440ced729034f Merged-In: Ifdaa01f3f4ddd5bb3f3d808d38f440ced729034f (cherry picked from commit 78acfe71d5d527ec727ffa3ad33f0de6255d60d7) --- .../locksettings/SyntheticPasswordCrypto.java | 21 ++++++++++++--- .../SyntheticPasswordManager.java | 27 ++++++++++++++----- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java index b7bca1fb1c4a..ef94000d3a6b 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java @@ -112,7 +112,7 @@ public static byte[] decrypt(byte[] keyBytes, byte[] personalisation, byte[] cip } } - public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) { + public static byte[] decryptBlobV1(String keyAlias, byte[] blob, byte[] applicationId) { try { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); @@ -120,6 +120,20 @@ public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicatio SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null); byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob); return decrypt(decryptionKey, intermediate); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to decrypt blob", e); + } + } + + public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) { + try { + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + + SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null); + byte[] intermediate = decrypt(decryptionKey, blob); + return decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate); } catch (CertificateException | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException @@ -150,9 +164,8 @@ public static byte[] createBlob(String keyAlias, byte[] data, byte[] application keyStore.setEntry(keyAlias, new KeyStore.SecretKeyEntry(secretKey), builder.build()); - byte[] intermediate = encrypt(secretKey, data); - return encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate); - + byte[] intermediate = encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, data); + return encrypt(secretKey, intermediate); } catch (CertificateException | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 9440f17164aa..ca6c9e78d0a2 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -101,7 +101,8 @@ public class SyntheticPasswordManager { private static final byte WEAVER_VERSION = 1; private static final int INVALID_WEAVER_SLOT = -1; - private static final byte SYNTHETIC_PASSWORD_VERSION = 1; + private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1; + private static final byte SYNTHETIC_PASSWORD_VERSION = 2; private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0; private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1; @@ -792,6 +793,7 @@ public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperServ byte[] pwdToken = computePasswordToken(credential, pwd); final byte[] applicationId; + final long sid; int weaverSlot = loadWeaverSlot(handle, userId); if (weaverSlot != INVALID_WEAVER_SLOT) { // Weaver based user password @@ -804,6 +806,7 @@ public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperServ if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { return result; } + sid = GateKeeper.INVALID_SECURE_USER_ID; applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload()); } else { byte[] gkPwdToken = passwordTokenToGkInput(pwdToken); @@ -836,12 +839,13 @@ public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperServ result.gkResponse = VerifyCredentialResponse.ERROR; return result; } + sid = sidFromPasswordHandle(pwd.passwordHandle); applicationId = transformUnderSecdiscardable(pwdToken, loadSecdiscardable(handle, userId)); } result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED, - applicationId, userId); + applicationId, sid, userId); // Perform verifyChallenge to refresh auth tokens for GK if user password exists. result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId); @@ -877,7 +881,7 @@ public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperServ } byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable); result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED, - applicationId, userId); + applicationId, 0L, userId); if (result.authToken != null) { result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId); if (result.gkResponse == null) { @@ -892,19 +896,26 @@ public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperServ } private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type, - byte[] applicationId, int userId) { + byte[] applicationId, long sid, int userId) { byte[] blob = loadState(SP_BLOB_NAME, handle, userId); if (blob == null) { return null; } - if (blob[0] != SYNTHETIC_PASSWORD_VERSION) { + final byte version = blob[0]; + if (version != SYNTHETIC_PASSWORD_VERSION && version != SYNTHETIC_PASSWORD_VERSION_V1) { throw new RuntimeException("Unknown blob version"); } if (blob[1] != type) { throw new RuntimeException("Invalid blob type"); } - byte[] secret = decryptSPBlob(getHandleName(handle), + final byte[] secret; + if (version == SYNTHETIC_PASSWORD_VERSION_V1) { + secret = SyntheticPasswordCrypto.decryptBlobV1(getHandleName(handle), + Arrays.copyOfRange(blob, 2, blob.length), applicationId); + } else { + secret = decryptSPBlob(getHandleName(handle), Arrays.copyOfRange(blob, 2, blob.length), applicationId); + } if (secret == null) { Log.e(TAG, "Fail to decrypt SP for user " + userId); return null; @@ -919,6 +930,10 @@ private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type, } else { result.syntheticPassword = new String(secret); } + if (version == SYNTHETIC_PASSWORD_VERSION_V1) { + Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type); + createSyntheticPasswordBlob(handle, type, result, applicationId, sid, userId); + } return result; } From 7a722dcae9ac38887e4ae9d43ed22aea68ab828c Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Tue, 14 Nov 2017 00:50:18 -0800 Subject: [PATCH 05/38] OMS: Only allow trusted overlays to be registered. Bug: 69383160 Test: cts-tradefed run cts -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.OverlayHostTest Change-Id: I930c11716317cff1ec485a3943d1f22f07a423df Merged-In: I930c11716317cff1ec485a3943d1f22f07a423df (cherry picked from commit 80609e584c9c6155ed3199109735ec8d16f6115c) --- core/java/android/content/pm/PackageInfo.java | 26 ++++++++++++++++--- .../android/content/pm/PackageParser.java | 10 ++++++- .../server/om/OverlayManagerService.java | 3 ++- .../server/om/OverlayManagerServiceImpl.java | 22 ++++++++++------ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index ba488f6a0518..3230ee715571 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -286,8 +286,26 @@ public class PackageInfo implements Parcelable { /** @hide */ public int overlayPriority; - /** @hide */ - public boolean isStaticOverlay; + + /** + * Flag for use with {@link #overlayFlags}. Marks the overlay as static, meaning it cannot + * be enabled/disabled at runtime. + * @hide + */ + public static final int FLAG_OVERLAY_STATIC = 1 << 1; + + /** + * Flag for use with {@link #overlayFlags}. Marks the overlay as trusted (not 3rd party). + * @hide + */ + public static final int FLAG_OVERLAY_TRUSTED = 1 << 2; + + /** + * Modifiers that affect the state of this overlay. See {@link #FLAG_OVERLAY_STATIC}, + * {@link #FLAG_OVERLAY_TRUSTED}. + * @hide + */ + public int overlayFlags; public PackageInfo() { } @@ -342,8 +360,8 @@ public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeString(restrictedAccountType); dest.writeString(requiredAccountType); dest.writeString(overlayTarget); - dest.writeInt(isStaticOverlay ? 1 : 0); dest.writeInt(overlayPriority); + dest.writeInt(overlayFlags); } public static final Parcelable.Creator CREATOR @@ -394,8 +412,8 @@ private PackageInfo(Parcel source) { restrictedAccountType = source.readString(); requiredAccountType = source.readString(); overlayTarget = source.readString(); - isStaticOverlay = source.readInt() != 0; overlayPriority = source.readInt(); + overlayFlags = source.readInt(); // The component lists were flattened with the redundant ApplicationInfo // instances omitted. Distribute the canonical one here as appropriate. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index cb9ecf3e2bd8..4689f45098e2 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -678,7 +678,15 @@ public static PackageInfo generatePackageInfo(PackageParser.Package p, pi.requiredAccountType = p.mRequiredAccountType; pi.overlayTarget = p.mOverlayTarget; pi.overlayPriority = p.mOverlayPriority; - pi.isStaticOverlay = p.mIsStaticOverlay; + + if (p.mIsStaticOverlay) { + pi.overlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC; + } + + if (p.mTrustedOverlay) { + pi.overlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED; + } + pi.firstInstallTime = firstInstallTime; pi.lastUpdateTime = lastUpdateTime; if ((flags&PackageManager.GET_GIDS) != 0) { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 2940a6e3fc8d..0b3efdba212d 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -669,7 +669,8 @@ private void enforceDumpPermission(@NonNull final String message) { }; private boolean isOverlayPackage(@NonNull final PackageInfo pi) { - return pi != null && pi.overlayTarget != null; + return pi != null && pi.overlayTarget != null + && (pi.overlayFlags & PackageInfo.FLAG_OVERLAY_TRUSTED) != 0; } private final class OverlayChangeListener diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index db6e9749535b..497d79d6fbc4 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -68,6 +68,11 @@ final class OverlayManagerServiceImpl { mListener = listener; } + private static boolean isPackageStaticOverlay(final PackageInfo packageInfo) { + return packageInfo.overlayTarget != null + && (packageInfo.overlayFlags & PackageInfo.FLAG_OVERLAY_STATIC) != 0; + } + /** * Call this to synchronize the Settings for a user with what PackageManager knows about a user. * Returns a list of target packages that must refresh their overlays. This list is the union @@ -102,11 +107,11 @@ ArrayList updateOverlaysForUser(final int newUserId) { mSettings.init(overlayPackage.packageName, newUserId, overlayPackage.overlayTarget, overlayPackage.applicationInfo.getBaseCodePath(), - overlayPackage.isStaticOverlay, overlayPackage.overlayPriority); + isPackageStaticOverlay(overlayPackage), overlayPackage.overlayPriority); if (oi == null) { // This overlay does not exist in our settings. - if (overlayPackage.isStaticOverlay || + if (isPackageStaticOverlay(overlayPackage) || mDefaultOverlays.contains(overlayPackage.packageName)) { // Enable this overlay by default. if (DEBUG) { @@ -255,8 +260,8 @@ void onOverlayPackageAdded(@NonNull final String packageName, final int userId) mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId); mSettings.init(packageName, userId, overlayPackage.overlayTarget, - overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay, - overlayPackage.overlayPriority); + overlayPackage.applicationInfo.getBaseCodePath(), + isPackageStaticOverlay(overlayPackage), overlayPackage.overlayPriority); try { if (updateState(targetPackage, overlayPackage, userId)) { mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); @@ -313,7 +318,7 @@ boolean setEnabled(@NonNull final String packageName, final boolean enable, } // Ignore static overlays. - if (overlayPackage.isStaticOverlay) { + if (isPackageStaticOverlay(overlayPackage)) { return false; } @@ -363,7 +368,7 @@ boolean setEnabledExclusive(@NonNull final String packageName, final int userId) continue; } - if (disabledOverlayPackageInfo.isStaticOverlay) { + if (isPackageStaticOverlay(disabledOverlayPackageInfo)) { // Don't touch static overlays. continue; } @@ -388,7 +393,7 @@ boolean setEnabledExclusive(@NonNull final String packageName, final int userId) private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); - if (overlayPackage == null || overlayPackage.isStaticOverlay) { + if (overlayPackage == null || isPackageStaticOverlay(overlayPackage)) { return false; } return true; @@ -483,7 +488,8 @@ private boolean updateState(@Nullable final PackageInfo targetPackage, throws OverlayManagerSettings.BadKeyException { // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers. if (targetPackage != null && - !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) { + !("android".equals(targetPackage.packageName) + && isPackageStaticOverlay(overlayPackage))) { mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); } From f18f319d6b262c13dae2469183be1d0dd863c72f Mon Sep 17 00:00:00 2001 From: Nicholas Chum Date: Sat, 27 Aug 2016 10:56:46 -0400 Subject: [PATCH 06/38] Themes: Notifications: Expose a bool to disable dynamic colors forward port to oreo 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. Oreo edits: follow bool for OverflowNumbers as well before: https://i.imgur.com/JqeLFD1.jpg after: https://i.imgur.com/GPoM0zo.jpg Change-Id: I3c7828118991ec4fc616011caf073c81f75428b4 --- core/java/android/app/Notification.java | 27 ++++++++++++++++--- core/res/res/values/projekt_colors.xml | 24 +++++++++++++++++ core/res/res/values/projekt_config.xml | 22 +++++++++++++++ core/res/res/values/projekt_symbols.xml | 26 ++++++++++++++++++ .../notification/HybridGroupManager.java | 8 ++++-- 5 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 core/res/res/values/projekt_colors.xml 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 7caeca3da6f8..26a851654702 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4809,7 +4809,12 @@ private CharSequence processLegacyText(CharSequence charSequence, boolean ambien private void processSmallIconColor(Icon smallIcon, RemoteViews contentView, boolean ambient) { boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); - int color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor(); + int color; + if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) { + color = ambient ? resolveAmbientColor() : mContext.getColor(R.color.notification_icon_default_color); + } else { + color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor(); + } if (colorable) { contentView.setDrawableParameters(R.id.icon, false, -1, color, PorterDuff.Mode.SRC_ATOP, -1); @@ -4828,7 +4833,7 @@ private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) { 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); } } @@ -4839,7 +4844,23 @@ private void sanitizeColor() { } } + 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; } @@ -6217,7 +6238,7 @@ private CharSequence makeMessageLine(Message m, Builder builder) { sb.append(bidi.unicodeWrap(m.mSender), makeFontColorSpan(colorize ? builder.getPrimaryTextColor() - : Color.BLACK), + : builder.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 new file mode 100644 index 000000000000..94ec4a37639d --- /dev/null +++ b/core/res/res/values/projekt_colors.xml @@ -0,0 +1,24 @@ + + + + + + @android:color/notification_default_color + + + @android:color/black + diff --git a/core/res/res/values/projekt_config.xml b/core/res/res/values/projekt_config.xml new file mode 100644 index 000000000000..a6b5f894bbfa --- /dev/null +++ b/core/res/res/values/projekt_config.xml @@ -0,0 +1,22 @@ + + + + + + true + + diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml new file mode 100644 index 000000000000..c3eb46562998 --- /dev/null +++ b/core/res/res/values/projekt_symbols.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java index 3ed8cce21ac5..0ca9e8873f11 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java @@ -81,8 +81,12 @@ private TextView inflateOverflowNumber() { } private void updateOverFlowNumberColor(TextView numberView) { - numberView.setTextColor(NotificationUtils.interpolateColors( - mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount)); + if (!mContext.getResources().getBoolean(com.android.internal.R.bool.config_allowNotificationIconTextTinting)) { + numberView.setTextColor(mContext.getColor(com.android.internal.R.color.notification_text_default_color)); + } else { + numberView.setTextColor(NotificationUtils.interpolateColors( + mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount)); + } } public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) { From 4b857261936d3e4fea4beac85ce7ab0466e019a6 Mon Sep 17 00:00:00 2001 From: George G Date: Mon, 14 Nov 2016 14:49:47 +0200 Subject: [PATCH 07/38] Themes: Notification dynamic colors bool compatible with OMS7 forward ported to oreo 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 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 26a851654702..b5dd5b9e766a 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4810,7 +4810,7 @@ private void processSmallIconColor(Icon smallIcon, RemoteViews contentView, boolean ambient) { boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); int color; - if (!Resources.getSystem().getBoolean(R.bool.config_allowNotificationIconTextTinting)) { + if (!mContext.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) { color = ambient ? resolveAmbientColor() : mContext.getColor(R.color.notification_icon_default_color); } else { color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor(); @@ -4849,7 +4849,7 @@ int getSenderTextColor() { } 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(); @@ -4857,7 +4857,7 @@ int resolveIconContrastColor() { } 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); } From 79a819645b705660d2e77832fa2375fd9729e253 Mon Sep 17 00:00:00 2001 From: Adarsh-MR Date: Mon, 27 Nov 2017 11:23:45 +0000 Subject: [PATCH 08/38] Themes: Notifications: extend dynamic notification bool for ambient notifications * added a seperate color resource, so this way themer can use diff color (ex: white) for ambient and accent for normal notification. Change-Id: I65a518d9433558004289826abbf25dc374dd7ec7 Signed-off-by: Adarsh-MR --- .../com/android/internal/util/NotificationColorUtil.java | 9 ++++++++- core/res/res/values/projekt_colors.xml | 5 ++++- core/res/res/values/projekt_symbols.xml | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 933cc7af975a..c72ac2d3650e 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -40,6 +40,8 @@ import android.util.Log; import android.util.Pair; +import com.android.internal.R; + import java.util.Arrays; import java.util.WeakHashMap; @@ -515,7 +517,12 @@ public static int resolveAmbientColor(Context context, int notificationColor) { final int resolvedColor = resolveColor(context, notificationColor); int color = resolvedColor; - color = NotificationColorUtil.ensureTextContrastOnBlack(color); + + if (!context.getResources().getBoolean(R.bool.config_allowNotificationIconTextTinting)) { + color = context.getColor(R.color.notification_ambient_default_color); + } else { + color = NotificationColorUtil.ensureTextContrastOnBlack(color); + } if (color != resolvedColor) { if (DEBUG){ diff --git a/core/res/res/values/projekt_colors.xml b/core/res/res/values/projekt_colors.xml index 94ec4a37639d..4aee4d82adb7 100644 --- a/core/res/res/values/projekt_colors.xml +++ b/core/res/res/values/projekt_colors.xml @@ -18,7 +18,10 @@ @android:color/notification_default_color - + + + @android:color/notification_text_default_color + @android:color/black diff --git a/core/res/res/values/projekt_symbols.xml b/core/res/res/values/projekt_symbols.xml index c3eb46562998..36213317c7dc 100644 --- a/core/res/res/values/projekt_symbols.xml +++ b/core/res/res/values/projekt_symbols.xml @@ -19,7 +19,8 @@ - + + From 79d56d191c7b209de4974dde59959f50dbe89e52 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar Date: Mon, 5 Dec 2016 19:00:04 +0700 Subject: [PATCH 09/38] Themes: SystemUI: Use own drawables for QS expand icon forward ported and adapted to oreo-mr1 changes. 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 --- .../SystemUI/res/drawable/ic_qs_collapse.xml | 55 +++++++++++++++++++ .../res/drawable/ic_qs_collapse_animation.xml | 25 +++++++++ .../SystemUI/res/drawable/ic_qs_expand.xml | 55 +++++++++++++++++++ .../res/drawable/ic_qs_expand_animation.xml | 25 +++++++++ .../statusbar/phone/ExpandableIndicator.java | 8 +-- 5 files changed, 164 insertions(+), 4 deletions(-) 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 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 000000000000..3853d121ce2c --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_collapse.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + 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 000000000000..18c6307b9ad9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_collapse_animation.xml @@ -0,0 +1,25 @@ + + + + + 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 000000000000..79ff80806438 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_expand.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + 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 000000000000..abd6678e335f --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_expand_animation.xml @@ -0,0 +1,25 @@ + + + + + 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 8f49c85b0938..72ec7a7783e7 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 void setDefaultDirection(boolean isDefaultDirection) { 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; } } From fb542e2fd9864f992df69214a4f15a9bd00ec536 Mon Sep 17 00:00:00 2001 From: Dave Kover Date: Thu, 14 Apr 2016 10:19:13 +0700 Subject: [PATCH 10/38] Themes: Allow Navbar ripple color to be themed Forward ported and adapted to oreo LightNavigationBar 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 Signed-off-by: Adarsh-MR --- .../SystemUI/res/values/projekt_colors.xml | 23 +++++++++++++++++++ .../statusbar/policy/KeyButtonRipple.java | 7 +++++- 2 files changed, 29 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 000000000000..b92b5a8300a7 --- /dev/null +++ b/packages/SystemUI/res/values/projekt_colors.xml @@ -0,0 +1,23 @@ + + + + + + + #FFFFFFFF + + + #ff000000 + + 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 cc7943b85bc1..53c78b7ad211 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java @@ -68,9 +68,14 @@ public class KeyButtonRipple extends Drawable { private final HashSet mRunningAnimations = new HashSet<>(); private final ArrayList mTmpArray = new ArrayList<>(); + private int mRippleColor; + private int mRippleColorDark; + 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); + mRippleColorDark = ctx.getResources().getColor(R.color.navbutton_ripple_color_dark); } public void setDarkIntensity(float darkIntensity) { @@ -81,7 +86,7 @@ private Paint getRipplePaint() { if (mRipplePaint == null) { mRipplePaint = new Paint(); mRipplePaint.setAntiAlias(true); - mRipplePaint.setColor(mLastDark ? 0xff000000 : 0xffffffff); + mRipplePaint.setColor(mLastDark ? mRippleColorDark : mRippleColor); } return mRipplePaint; } From 3b1263acd997eec696752b6214422a78fc48aba5 Mon Sep 17 00:00:00 2001 From: daveyannihilation Date: Sun, 1 Jan 2017 01:47:53 -0700 Subject: [PATCH 11/38] Themes: 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 +-- .../SystemUI/res/values/projekt_styles.xml | 22 +++++++++++++++++++ 2 files changed, 23 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 41cdb78392a9..344c5aa0531a 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 000000000000..8c61aaf0ba40 --- /dev/null +++ b/packages/SystemUI/res/values/projekt_styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + From 798e2853d8dd942e6f465e80cedfb44102a0c48a Mon Sep 17 00:00:00 2001 From: George G Date: Thu, 2 Feb 2017 01:52:27 +0200 Subject: [PATCH 12/38] Themes: 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 c329918afc27..7139c34fc691 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -302,7 +302,7 @@ private Drawable loadDrawableInner(Context context) { resPackage = context.getPackageName(); } if ("android".equals(resPackage)) { - mObj1 = Resources.getSystem(); + mObj1 = context.getResources(); } else { final PackageManager pm = context.getPackageManager(); try { From c16409c11b4beb05111d007a4ccfd77f01558e93 Mon Sep 17 00:00:00 2001 From: Bryan Owens Date: Thu, 30 Mar 2017 13:30:04 -0500 Subject: [PATCH 13/38] Themes: Expose Keyboard Shortcuts Dialog Change-Id: I84d3e57fe8c42d79ff6e0b6502cb6cd49aaaf91b Signed-off-by: Bryan Owens --- packages/SystemUI/res/values/projekt_styles.xml | 3 +++ .../src/com/android/systemui/statusbar/KeyboardShortcuts.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/res/values/projekt_styles.xml b/packages/SystemUI/res/values/projekt_styles.xml index 8c61aaf0ba40..d3a59076b612 100644 --- a/packages/SystemUI/res/values/projekt_styles.xml +++ b/packages/SystemUI/res/values/projekt_styles.xml @@ -19,4 +19,7 @@ ?android:attr/textColorPrimaryInverse + +