From dbb8dc5a712c50b81dd5ba1403d0707914be9c82 Mon Sep 17 00:00:00 2001 From: Eva Bertels Date: Thu, 16 Aug 2018 12:46:12 +0100 Subject: [PATCH 01/20] Added check for misprovisioned Pixel 2 device. Some Pixel devices had a wrong brand value provisioned into keymaster. Due to this misprovisioning those devices fail device ID attestation because it includes a check for the correct brand value. This is now solved by re-trying Device ID attestation if we are running on a potentially misprovisioned device, allowing for the known incorrect brand value. Bug: 69471841 Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testKeyManagement Change-Id: If715ebdd4ab6d7fcfffab60b40fd2dc8fa1fda44 Merged-In: Ia0da5478d6092c1927d26600a6893ae8ce53da51 (cherry picked from commit 3f821a8e17f97a6f0b3ae408b2e7f2bfde666df4) --- core/res/res/values/config.xml | 7 ++++ core/res/res/values/symbols.xml | 3 ++ .../security/keystore/AttestationUtils.java | 38 ++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 9d6aee102c028..b372d7b767d55 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3508,4 +3508,11 @@ true + + + + + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index cd9d0c4f57f97..a3ed1b0526d0a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3412,4 +3412,7 @@ + + + diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index 1be8309bcf5ab..f7993eff6b08f 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -22,9 +22,9 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; +import android.content.res.Resources; import android.os.Build; import android.security.KeyStore; -import android.security.KeyStoreException; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterCertificateChain; import android.security.keymaster.KeymasterDefs; @@ -117,6 +117,40 @@ public abstract class AttestationUtils { @NonNull public static KeymasterArguments prepareAttestationArguments(Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws DeviceIdAttestationException { + return prepareAttestationArguments(context, idTypes,attestationChallenge, Build.BRAND); + } + + /** + * Prepares Keymaster Arguments with attestation data for misprovisioned Pixel 2 device. + * See http://go/keyAttestationFailure and http://b/69471841 for more info. + * @hide should only be used by KeyChain. + */ + @NonNull public static KeymasterArguments prepareAttestationArgumentsIfMisprovisioned( + Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws + DeviceIdAttestationException { + if (!isPotentiallyMisprovisionedDevice(context)) { + return null; + } + Resources resources = context.getResources(); + String misprovisionedBrand = resources.getString( + com.android.internal.R.string.config_misprovisionedBrandValue); + return prepareAttestationArguments( + context, idTypes, attestationChallenge, misprovisionedBrand); + } + + @NonNull private static boolean isPotentiallyMisprovisionedDevice(Context context) { + Resources resources = context.getResources(); + String misprovisionedModel = resources.getString( + com.android.internal.R.string.config_misprovisionedDeviceModel); + String misprovisionedBrand = resources.getString( + com.android.internal.R.string.config_misprovisionedBrandValue); + + return (Build.MODEL.equals(misprovisionedModel)); + } + + @NonNull private static KeymasterArguments prepareAttestationArguments(Context context, + @NonNull int[] idTypes, @NonNull byte[] attestationChallenge, String brand) throws + DeviceIdAttestationException { // Check method arguments, retrieve requested device IDs and prepare attestation arguments. if (attestationChallenge == null) { throw new NullPointerException("Missing attestation challenge"); @@ -169,7 +203,7 @@ public abstract class AttestationUtils { } } attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND, - Build.BRAND.getBytes(StandardCharsets.UTF_8)); + brand.getBytes(StandardCharsets.UTF_8)); attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE, Build.DEVICE.getBytes(StandardCharsets.UTF_8)); attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT, From 7df76c43d8f92254f0a189c90f4bc1ffd38e54ca Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 23 Aug 2018 12:39:05 +0200 Subject: [PATCH 02/20] DO NOT MERGE Use correct lock when killing processes Test: Switch display cutout Bug: 113093654 Change-Id: I2ca076a214da86656b6c71ebe1f63eb92e340ac0 (cherry picked from commit 1fd30aa5581dec8cfa5113fe436bcd963d0a35f9) --- .../core/java/com/android/server/am/ActivityManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 444ad8e2ced79..c5b8b950d4567 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -26873,7 +26873,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void notifyDefaultDisplaySizeChanged() { - synchronized (this) { + synchronized (ActivityManagerService.this) { if (mSystemServiceManager.isBootCompleted() && mHomeProcess != null) { // TODO: Ugly hack to unblock the release From a433d41005bbf06be09fb2d505ea0726f7d4bfbf Mon Sep 17 00:00:00 2001 From: Matthew Ng Date: Thu, 9 Aug 2018 13:55:05 -0700 Subject: [PATCH 03/20] Reduce NearestTouchFrame size to prevent button taps on nav bar The NearestTouchFrame spanned the entire nav bar that took any tap to hit the nearest button such as the back button. Reducing it prevents taps from the edge of the nav bar. Related: ag/4179853 Change-Id: I25a73cc995ed8d479ca9d5da85ec8a7cb629769d Fixes: 112298917 Test: tap the left side of the nav bar (cherry picked from commit 9e90f24dc5dc2574700c46288617bea18b28bf29) (cherry picked from commit 7daaaad74a29eca0e2a56b29fe55e2f615b05415) --- .../SystemUI/res/layout/navigation_layout.xml | 12 +++++------ .../res/layout/navigation_layout_rot90.xml | 20 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml index baaf699c278ad..d72021e27e0bc 100644 --- a/packages/SystemUI/res/layout/navigation_layout.xml +++ b/packages/SystemUI/res/layout/navigation_layout.xml @@ -18,14 +18,16 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:layout_marginStart="@dimen/rounded_corner_content_padding" + android:layout_marginEnd="@dimen/rounded_corner_content_padding" + android:paddingStart="@dimen/nav_content_padding" + android:paddingEnd="@dimen/nav_content_padding"> @@ -34,8 +36,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" - android:paddingStart="@dimen/nav_content_padding" - android:paddingEnd="@dimen/nav_content_padding" android:clipToPadding="false" android:clipChildren="false" /> @@ -46,8 +46,6 @@ android:layout_gravity="center" android:gravity="center" android:orientation="horizontal" - android:paddingStart="@dimen/nav_content_padding" - android:paddingEnd="@dimen/nav_content_padding" android:clipToPadding="false" android:clipChildren="false" /> diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml index 6d5b77885a09d..24a0c71f3bada 100644 --- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml +++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml @@ -18,14 +18,16 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:layout_marginTop="@dimen/rounded_corner_content_padding" + android:layout_marginBottom="@dimen/rounded_corner_content_padding" + android:paddingTop="@dimen/nav_content_padding" + android:paddingBottom="@dimen/nav_content_padding"> @@ -34,10 +36,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:paddingTop="@dimen/nav_content_padding" - android:paddingBottom="@dimen/nav_content_padding" - android:clipChildren="false" - android:clipToPadding="false" /> + android:clipToPadding="false" + android:clipChildren="false" /> + android:clipToPadding="false" + android:clipChildren="false" /> From f3113c78fb1af9f5520feecb4d796b7b51e40432 Mon Sep 17 00:00:00 2001 From: Tyler Gunn Date: Tue, 28 Aug 2018 08:39:39 -0700 Subject: [PATCH 04/20] Add equality method for PhoneAccount. Checks for equality between two PhoneAccounts, not taking into account the icon, which cannot be compared with equality. Test: Manual as part of telephony account registry updates. Test: Added new unit tests to test equality. Bug: 112884689 Merged-In: Change-Id: Ibd0c69425bf185dc6b79db4ca4e9ca4a770320a3 Change-Id: Ibd0c69425bf185dc6b79db4ca4e9ca4a770320a3 (cherry picked from commit a04bd3d292ce29ad6f8c94348ea1c8ce80d29e8e) (cherry picked from commit 5df50b83bcc22a3d23de6f48d5d93418bfb63f1d) --- .../java/android/telecom/PhoneAccount.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index b3a3bf21cd8b4..8e22221d78761 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -28,6 +28,7 @@ import java.lang.String; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * Represents a distinct method to place or receive a phone call. Apps which can place calls and @@ -348,6 +349,33 @@ public final class PhoneAccount implements Parcelable { private boolean mIsEnabled; private String mGroupId; + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PhoneAccount that = (PhoneAccount) o; + return mCapabilities == that.mCapabilities && + mHighlightColor == that.mHighlightColor && + mSupportedAudioRoutes == that.mSupportedAudioRoutes && + mIsEnabled == that.mIsEnabled && + Objects.equals(mAccountHandle, that.mAccountHandle) && + Objects.equals(mAddress, that.mAddress) && + Objects.equals(mSubscriptionAddress, that.mSubscriptionAddress) && + Objects.equals(mLabel, that.mLabel) && + Objects.equals(mShortDescription, that.mShortDescription) && + Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) && + areBundlesEqual(mExtras, that.mExtras) && + Objects.equals(mGroupId, that.mGroupId); + } + + @Override + public int hashCode() { + return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities, + mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes, + mSupportedAudioRoutes, + mExtras, mIsEnabled, mGroupId); + } + /** * Helper class for creating a {@link PhoneAccount}. */ @@ -1010,4 +1038,31 @@ public final class PhoneAccount implements Parcelable { return sb.toString(); } + + /** + * Determines if two {@link Bundle}s are equal. + * @param extras First {@link Bundle} to check. + * @param newExtras {@link Bundle} to compare against. + * @return {@code true} if the {@link Bundle}s are equal, {@code false} otherwise. + */ + private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) { + if (extras == null || newExtras == null) { + return extras == newExtras; + } + + if (extras.size() != newExtras.size()) { + return false; + } + + for(String key : extras.keySet()) { + if (key != null) { + final Object value = extras.get(key); + final Object newValue = newExtras.get(key); + if (!Objects.equals(value, newValue)) { + return false; + } + } + } + return true; + } } From 181dc252ddec574464882970d3fab290e8b625b5 Mon Sep 17 00:00:00 2001 From: dwchen Date: Mon, 20 Aug 2018 10:17:48 -0700 Subject: [PATCH 05/20] Fixes possible issue with no-op creator. Leaving a no-op CREATOR can lead to issues. We throw a run-time exception to prevent anyone from using this. The StatsLogEventWrapper is meant to be write-only since it's only used to send data to statsd. Bug: 112550251 Test: Tested with provided POC app by external researcher. Change-Id: I001d84e2a61a1cd8a4f59aa156ca52f73ad0f6e1 (cherry picked from commit 78622d57ad102c054306b01321b6b2dbec3f9d1d) --- .../java/android/os/StatsLogEventWrapper.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java index d4d3dc838d91d..7b3ea57ba0e90 100644 --- a/core/java/android/os/StatsLogEventWrapper.java +++ b/core/java/android/os/StatsLogEventWrapper.java @@ -65,11 +65,17 @@ public final class StatsLogEventWrapper implements Parcelable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public StatsLogEventWrapper createFromParcel(Parcel in) { - return new StatsLogEventWrapper(in); + android.util.EventLog.writeEvent(0x534e4554, "112550251", + android.os.Binder.getCallingUid(), ""); + // Purposefully leaving this method not implemented. + throw new RuntimeException("Not implemented"); } public StatsLogEventWrapper[] newArray(int size) { - return new StatsLogEventWrapper[size]; + android.util.EventLog.writeEvent(0x534e4554, "112550251", + android.os.Binder.getCallingUid(), ""); + // Purposefully leaving this method not implemented. + throw new RuntimeException("Not implemented"); } }; @@ -120,10 +126,6 @@ public final class StatsLogEventWrapper implements Parcelable { mStorage.write(bytes, 0, bytes.length); } - private StatsLogEventWrapper(Parcel in) { - readFromParcel(in); - } - /** * Writes the stored fields to a byte array. Will first write a new-line character to denote * END_LIST before writing contents to byte array. @@ -133,13 +135,6 @@ public final class StatsLogEventWrapper implements Parcelable { out.writeByteArray(mStorage.toByteArray()); } - /** - * Not implemented. - */ - public void readFromParcel(Parcel in) { - // Not needed since this java class is for sending to statsd only. - } - /** * Boilerplate for Parcel. */ From 25060bbde58faf298a7ed5cd9b0bf48acf0c2405 Mon Sep 17 00:00:00 2001 From: Hongming Jin Date: Wed, 8 Aug 2018 15:01:57 -0700 Subject: [PATCH 06/20] RESTRICT AUTOMERGE: Check both self and shared user id package for requested permissions. Bug: 111752150 Test: Manual local test Change-Id: I80383300cd5d2455d08a0ad91000efa85404903b (cherry picked from commit 5e37e9d962c476202590bef32b87c2eb794d61a1) --- .../com/android/server/pm/permission/BasePermission.java | 5 ++++- .../android/server/pm/permission/PermissionsState.java | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 1d002efc546fd..820258022fd5f 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -39,6 +39,7 @@ import android.util.Slog; import com.android.server.pm.DumpState; import com.android.server.pm.PackageManagerService; +import com.android.server.pm.PackageSetting; import com.android.server.pm.PackageSettingBase; import org.xmlpull.v1.XmlPullParser; @@ -374,8 +375,10 @@ public final class BasePermission { } public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) { + final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras; + final PermissionsState permsState = pkgSetting.getPermissionsState(); int index = pkg.requestedPermissions.indexOf(name); - if (index == -1) { + if (!permsState.hasRequestedPermission(name) && index == -1) { throw new SecurityException("Package " + pkg.packageName + " has not requested permission " + name); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java index 11df380427eb3..5e66bfc3cd3e1 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionsState.java +++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java @@ -20,9 +20,9 @@ import android.content.pm.PackageManager; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; - import android.util.SparseArray; import android.util.SparseBooleanArray; + import com.android.internal.util.ArrayUtils; import java.util.ArrayList; @@ -290,6 +290,13 @@ public final class PermissionsState { return false; } + /** + * Returns whether the state has any known request for the given permission name, + * whether or not it has been granted. + */ + public boolean hasRequestedPermission(String name) { + return mPermissions != null && (mPermissions.get(name) != null); + } /** * Gets all permissions for a given device user id regardless if they * are install time or runtime permissions. From 8e81142af3dceb913ca50f67df3ded84233f932a Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Thu, 30 Aug 2018 17:25:56 +0800 Subject: [PATCH 07/20] Changing SUPL_ES=1 for SUPL end point control SUPL_ES=1 ensures the GnssLocationProvider and related framework code accepts incoming SMS SUPL_INIT messages with ES-bit=1 (which allow redirection of the ESLP end-point e.g. to the current local emergency services provider when you are travelling) only during an emergency call Bug: 111899241 Bug: 112159033 Test: Build pass Change-Id: I7dcd9c173a1d56fcf0da15257db5b8d1322b39d6 (cherry picked from commit 5b63dcc6a617cbab74dbda1f4cd759c75efa3aa5) --- core/res/res/values-mcc302-mnc220/config.xml | 2 +- core/res/res/values-mcc302-mnc221/config.xml | 2 +- core/res/res/values-mcc302-mnc370/config.xml | 2 +- core/res/res/values-mcc302-mnc610/config.xml | 2 +- core/res/res/values-mcc302-mnc640/config.xml | 2 +- core/res/res/values-mcc302-mnc720/config.xml | 2 +- core/res/res/values/config.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml index 8774334f11bee..5343e7cea8477 100644 --- a/core/res/res/values-mcc302-mnc220/config.xml +++ b/core/res/res/values-mcc302-mnc220/config.xml @@ -40,7 +40,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=3 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml index 05896b18cfb8d..cb9466be77b64 100644 --- a/core/res/res/values-mcc302-mnc221/config.xml +++ b/core/res/res/values-mcc302-mnc221/config.xml @@ -38,7 +38,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=3 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml index 1241a9d029d6b..b520d5d95a341 100644 --- a/core/res/res/values-mcc302-mnc370/config.xml +++ b/core/res/res/values-mcc302-mnc370/config.xml @@ -41,7 +41,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=2 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml index 232f14969ad1b..650aa62b4a4e1 100644 --- a/core/res/res/values-mcc302-mnc610/config.xml +++ b/core/res/res/values-mcc302-mnc610/config.xml @@ -28,7 +28,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=2 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml index 1d2e625952f8d..4bb68dcf04be7 100644 --- a/core/res/res/values-mcc302-mnc640/config.xml +++ b/core/res/res/values-mcc302-mnc640/config.xml @@ -24,7 +24,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=2 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml index ef1ecd29845cc..11bfa056d2954 100644 --- a/core/res/res/values-mcc302-mnc720/config.xml +++ b/core/res/res/values-mcc302-mnc720/config.xml @@ -43,7 +43,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=2 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b372d7b767d55..a9d69c1bcbbe7 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2784,7 +2784,7 @@ SUPL_PORT=7275 SUPL_VER=0x20000 SUPL_MODE=1 - SUPL_ES=0 + SUPL_ES=1 LPP_PROFILE=0 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 A_GLONASS_POS_PROTOCOL_SELECT=0 From 6a947f048a76a5936fd2b693e01f849aef22c907 Mon Sep 17 00:00:00 2001 From: Michael Wachenschwanz Date: Fri, 24 Aug 2018 21:50:35 -0700 Subject: [PATCH 08/20] Verify number of Map entries written to Parcel Make sure the number of entries written by Parcel#writeMapInternal matches the size written. If a mismatch were allowed, an exploitable scenario could occur where the data read from the Parcel would not match the data written. Fixes: 112859604 Test: cts-tradefed run cts -m CtsOsTestCases -t android.os.cts.ParcelTest Change-Id: I325d08a8b66b6e80fe76501359c41b6656848607 Merged-In: I325d08a8b66b6e80fe76501359c41b6656848607 (cherry picked from commit 057a01d1f38e9b46d3faa4059fdd7c8717681ea0) --- core/java/android/os/Parcel.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 514292872e90d..460f12510d451 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -835,11 +835,19 @@ public final class Parcel { return; } Set> entries = val.entrySet(); - writeInt(entries.size()); + int size = entries.size(); + writeInt(size); + for (Map.Entry e : entries) { writeValue(e.getKey()); writeValue(e.getValue()); + size--; } + + if (size != 0) { + throw new BadParcelableException("Map size does not match number of entries!"); + } + } /** From a3431a2b0d155893188dea4f58df544be0e48931 Mon Sep 17 00:00:00 2001 From: Hongming Jin Date: Fri, 28 Sep 2018 19:21:46 +0000 Subject: [PATCH 09/20] Revert "RESTRICT AUTOMERGE: Revoke permissions defined in a to-be removed package." This reverts commit fde947837c848b51a830b74b28f96f9808405492. Reason for revert: triggers other issue. Bug: 114365189 Change-Id: I37523a1778d55153253cf10df1ede68c5acb8178 (cherry picked from commit 06cc74977fcebe8a270e6bcd812dcfb31c32492c) --- .../server/pm/PackageManagerService.java | 3 +- .../permission/PermissionManagerInternal.java | 8 +- .../permission/PermissionManagerService.java | 81 +++---------------- 3 files changed, 13 insertions(+), 79 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 670c1af96998e..82ad46f08aed0 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12344,8 +12344,7 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r); } - final ArrayList allPackageNames = new ArrayList<>(mPackages.keySet()); - mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty); + mPermissionManager.removeAllPermissions(pkg, chatty); N = pkg.instrumentation.size(); r = null; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java index c3f23a81518ad..a042fedf8b470 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java @@ -115,11 +115,7 @@ public abstract class PermissionManagerInternal { */ public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty); - public abstract void removeAllPermissions( - @NonNull PackageParser.Package pkg, - @NonNull List allPackageNames, - @Nullable PermissionCallback permissionCallback, - boolean chatty); + public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async, int callingUid, @Nullable PermissionCallback callback); public abstract void removeDynamicPermission(@NonNull String permName, int callingUid, @@ -193,4 +189,4 @@ public abstract class PermissionManagerInternal { /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); -} +} \ No newline at end of file diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 02c9049f008ee..c51a72406b539 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -30,7 +30,6 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; @@ -38,7 +37,6 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.PackageParser.Package; import android.metrics.LogMaker; -import android.os.AsyncTask; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -457,9 +455,8 @@ public class PermissionManagerService { " to " + newPermissionGroupName); try { - revokeRuntimePermission(permissionName, packageName, - mSettings.getPermission(permissionName), false, - Process.SYSTEM_UID, userId, permissionCallback, false); + revokeRuntimePermission(permissionName, packageName, false, + Process.SYSTEM_UID, userId, permissionCallback); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); @@ -552,59 +549,9 @@ public class PermissionManagerService { } - private void revokeAllPermissions( - @NonNull List bps, - @NonNull List allPackageNames, - @Nullable PermissionCallback permissionCallback) { - AsyncTask.execute(() -> { - final int numRemovedPermissions = bps.size(); - for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) { - final int[] userIds = mUserManagerInt.getUserIds(); - final int numUserIds = userIds.length; - - final int numPackages = allPackageNames.size(); - for (int packageNum = 0; packageNum < numPackages; packageNum++) { - final String packageName = allPackageNames.get(packageNum); - final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo( - packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM); - if (applicationInfo != null - && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - continue; - } - for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { - final int userId = userIds[userIdNum]; - final String permissionName = bps.get(permissionNum).getName(); - if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM, - userId) == PackageManager.PERMISSION_GRANTED) { - try { - revokeRuntimePermission( - permissionName, - packageName, - bps.get(permissionNum), - false, - Process.SYSTEM_UID, - userId, - permissionCallback, - true); - } catch (IllegalArgumentException e) { - Slog.e(TAG, "Could not revoke " + permissionName + " from " - + packageName, e); - } - } - } - } - } - }); - } - - private void removeAllPermissions( - @NonNull PackageParser.Package pkg, - @NonNull List allPackageNames, - @Nullable PermissionCallback permissionCallback, - boolean chatty) { + private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) { synchronized (mLock) { int N = pkg.permissions.size(); - List bps = new ArrayList(N); StringBuilder r = null; for (int i=0; i allPackageNames, - PermissionCallback permissionCallback, boolean chatty) { - PermissionManagerService.this.removeAllPermissions( - pkg, allPackageNames, permissionCallback, chatty); + public void removeAllPermissions(Package pkg, boolean chatty) { + PermissionManagerService.this.removeAllPermissions(pkg, chatty); } @Override public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid, @@ -2170,8 +2110,7 @@ public class PermissionManagerService { boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) { PermissionManagerService.this.revokeRuntimePermission(permName, packageName, - mSettings.getPermission(permName), overridePolicy, callingUid, userId, - callback, false); + overridePolicy, callingUid, userId, callback); } @Override public void updatePermissions(String packageName, Package pkg, boolean replaceGrant, From a4568bd2095ab29dd5fc799988b15383adb6ce2e Mon Sep 17 00:00:00 2001 From: Hongming Jin Date: Fri, 28 Sep 2018 19:23:22 +0000 Subject: [PATCH 10/20] Revert "RESTRICT AUTOMERGE: Check both self and shared user id package for requested permissions." This reverts commit 5e37e9d962c476202590bef32b87c2eb794d61a1. Reason for revert: Not a security fix and the security fix needs this cl is reverted. Bug: 114365189 Change-Id: Ia12ce2692b47a1d59be0b199b1fbfa415767e145 (cherry picked from commit 0b103c697331a5bcae2f65de4a3864bca0b592ff) --- .../com/android/server/pm/permission/BasePermission.java | 5 +---- .../android/server/pm/permission/PermissionsState.java | 9 +-------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 820258022fd5f..1d002efc546fd 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -39,7 +39,6 @@ import android.util.Slog; import com.android.server.pm.DumpState; import com.android.server.pm.PackageManagerService; -import com.android.server.pm.PackageSetting; import com.android.server.pm.PackageSettingBase; import org.xmlpull.v1.XmlPullParser; @@ -375,10 +374,8 @@ public final class BasePermission { } public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) { - final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras; - final PermissionsState permsState = pkgSetting.getPermissionsState(); int index = pkg.requestedPermissions.indexOf(name); - if (!permsState.hasRequestedPermission(name) && index == -1) { + if (index == -1) { throw new SecurityException("Package " + pkg.packageName + " has not requested permission " + name); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java index 5e66bfc3cd3e1..11df380427eb3 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionsState.java +++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java @@ -20,9 +20,9 @@ import android.content.pm.PackageManager; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; + import android.util.SparseArray; import android.util.SparseBooleanArray; - import com.android.internal.util.ArrayUtils; import java.util.ArrayList; @@ -290,13 +290,6 @@ public final class PermissionsState { return false; } - /** - * Returns whether the state has any known request for the given permission name, - * whether or not it has been granted. - */ - public boolean hasRequestedPermission(String name) { - return mPermissions != null && (mPermissions.get(name) != null); - } /** * Gets all permissions for a given device user id regardless if they * are install time or runtime permissions. From e1fb58dcea9d56fc558d295e7ed5844c98efe7cf Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Wed, 5 Sep 2018 18:52:35 -0700 Subject: [PATCH 11/20] Keep app in high memory adjust if moving from TOP to FGS If an app was in the TOP state and immediately moved to a foreground service state, then try harder to keep it in memory for another 20 seconds before releasing the memory to bound foreground services. Using an oom_adj value of 50 which is between "fore" and "vis". So BFGS apps might get killed ("vis") before this recently FGS'ed app. That way any app that has a lot of state in memory that it needs to persist before getting killed has a chance to do so. Also bind NotificationListeners with a special bind flag to rank them below FGS (perceptible adj) so that they can be killed before any other foreground services or bound services get killed. Bug: 110969183 Test: Manual for now. Take a bunch of portrait pictures and hit home, while being under memory pressure with a bunch of notification listeners. Change-Id: Ie8934c2331afe6450c582b209869aeca7272f58a Merged-In: Ie8934c2331afe6450c582b209869aeca7272f58a (cherry picked from commit b735830a1e71e72c4e72260d7eab0382b4ee19df) --- core/java/android/content/Context.java | 9 +++++++ .../server/am/ActivityManagerConstants.java | 11 +++++++- .../server/am/ActivityManagerService.java | 26 +++++++++++++++++++ .../com/android/server/am/ProcessList.java | 5 ++++ .../com/android/server/am/ProcessRecord.java | 6 +++++ .../server/notification/ManagedServices.java | 10 ++++--- .../NotificationManagerService.java | 14 ++++++++++ 7 files changed, 77 insertions(+), 4 deletions(-) diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 90a94ee76085b..b53202ef1741b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -325,6 +325,15 @@ public abstract class Context { */ public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080; + /** + * Flag for {@link #bindService}: If binding from something better than perceptible, + * still set the adjust below perceptible. This would be used for bound services that can + * afford to be evicted when under extreme memory pressure, but should be restarted as soon + * as possible. + * @hide + */ + public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100; + /** * @hide Flag for {@link #bindService}: allows binding to a service provided * by an instant app. Note that the caller may not have access to the instant diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 9bf72fb86cd6a..d14c1a1adf77e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -67,6 +67,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration"; static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry"; static final String KEY_PROCESS_START_ASYNC = "process_start_async"; + static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000; @@ -95,7 +96,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000; private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16; private static final boolean DEFAULT_PROCESS_START_ASYNC = true; - + private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000; // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; @@ -207,6 +208,10 @@ final class ActivityManagerConstants extends ContentObserver { // Indicates if the processes need to be started asynchronously. public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC; + // Allow app just moving from TOP to FOREGROUND_SERVICE to stay in a higher adj value for + // this long. + public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION; + // Indicates whether the activity starts logging is enabled. // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED boolean mFlagActivityStartsLoggingEnabled; @@ -348,6 +353,8 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY); FLAG_PROCESS_START_ASYNC = mParser.getBoolean(KEY_PROCESS_START_ASYNC, DEFAULT_PROCESS_START_ASYNC); + TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION, + DEFAULT_TOP_TO_FGS_GRACE_DURATION); updateMaxCachedProcesses(); } @@ -423,6 +430,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(MAX_SERVICE_INACTIVITY); pw.print(" "); pw.print(KEY_BG_START_TIMEOUT); pw.print("="); pw.println(BG_START_TIMEOUT); + pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("="); + pw.println(TOP_TO_FGS_GRACE_DURATION); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c5b8b950d4567..08161c91eff4e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -23376,6 +23376,19 @@ public class ActivityManagerService extends IActivityManager.Stub } } + // If the app was recently in the foreground and moved to a foreground service status, + // allow it to get a higher rank in memory for some time, compared to other foreground + // services so that it can finish performing any persistence/processing of in-memory state. + if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now + || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) { + adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; + app.adjType = "fg-service-act"; + if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { + reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app); + } + } + if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { if (app.forcingToImportant != null) { @@ -23640,6 +23653,10 @@ public class ActivityManagerService extends IActivityManager.Stub schedGroup = ProcessList.SCHED_GROUP_DEFAULT; procState = ActivityManager.PROCESS_STATE_PERSISTENT; } + } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0 + && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ + && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) { + newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1; } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) { @@ -24610,6 +24627,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Must be called before updating setProcState maybeUpdateUsageStatsLocked(app, nowElapsed); + maybeUpdateLastTopTime(app, now); + app.setProcState = app.curProcState; if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) { app.notCachedSinceIdle = false; @@ -24834,6 +24853,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) { + if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP + && app.curProcState > ActivityManager.PROCESS_STATE_TOP) { + app.lastTopTime = nowUptime; + } + } + private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) { if (proc.thread != null) { if (proc.baseProcessTracker != null) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 784d62e519664..3ac7885eba375 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -104,6 +104,11 @@ public final class ProcessList { static final int VISIBLE_APP_ADJ = 100; static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1; + // This is a process that was recently TOP and moved to FGS. Continue to treat it almost + // like a foreground app for a while. + // @see TOP_TO_FGS_GRACE_PERIOD + static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50; + // This is the process running the current foreground app. We'd really // rather not kill it! static final int FOREGROUND_APP_ADJ = 0; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 28ebbb87f261a..e3e839f631720 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -163,6 +163,7 @@ final class ProcessRecord { long lastRequestedGc; // When we last asked the app to do a gc long lastLowMemory; // When we last told the app that memory is low long lastProviderTime; // The last time someone else was using a provider in this process. + long lastTopTime; // The last time the process was in the TOP state or greater. boolean reportLowMemory; // Set to true when waiting to report low mem boolean empty; // Is this an empty background process? boolean cached; // Is this a cached process? @@ -380,6 +381,11 @@ final class ProcessRecord { TimeUtils.formatDuration(lastProviderTime, nowUptime, pw); pw.println(); } + if (lastTopTime > 0) { + pw.print(prefix); pw.print("lastTopTime="); + TimeUtils.formatDuration(lastTopTime, nowUptime, pw); + pw.println(); + } if (hasStartedServices) { pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices); } diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index f7becd5188612..30fa7fe4ce87c 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -175,6 +175,10 @@ abstract public class ManagedServices { } } + protected int getBindFlags() { + return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT; + } + protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } private ManagedServiceInfo newServiceInfo(IInterface service, @@ -1022,9 +1026,9 @@ abstract public class ManagedServices { } }; if (!mContext.bindServiceAsUser(intent, - serviceConnection, - BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT, - new UserHandle(userid))) { + serviceConnection, + getBindFlags(), + new UserHandle(userid))) { mServicesBinding.remove(servicesBindingTag); Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent); return; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 8304e2691979a..f2b7bbe636e57 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -33,6 +33,10 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; +import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE; +import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT; +import static android.content.Context.BIND_AUTO_CREATE; +import static android.content.Context.BIND_FOREGROUND_SERVICE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -6520,6 +6524,16 @@ public class NotificationManagerService extends SystemService { } + @Override + protected int getBindFlags() { + // Most of the same flags as the base, but also add BIND_ADJUST_BELOW_PERCEPTIBLE + // because too many 3P apps could be kept in memory as notification listeners and + // cause extreme memory pressure. + // TODO: Change the binding lifecycle of NotificationListeners to avoid this situation. + return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE + | BIND_ADJUST_BELOW_PERCEPTIBLE | BIND_ALLOW_WHITELIST_MANAGEMENT; + } + @Override protected Config getConfig() { Config c = new Config(); From fe0e09e4e384ec26a4a6f5ffba1f6e60dae2a7f4 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 4 Sep 2018 19:49:57 -0700 Subject: [PATCH 12/20] DO NOT MERGE: Reset launch start times when removing a process When removing an exiting process that is running foreground activities, clear the launch times for the current windowing mode. When an app process is removed, activities from the process may be relaunched. In the case of forceStopPackageLocked the activities are finished before any window is drawn, and the launch time is not cleared. This will be incorrectly used to calculate launch time for the next launched activity launched in the same windowing mode. Bug: 80084651 Test: adb shell am start -W com.amazon.mShop.android.shopping/com.amazon.mShop.home.HomeActivity && sleep 1 && adb shell am force-stop com.amazon.mShop.android.shopping Change-Id: I2c4f0716c922baa1ad209b4ea1fa7ce366e0e108 (cherry picked from commit 9372683dd2b6ceafee4714770b51e67066e3d8bc) --- .../android/server/am/ActivityManagerService.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c5b8b950d4567..2f1021a3dd9bb 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5889,6 +5889,7 @@ public class ActivityManagerService extends IActivityManager.Stub private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; + final boolean clearLaunchStartTime = !restarting && app.removed && app.foregroundActivities; boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, false /*replacingPid*/); if (!kept && !restarting) { @@ -5929,6 +5930,19 @@ public class ActivityManagerService extends IActivityManager.Stub } finally { mWindowManager.continueSurfaceLayout(); } + + // Hack for pi + // When an app process is removed, activities from the process may be relaunched. In the + // case of forceStopPackageLocked the activities are finished before any window is drawn, + // and the launch time is not cleared. This will be incorrectly used to calculate launch + // time for the next launched activity launched in the same windowing mode. + if (clearLaunchStartTime) { + final LaunchTimeTracker.Entry entry = mStackSupervisor + .getLaunchTimeTracker().getEntry(mStackSupervisor.getWindowingMode()); + if (entry != null) { + entry.mLaunchStartTime = 0; + } + } } private final int getLRURecordIndexForAppLocked(IApplicationThread thread) { From 553bb7c6a2b2c70b1cd011aec9bf9c151818d8c3 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Wed, 5 Sep 2018 18:52:35 -0700 Subject: [PATCH 13/20] Keep app in high memory adjust if moving from TOP to FGS If an app was in the TOP state and immediately moved to a foreground service state, then try harder to keep it in memory for another 20 seconds before releasing the memory to bound foreground services. Using an oom_adj value of 50 which is between "fore" and "vis". So BFGS apps might get killed ("vis") before this recently FGS'ed app. That way any app that has a lot of state in memory that it needs to persist before getting killed has a chance to do so. Also bind NotificationListeners with a special bind flag to rank them below FGS (perceptible adj) so that they can be killed before any other foreground services or bound services get killed. Bug: 110969183 Test: Manual for now. Take a bunch of portrait pictures and hit home, while being under memory pressure with a bunch of notification listeners. Change-Id: Ie8934c2331afe6450c582b209869aeca7272f58a Merged-In: Ie8934c2331afe6450c582b209869aeca7272f58a (cherry picked from commit b735830a1e71e72c4e72260d7eab0382b4ee19df) --- core/java/android/content/Context.java | 9 +++++++ .../server/am/ActivityManagerConstants.java | 11 +++++++- .../server/am/ActivityManagerService.java | 26 +++++++++++++++++++ .../com/android/server/am/ProcessList.java | 5 ++++ .../com/android/server/am/ProcessRecord.java | 6 +++++ .../server/notification/ManagedServices.java | 10 ++++--- .../NotificationManagerService.java | 14 ++++++++++ 7 files changed, 77 insertions(+), 4 deletions(-) diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 90a94ee76085b..b53202ef1741b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -325,6 +325,15 @@ public abstract class Context { */ public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080; + /** + * Flag for {@link #bindService}: If binding from something better than perceptible, + * still set the adjust below perceptible. This would be used for bound services that can + * afford to be evicted when under extreme memory pressure, but should be restarted as soon + * as possible. + * @hide + */ + public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100; + /** * @hide Flag for {@link #bindService}: allows binding to a service provided * by an instant app. Note that the caller may not have access to the instant diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 9bf72fb86cd6a..d14c1a1adf77e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -67,6 +67,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration"; static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry"; static final String KEY_PROCESS_START_ASYNC = "process_start_async"; + static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000; @@ -95,7 +96,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000; private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16; private static final boolean DEFAULT_PROCESS_START_ASYNC = true; - + private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000; // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; @@ -207,6 +208,10 @@ final class ActivityManagerConstants extends ContentObserver { // Indicates if the processes need to be started asynchronously. public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC; + // Allow app just moving from TOP to FOREGROUND_SERVICE to stay in a higher adj value for + // this long. + public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION; + // Indicates whether the activity starts logging is enabled. // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED boolean mFlagActivityStartsLoggingEnabled; @@ -348,6 +353,8 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY); FLAG_PROCESS_START_ASYNC = mParser.getBoolean(KEY_PROCESS_START_ASYNC, DEFAULT_PROCESS_START_ASYNC); + TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION, + DEFAULT_TOP_TO_FGS_GRACE_DURATION); updateMaxCachedProcesses(); } @@ -423,6 +430,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(MAX_SERVICE_INACTIVITY); pw.print(" "); pw.print(KEY_BG_START_TIMEOUT); pw.print("="); pw.println(BG_START_TIMEOUT); + pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("="); + pw.println(TOP_TO_FGS_GRACE_DURATION); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2f1021a3dd9bb..145c1c964a314 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -23390,6 +23390,19 @@ public class ActivityManagerService extends IActivityManager.Stub } } + // If the app was recently in the foreground and moved to a foreground service status, + // allow it to get a higher rank in memory for some time, compared to other foreground + // services so that it can finish performing any persistence/processing of in-memory state. + if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now + || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) { + adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; + app.adjType = "fg-service-act"; + if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { + reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app); + } + } + if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { if (app.forcingToImportant != null) { @@ -23654,6 +23667,10 @@ public class ActivityManagerService extends IActivityManager.Stub schedGroup = ProcessList.SCHED_GROUP_DEFAULT; procState = ActivityManager.PROCESS_STATE_PERSISTENT; } + } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0 + && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ + && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) { + newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1; } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) { @@ -24624,6 +24641,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Must be called before updating setProcState maybeUpdateUsageStatsLocked(app, nowElapsed); + maybeUpdateLastTopTime(app, now); + app.setProcState = app.curProcState; if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) { app.notCachedSinceIdle = false; @@ -24848,6 +24867,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) { + if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP + && app.curProcState > ActivityManager.PROCESS_STATE_TOP) { + app.lastTopTime = nowUptime; + } + } + private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) { if (proc.thread != null) { if (proc.baseProcessTracker != null) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 784d62e519664..3ac7885eba375 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -104,6 +104,11 @@ public final class ProcessList { static final int VISIBLE_APP_ADJ = 100; static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1; + // This is a process that was recently TOP and moved to FGS. Continue to treat it almost + // like a foreground app for a while. + // @see TOP_TO_FGS_GRACE_PERIOD + static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50; + // This is the process running the current foreground app. We'd really // rather not kill it! static final int FOREGROUND_APP_ADJ = 0; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 28ebbb87f261a..e3e839f631720 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -163,6 +163,7 @@ final class ProcessRecord { long lastRequestedGc; // When we last asked the app to do a gc long lastLowMemory; // When we last told the app that memory is low long lastProviderTime; // The last time someone else was using a provider in this process. + long lastTopTime; // The last time the process was in the TOP state or greater. boolean reportLowMemory; // Set to true when waiting to report low mem boolean empty; // Is this an empty background process? boolean cached; // Is this a cached process? @@ -380,6 +381,11 @@ final class ProcessRecord { TimeUtils.formatDuration(lastProviderTime, nowUptime, pw); pw.println(); } + if (lastTopTime > 0) { + pw.print(prefix); pw.print("lastTopTime="); + TimeUtils.formatDuration(lastTopTime, nowUptime, pw); + pw.println(); + } if (hasStartedServices) { pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices); } diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index f7becd5188612..30fa7fe4ce87c 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -175,6 +175,10 @@ abstract public class ManagedServices { } } + protected int getBindFlags() { + return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT; + } + protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } private ManagedServiceInfo newServiceInfo(IInterface service, @@ -1022,9 +1026,9 @@ abstract public class ManagedServices { } }; if (!mContext.bindServiceAsUser(intent, - serviceConnection, - BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT, - new UserHandle(userid))) { + serviceConnection, + getBindFlags(), + new UserHandle(userid))) { mServicesBinding.remove(servicesBindingTag); Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent); return; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 8304e2691979a..f2b7bbe636e57 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -33,6 +33,10 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; +import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE; +import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT; +import static android.content.Context.BIND_AUTO_CREATE; +import static android.content.Context.BIND_FOREGROUND_SERVICE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -6520,6 +6524,16 @@ public class NotificationManagerService extends SystemService { } + @Override + protected int getBindFlags() { + // Most of the same flags as the base, but also add BIND_ADJUST_BELOW_PERCEPTIBLE + // because too many 3P apps could be kept in memory as notification listeners and + // cause extreme memory pressure. + // TODO: Change the binding lifecycle of NotificationListeners to avoid this situation. + return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE + | BIND_ADJUST_BELOW_PERCEPTIBLE | BIND_ALLOW_WHITELIST_MANAGEMENT; + } + @Override protected Config getConfig() { Config c = new Config(); From 35f31cbac405b20ec1cd55714609c88f98a99c14 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 24 Sep 2018 13:23:57 -0600 Subject: [PATCH 14/20] Recover shady content:// paths. The path-permission element offers prefix or regex style matching of paths, but most providers internally use UriMatcher to decide what to do with an incoming Uri. This causes trouble because UriMatcher uses Uri.getPathSegments(), which quietly ignores "empty" paths. Consider this example: uriMatcher.addURI("com.example", "/private", CODE_PRIVATE); content://com.example//private The Uri above will pass the security check, since it's not technically a prefix match. But the UriMatcher will then match it as CODE_PRIVATE, since it ignores the "//" zero-length path. Since we can't safely change the behavior of either path-permission or UriMatcher, we're left with recovering these shady paths by trimming away zero-length paths. Bug: 112555574 Test: atest android.appsecurity.cts.AppSecurityTests Test: atest FrameworksCoreTests:android.content.ContentProviderTest Merged-In: Ibadbfa4fc904ec54780c8102958735b03293fb9a Change-Id: Ibadbfa4fc904ec54780c8102958735b03293fb9a (cherry picked from commit c084ddbf826b25808c4553e4b5992c6723eac4ea) --- .../java/android/content/ContentProvider.java | 53 ++++++++++++------- .../content/ContentProviderOperation.java | 16 +----- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index cdeaea3ebcae1..e2c898d153ee5 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -54,6 +54,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Objects; /** * Content providers are one of the primary building blocks of Android applications, providing @@ -208,7 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { // The caller has no access to the data, so return an empty cursor with @@ -247,14 +248,14 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public String getType(Uri uri) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); return ContentProvider.this.getType(uri); } @Override public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = maybeGetUriWithoutUserId(uri); if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { @@ -270,7 +271,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { return 0; @@ -292,11 +293,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 { for (int i = 0; i < numOperations; i++) { ContentProviderOperation operation = operations.get(i); Uri uri = operation.getUri(); - validateIncomingUri(uri); userIds[i] = getUserIdFromUri(uri); - if (userIds[i] != UserHandle.USER_CURRENT) { - // Removing the user id from the uri. - operation = new ContentProviderOperation(operation, true); + uri = validateIncomingUri(uri); + uri = maybeGetUriWithoutUserId(uri); + // Rebuild operation if we changed the Uri above + if (!Objects.equals(operation.getUri(), uri)) { + operation = new ContentProviderOperation(operation, uri); operations.set(i, operation); } if (operation.isReadOperation()) { @@ -331,7 +333,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { return 0; @@ -347,7 +349,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public int update(String callingPkg, Uri uri, ContentValues values, String selection, String[] selectionArgs) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { return 0; @@ -364,7 +366,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { public ParcelFileDescriptor openFile( String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken) throws FileNotFoundException { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(callingPkg, uri, mode, callerToken); final String original = setCallingPackage(callingPkg); @@ -380,7 +382,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { public AssetFileDescriptor openAssetFile( String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal) throws FileNotFoundException { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(callingPkg, uri, mode, null); final String original = setCallingPackage(callingPkg); @@ -406,7 +408,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter); } @@ -415,7 +417,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType, Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException { Bundle.setDefusable(opts, true); - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(callingPkg, uri, "r", null); final String original = setCallingPackage(callingPkg); @@ -434,7 +436,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public Uri canonicalize(String callingPkg, Uri uri) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = getUriWithoutUserId(uri); if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { @@ -450,7 +452,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public Uri uncanonicalize(String callingPkg, Uri uri) { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = getUriWithoutUserId(uri); if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { @@ -467,7 +469,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { @Override public boolean refresh(String callingPkg, Uri uri, Bundle args, ICancellationSignal cancellationSignal) throws RemoteException { - validateIncomingUri(uri); + uri = validateIncomingUri(uri); uri = getUriWithoutUserId(uri); if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { return false; @@ -1901,7 +1903,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { */ if (mContext == null) { mContext = context; - if (context != null) { + if (context != null && mTransport != null) { mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); } @@ -2010,7 +2012,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } /** @hide */ - private void validateIncomingUri(Uri uri) throws SecurityException { + public Uri validateIncomingUri(Uri uri) throws SecurityException { String auth = uri.getAuthority(); if (!mSingleUser) { int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT); @@ -2029,6 +2031,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } throw new SecurityException(message); } + + // Normalize the path by removing any empty path segments, which can be + // a source of security issues. + final String encodedPath = uri.getEncodedPath(); + if (encodedPath != null && encodedPath.indexOf("//") != -1) { + final Uri normalized = uri.buildUpon() + .encodedPath(encodedPath.replaceAll("//+", "/")).build(); + Log.w(TAG, "Normalized " + uri + " to " + normalized + + " to avoid possible security issues"); + return normalized; + } else { + return uri; + } } /** @hide */ diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java index 8f3a31746266a..f3914f2a4e765 100644 --- a/core/java/android/content/ContentProviderOperation.java +++ b/core/java/android/content/ContentProviderOperation.java @@ -94,13 +94,9 @@ public class ContentProviderOperation implements Parcelable { } /** @hide */ - public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) { + public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) { mType = cpo.mType; - if (removeUserIdFromUri) { - mUri = ContentProvider.getUriWithoutUserId(cpo.mUri); - } else { - mUri = cpo.mUri; - } + mUri = withUri; mValues = cpo.mValues; mSelection = cpo.mSelection; mSelectionArgs = cpo.mSelectionArgs; @@ -110,14 +106,6 @@ public class ContentProviderOperation implements Parcelable { mYieldAllowed = cpo.mYieldAllowed; } - /** @hide */ - public ContentProviderOperation getWithoutUserIdInUri() { - if (ContentProvider.uriHasUserId(mUri)) { - return new ContentProviderOperation(this, true); - } - return this; - } - public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); Uri.writeToParcel(dest, mUri); From 7d4945ca8664c7e5def08ce4bbd6841a1bfac174 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 15 Oct 2018 16:29:15 -0700 Subject: [PATCH 15/20] hwui: purge malloc pages on bitmap destruction Immediately purge malloc pages on bitmap destruction. Bitmaps are often big and can cause memory to stay high for much longer than it should. Test: boots and works bug 117795621 Merged-in: If2e8c5f1fc07039cf3dc3edcd3dc06861dbce1a1 Change-Id: If2e8c5f1fc07039cf3dc3edcd3dc06861dbce1a1 (cherry picked from commit 535fae32e597445a480896ea8e01662ada444c0c) --- libs/hwui/hwui/Bitmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 263d249d20e98..c6ef090c1f763 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -223,6 +223,7 @@ Bitmap::~Bitmap() { break; case PixelStorageType::Heap: free(mPixelStorage.heap.address); + mallopt(M_PURGE, 0); break; case PixelStorageType::Hardware: auto buffer = mPixelStorage.hardware.buffer; @@ -230,7 +231,6 @@ Bitmap::~Bitmap() { mPixelStorage.hardware.buffer = nullptr; break; } - android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID()); } From 64ea6ca2e39b779495feb695033c414ebfe62ac0 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 15 Oct 2018 16:50:23 -0700 Subject: [PATCH 16/20] wm: recycle bitmaps immediately in TaskSnapshotPersister Bitmap created in TaskSnapshotPersister are very short lived and shouldn't be left around in the Java heap. Test: boot, switch apps, works bug 117795621 Merged-in: I4b5e0db50c2b7adaa71cb0d22535c1b37c7523e8 Change-Id: I4b5e0db50c2b7adaa71cb0d22535c1b37c7523e8 (cherry picked from commit 9b4eaf740957663b01d4bf056df250dd028e0cb0) --- .../core/java/com/android/server/wm/TaskSnapshotPersister.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index a642e6ab744ae..d1c0443c58e12 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -360,6 +360,7 @@ class TaskSnapshotPersister { // For snapshots with reduced resolution, do not create or save full sized bitmaps if (mSnapshot.isReducedResolution()) { + swBitmap.recycle(); return true; } @@ -372,6 +373,8 @@ class TaskSnapshotPersister { Slog.e(TAG, "Unable to open " + file + " for persisting.", e); return false; } + reduced.recycle(); + swBitmap.recycle(); return true; } } From 7105e37a8c6d4dcf95695298486b25b8c43a6a7e Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Fri, 19 Oct 2018 18:12:40 -0400 Subject: [PATCH 17/20] Add configurable default setting for assistant componentname By requiring an explicit default setting, it eliminates all ambiguous states where a disambiguation would normally be shown. With this change in place, at no point should a disambiguation be shown. (Note: this is a fix to Change-Id: Ib32daf that clarifies the logic if R.string.config_defaultAssistantComponentName has not been set in a given build.) Test: manual Bug: 111603898 Change-Id: Id39fdf700ed4ef08ebbc333b5452223430ac2e48 Merged-In: Ib32dafbd3c6fcbe11186dc8ecab6b09c9b734067 (cherry picked from commit c6ed3a29f0e2f0f1ceb727c5ece07702987e4ba5) --- .../com/android/internal/app/AssistUtils.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java index 9171959537c87..fed0a89a4d75f 100644 --- a/core/java/com/android/internal/app/AssistUtils.java +++ b/core/java/com/android/internal/app/AssistUtils.java @@ -32,6 +32,8 @@ import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; +import com.android.internal.R; + /** * Utility method for dealing with the assistant aspects of * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}. @@ -40,6 +42,14 @@ public class AssistUtils { private static final String TAG = "AssistUtils"; + /** + * Sentinel value for "no default assistant specified." + * + * Empty string is already used to represent an explicit setting of No Assistant. null cannot + * be used because we can't represent a null value in XML. + */ + private static final String UNSET = "#+UNSET"; + private final Context mContext; private final IVoiceInteractionManagerService mVoiceInteractionManagerService; @@ -152,10 +162,21 @@ public class AssistUtils { return ComponentName.unflattenFromString(setting); } + final String defaultSetting = mContext.getResources().getString( + R.string.config_defaultAssistantComponentName); + if (defaultSetting != null && !defaultSetting.equals(UNSET)) { + return ComponentName.unflattenFromString(defaultSetting); + } + // Fallback to keep backward compatible behavior when there is no user setting. if (activeServiceSupportsAssistGesture()) { return getActiveServiceComponentName(); } + + if (UNSET.equals(defaultSetting)) { + return null; + } + final SearchManager searchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); if (searchManager == null) { From 3a1a64c045ffe89823d8cf2df17655d119f967ba Mon Sep 17 00:00:00 2001 From: Adam Seaton Date: Mon, 22 Oct 2018 13:07:18 -0700 Subject: [PATCH 18/20] Add Missing XML files from 5282778 to fix build Bug:111603898 (cherry picked from commit 974a86e201e2fa17bad58d1fb2f83b7d21ed1580) Change-Id: Ica3e8254b90ce5a5ce697d7f5dd683fdd148492e --- core/res/res/values/config.xml | 6 +++++- core/res/res/values/symbols.xml | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index a9d69c1bcbbe7..edeaa1e4ec3fe 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3515,4 +3515,8 @@ - + + + + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a3ed1b0526d0a..864c4acadc6c1 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3415,4 +3415,6 @@ + + From 12f511e1ab9e38b35a0d3d4a6f5bf89017768d40 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 22 Oct 2018 15:26:08 -0700 Subject: [PATCH 19/20] ActivityThread: purge jemalloc at appropriate times Don't let jemalloc sit around with unused pages. Test: boots, works bug 117795621 Change-Id: I1fc3fcf5aa2798c67ea8cada6eeec852b2bebee7 (cherry picked from commit 7745ba061a0ef3e20470ed98267e2062b407ba79) --- core/java/android/app/ActivityThread.java | 40 ++++++++++++++- core/jni/Android.bp | 1 + core/jni/android_app_ActivityThread.cpp | 55 +++++++++++++++++++++ core/jni/android_view_DisplayListCanvas.cpp | 22 --------- 4 files changed, 95 insertions(+), 23 deletions(-) create mode 100644 core/jni/android_app_ActivityThread.cpp diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ab0b88c22d28c..14a622a68fad7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -359,6 +359,9 @@ public final class ActivityThread extends ClientTransactionHandler { = new ArrayMap>(); final GcIdler mGcIdler = new GcIdler(); + final PurgeIdler mPurgeIdler = new PurgeIdler(); + + boolean mPurgeIdlerScheduled = false; boolean mGcIdlerScheduled = false; static volatile Handler sMainThreadHandler; // set once in main() @@ -1595,6 +1598,7 @@ public final class ActivityThread extends ClientTransactionHandler { public static final int RUN_ISOLATED_ENTRY_POINT = 158; public static final int EXECUTE_TRANSACTION = 159; public static final int RELAUNCH_ACTIVITY = 160; + public static final int PURGE_RESOURCES = 161; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1638,6 +1642,7 @@ public final class ActivityThread extends ClientTransactionHandler { case RUN_ISOLATED_ENTRY_POINT: return "RUN_ISOLATED_ENTRY_POINT"; case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION"; case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; + case PURGE_RESOURCES: return "PURGE_RESOURCES"; } } return Integer.toString(code); @@ -1675,6 +1680,7 @@ public final class ActivityThread extends ClientTransactionHandler { case UNBIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind"); handleUnbindService((BindServiceData)msg.obj); + schedulePurgeIdler(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case SERVICE_ARGS: @@ -1685,6 +1691,7 @@ public final class ActivityThread extends ClientTransactionHandler { case STOP_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop"); handleStopService((IBinder)msg.obj); + schedulePurgeIdler(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CONFIGURATION_CHANGED: @@ -1818,6 +1825,9 @@ public final class ActivityThread extends ClientTransactionHandler { case RELAUNCH_ACTIVITY: handleRelaunchActivityLocally((IBinder) msg.obj); break; + case PURGE_RESOURCES: + schedulePurgeIdler(); + break; } Object obj = msg.obj; if (obj instanceof SomeArgs) { @@ -1870,6 +1880,17 @@ public final class ActivityThread extends ClientTransactionHandler { @Override public final boolean queueIdle() { doGcIfNeeded(); + nPurgePendingResources(); + return false; + } + } + + final class PurgeIdler implements MessageQueue.IdleHandler { + @Override + public boolean queueIdle() { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "purgePendingResources"); + nPurgePendingResources(); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return false; } } @@ -2181,6 +2202,22 @@ public final class ActivityThread extends ClientTransactionHandler { mH.removeMessages(H.GC_WHEN_IDLE); } + void schedulePurgeIdler() { + if (!mPurgeIdlerScheduled) { + mPurgeIdlerScheduled = true; + Looper.myQueue().addIdleHandler(mPurgeIdler); + } + mH.removeMessages(H.PURGE_RESOURCES); + } + + void unschedulePurgeIdler() { + if (mPurgeIdlerScheduled) { + mPurgeIdlerScheduled = false; + Looper.myQueue().removeIdleHandler(mPurgeIdler); + } + mH.removeMessages(H.PURGE_RESOURCES); + } + void doGcIfNeeded() { mGcIdlerScheduled = false; final long now = SystemClock.uptimeMillis(); @@ -4461,6 +4498,7 @@ public final class ActivityThread extends ClientTransactionHandler { } r.setState(ON_DESTROY); } + schedulePurgeIdler(); mActivities.remove(token); StrictMode.decrementExpectedActivityCount(activityClass); return r; @@ -6683,6 +6721,6 @@ public final class ActivityThread extends ClientTransactionHandler { } // ------------------ Regular JNI ------------------------ - + private native void nPurgePendingResources(); private native void nDumpGraphicsInfo(FileDescriptor fd); } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 302189fbb7008..13bd523e0d993 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -42,6 +42,7 @@ cc_library_shared { "com_google_android_gles_jni_EGLImpl.cpp", "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm "android_app_Activity.cpp", + "android_app_ActivityThread.cpp", "android_app_NativeActivity.cpp", "android_app_admin_SecurityLog.cpp", "android_opengl_EGL14.cpp", diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp new file mode 100644 index 0000000000000..d56e4c51124dd --- /dev/null +++ b/core/jni/android_app_ActivityThread.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 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. + */ + +#include "jni.h" +#include "GraphicsJNI.h" +#include + +#include +#include + +#include "core_jni_helpers.h" +#include + +namespace android { + +static void android_app_ActivityThread_purgePendingResources(JNIEnv* env, jobject clazz) { + // Don't care about return values. + mallopt(M_PURGE, 0); +} + +static void +android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { + int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); + android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd); + minikin::Layout::dumpMinikinStats(fd); +} + + +static JNINativeMethod gActivityThreadMethods[] = { + // ------------ Regular JNI ------------------ + { "nPurgePendingResources", "()V", + (void*) android_app_ActivityThread_purgePendingResources }, + { "nDumpGraphicsInfo", "(Ljava/io/FileDescriptor;)V", + (void*) android_app_ActivityThread_dumpGraphics } +}; + +int register_android_app_ActivityThread(JNIEnv* env) { + return RegisterMethodsOrDie(env, "android/app/ActivityThread", + gActivityThreadMethods, NELEM(gActivityThreadMethods)); +} + +}; diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp index 7956bf4ee222b..5197e7d481eba 100644 --- a/core/jni/android_view_DisplayListCanvas.cpp +++ b/core/jni/android_view_DisplayListCanvas.cpp @@ -88,17 +88,6 @@ private: sp mMessage; }; - -// ---------------- Regular JNI ----------------------------- - -static void -android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { - int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); - android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd); - minikin::Layout::dumpMinikinStats(fd); -} - - // ---------------- @FastNative ----------------------------- static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz, @@ -215,12 +204,6 @@ static JNINativeMethod gMethods[] = { { "nDrawRoundRect", "(JJJJJJJJ)V",(void*) android_view_DisplayListCanvas_drawRoundRectProps }, }; -static JNINativeMethod gActivityThreadMethods[] = { - // ------------ Regular JNI ------------------ - { "nDumpGraphicsInfo", "(Ljava/io/FileDescriptor;)V", - (void*) android_app_ActivityThread_dumpGraphics } -}; - int register_android_view_DisplayListCanvas(JNIEnv* env) { jclass runnableClass = FindClassOrDie(env, "java/lang/Runnable"); gRunnableMethodId = GetMethodIDOrDie(env, runnableClass, "run", "()V"); @@ -228,9 +211,4 @@ int register_android_view_DisplayListCanvas(JNIEnv* env) { return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } -int register_android_app_ActivityThread(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/app/ActivityThread", - gActivityThreadMethods, NELEM(gActivityThreadMethods)); -} - }; From 75e3e041fb63ea000c555505c4066e68f29112fb Mon Sep 17 00:00:00 2001 From: Amit Mahajan Date: Mon, 22 Oct 2018 10:43:34 -0700 Subject: [PATCH 20/20] Adding new intent ACTION_SMS_MMS_DB_CREATED. Test: manual (verified from logcat that intent is broadcast) Bug: 115990430 Merged-in: I660cf2d04a1b57a58c8cefd212e5f8d73b329890 Change-Id: I660cf2d04a1b57a58c8cefd212e5f8d73b329890 (cherry picked from commit 8c1c45a710a4955b0add308c8c640f9c61a7db31) (cherry picked from commit 1b26e44ce0792eda6b9bb2fa6b273842a8bf8ae3) --- core/res/AndroidManifest.xml | 1 + .../java/android/provider/Telephony.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cda1293e93c77..8cadd8c332cf6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -399,6 +399,7 @@ + diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index f2438b833d908..d6814f918f581 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -1150,6 +1150,33 @@ public final class Telephony { public static final String ACTION_EXTERNAL_PROVIDER_CHANGE = "android.provider.action.EXTERNAL_PROVIDER_CHANGE"; + /** + * Broadcast action: When SMS-MMS db is being created. If file-based encryption is + * supported, this broadcast indicates creation of the db in credential-encrypted + * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if + * this is the initial create of the db. Requires + * {@link android.Manifest.permission#READ_SMS} to receive. + * + * @see #EXTRA_IS_INITIAL_CREATE + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SMS_MMS_DB_CREATED = + "android.provider.action.SMS_MMS_DB_CREATED"; + + /** + * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_CREATED} to indicate + * whether the DB creation is the initial creation on the device, that is it is after a + * factory-data reset or a new device. Any subsequent creations of the DB (which + * happens only in error scenarios) will have this flag set to false. + * + * @see #ACTION_SMS_MMS_DB_CREATED + * + * @hide + */ + public static final String EXTRA_IS_INITIAL_CREATE = + "android.provider.extra.IS_INITIAL_CREATE"; /** * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a * {@link #DATA_SMS_RECEIVED_ACTION} intent.