diff options
36 files changed, 1040 insertions, 242 deletions
diff --git a/api/current.txt b/api/current.txt index 9425b81ee2d1..97361681f1a4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -41783,6 +41783,7 @@ package android.service.autofill { } public static final class Dataset.Builder { + ctor public Dataset.Builder(@NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation); ctor public Dataset.Builder(@NonNull android.widget.RemoteViews); ctor public Dataset.Builder(); method @NonNull public android.service.autofill.Dataset build(); @@ -41792,6 +41793,8 @@ package android.service.autofill { method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @NonNull android.widget.RemoteViews); method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern); method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.widget.RemoteViews); + method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation); + method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation); } public final class DateTransformation implements android.os.Parcelable android.service.autofill.Transformation { @@ -41880,7 +41883,6 @@ package android.service.autofill { public static final class FillResponse.Builder { ctor public FillResponse.Builder(); method @NonNull public android.service.autofill.FillResponse.Builder addDataset(@Nullable android.service.autofill.Dataset); - method @NonNull public android.service.autofill.FillResponse.Builder addInlineSuggestionSlice(@NonNull android.app.slice.Slice); method @NonNull public android.service.autofill.FillResponse build(); method @NonNull public android.service.autofill.FillResponse.Builder disableAutofill(long); method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews); @@ -41909,6 +41911,15 @@ package android.service.autofill { method public android.service.autofill.ImageTransformation build(); } + public final class InlinePresentation implements android.os.Parcelable { + ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec); + method public int describeContents(); + method @NonNull public android.view.inline.InlinePresentationSpec getInlinePresentationSpec(); + method @NonNull public android.app.slice.Slice getSlice(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.InlinePresentation> CREATOR; + } + public final class LuhnChecksumValidator implements android.os.Parcelable android.service.autofill.Validator { ctor public LuhnChecksumValidator(@NonNull android.view.autofill.AutofillId...); method public int describeContents(); diff --git a/api/system-current.txt b/api/system-current.txt index 6b2aea561f45..312cfc4855cb 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4331,6 +4331,15 @@ package android.media.soundtrigger { package android.media.tv { + public final class DvbDeviceInfo implements android.os.Parcelable { + ctor public DvbDeviceInfo(int, int); + method public int describeContents(); + method public int getAdapterId(); + method public int getDeviceId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR; + } + public final class TvContentRatingSystemInfo implements android.os.Parcelable { method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo); method public int describeContents(); @@ -4445,12 +4454,14 @@ package android.media.tv { method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String); + method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList(); method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList(); method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList(); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean isSingleSessionActive(); method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramAddedToWatchNext(String, long, long); method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramBrowsableDisabled(String, long); method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyWatchNextProgramBrowsableDisabled(String, long); + method @Nullable @RequiresPermission("android.permission.DVB_DEVICE") public android.os.ParcelFileDescriptor openDvbDevice(@NonNull android.media.tv.DvbDeviceInfo, int); method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public void releaseTvInputHardware(int, android.media.tv.TvInputManager.Hardware); method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void removeBlockedRating(@NonNull android.media.tv.TvContentRating); method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void setParentalControlsEnabled(boolean); @@ -7731,6 +7742,9 @@ package android.provider { } public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns { + field @NonNull public static final String AUTHORITY_LEGACY = "cellbroadcast-legacy"; + field @NonNull public static final android.net.Uri AUTHORITY_LEGACY_URI; + field @NonNull public static final String CALL_METHOD_GET_PREFERENCE = "get_preference"; field public static final String CID = "cid"; field public static final String CMAS_CATEGORY = "cmas_category"; field public static final String CMAS_CERTAINTY = "cmas_certainty"; @@ -7761,6 +7775,21 @@ package android.provider { field public static final String SUB_ID = "sub_id"; } + public static final class Telephony.CellBroadcasts.Preference { + field @NonNull public static final String ENABLE_ALERT_VIBRATION_PREF = "enable_alert_vibrate"; + field @NonNull public static final String ENABLE_AREA_UPDATE_INFO_PREF = "enable_area_update_info_alerts"; + field @NonNull public static final String ENABLE_CMAS_AMBER_PREF = "enable_cmas_amber_alerts"; + field @NonNull public static final String ENABLE_CMAS_EXTREME_THREAT_PREF = "enable_cmas_extreme_threat_alerts"; + field @NonNull public static final String ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF = "receive_cmas_in_second_language"; + field @NonNull public static final String ENABLE_CMAS_PRESIDENTIAL_PREF = "enable_cmas_presidential_alerts"; + field @NonNull public static final String ENABLE_CMAS_SEVERE_THREAT_PREF = "enable_cmas_severe_threat_alerts"; + field @NonNull public static final String ENABLE_EMERGENCY_PERF = "enable_emergency_alerts"; + field @NonNull public static final String ENABLE_FULL_VOLUME_PREF = "use_full_volume"; + field @NonNull public static final String ENABLE_PUBLIC_SAFETY_PREF = "enable_public_safety_messages"; + field @NonNull public static final String ENABLE_STATE_LOCAL_TEST_PREF = "enable_state_local_test_alerts"; + field @NonNull public static final String ENABLE_TEST_ALERT_PREF = "enable_test_alerts"; + } + public static final class Telephony.SimInfo { field @NonNull public static final android.net.Uri CONTENT_URI; } @@ -7989,6 +8018,11 @@ package android.service.autofill { field public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm"; } + public static final class Dataset.Builder { + ctor public Dataset.Builder(@NonNull android.service.autofill.InlinePresentation); + method @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.service.autofill.InlinePresentation); + } + } package android.service.autofill.augmented { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 3f9f7fbbe477..9aef20b29490 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3107,7 +3107,7 @@ public class ActivityManager { public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; /** - * Constant for {@link #importance}: This process is contains services + * Constant for {@link #importance}: This process contains services * that should remain running. These are background services apps have * started, not something the user is aware of, so they may be killed by * the system relatively freely (though it is generally desired that they diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java index 48d5cd2d65a5..611b66bc0265 100644 --- a/core/java/android/app/timedetector/TimeDetector.java +++ b/core/java/android/app/timedetector/TimeDetector.java @@ -48,7 +48,7 @@ public class TimeDetector { * signal if better signals are available such as those that come from more reliable sources or * were determined more recently. */ - @RequiresPermission(android.Manifest.permission.SET_TIME) + @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE) public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) { if (DEBUG) { Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion); @@ -63,7 +63,7 @@ public class TimeDetector { /** * Suggests the user's manually entered current time to the detector. */ - @RequiresPermission(android.Manifest.permission.SET_TIME) + @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE) public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) { if (DEBUG) { Log.d(TAG, "suggestManualTime called: " + timeSuggestion); diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java index 387a36bba608..e165d8a76caa 100644 --- a/core/java/android/app/timezonedetector/TimeZoneDetector.java +++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java @@ -47,7 +47,7 @@ public class TimeZoneDetector { * detector may ignore the signal based on system settings, whether better information is * available, and so on. */ - @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE) + @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE) public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) { if (DEBUG) { Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion); @@ -63,7 +63,7 @@ public class TimeZoneDetector { * Suggests the current time zone, determined for the user's manually information, to the * detector. The detector may ignore the signal based on system settings. */ - @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE) + @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE) public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) { if (DEBUG) { Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion); diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 3d449446af82..9f592e8d9718 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -1888,10 +1888,13 @@ public final class Debug /** * Note: currently only works when the requested pid has the same UID * as the caller. + * + * @return true if the meminfo was read successfully, false if not (i.e., given pid has gone). + * * @hide */ @UnsupportedAppUsage - public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo); + public static native boolean getMemoryInfo(int pid, MemoryInfo memoryInfo); /** * Retrieves the PSS memory used by the process as given by the @@ -1904,6 +1907,8 @@ public final class Debug * array of up to 3 entries to also receive (up to 3 values in order): the Uss and SwapPss and * Rss (only filled in as of {@link android.os.Build.VERSION_CODES#P}) of the process, and * another array to also retrieve the separate memtrack size. + * + * @return The PSS memory usage, or 0 if failed to retrieve (i.e., given pid has gone). * @hide */ public static native long getPss(int pid, long[] outUssSwapPssRss, long[] outMemtrack); diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index c95e132917d0..2aa346cf94cc 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -36,6 +36,7 @@ import android.database.Cursor; import android.database.sqlite.SqliteWrapper; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.os.Parcel; import android.telephony.Rlog; import android.telephony.ServiceState; @@ -4105,6 +4106,113 @@ public final class Telephony { public static final Uri MESSAGE_HISTORY_URI = Uri.parse("content://cellbroadcasts/history"); /** + * The authority for the legacy cellbroadcast provider. + * This is used for OEM data migration. OEMs want to migrate message history or + * sharepreference data to mainlined cellbroadcastreceiver app, should have a + * contentprovider with authority: cellbroadcast-legacy. Mainlined cellbroadcastreceiver + * will interact with this URI to retrieve data and persists to mainlined cellbroadcast app. + * + * @hide + */ + @SystemApi + public static final @NonNull String AUTHORITY_LEGACY = "cellbroadcast-legacy"; + + /** + * A content:// style uri to the authority for the legacy cellbroadcast provider. + * @hide + */ + @SystemApi + public static final @NonNull Uri AUTHORITY_LEGACY_URI = + Uri.parse("content://cellbroadcast-legacy"); + + /** + * Method name to {@link android.content.ContentProvider#call(String, String, Bundle) + * for {@link #AUTHORITY_LEGACY}. Used to query cellbroadcast {@link Preference}, + * containing following supported entries + * <ul> + * <li>{@link #ENABLE_AREA_UPDATE_INFO_PREF}</li> + * <li>{@link #ENABLE_TEST_ALERT_PREF}</li> + * <li>{@link #ENABLE_STATE_LOCAL_TEST_PREF}</li> + * <li>{@link #ENABLE_PUBLIC_SAFETY_PREF}</li> + * <li>{@link #ENABLE_CMAS_AMBER_PREF}</li> + * <li>{@link #ENABLE_CMAS_SEVERE_THREAT_PREF}</li> + * <li>{@link #ENABLE_CMAS_EXTREME_THREAT_PREF}</li> + * <li>{@link #ENABLE_CMAS_PRESIDENTIAL_PREF}</li> + * <li>{@link #ENABLE_ALERT_VIBRATION_PREF}</li> + * <li>{@link #ENABLE_EMERGENCY_PERF}</li> + * <li>{@link #ENABLE_FULL_VOLUME_PREF}</li> + * <li>{@link #ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF}</li> + * </ul> + * @hide + */ + @SystemApi + public static final @NonNull String CALL_METHOD_GET_PREFERENCE = "get_preference"; + + /** + * Arg name to {@link android.content.ContentProvider#call(String, String, Bundle)} + * for {@link #AUTHORITY_LEGACY}. + * Contains all supported shared preferences for cellbroadcast. + * + * @hide + */ + @SystemApi + public static final class Preference { + /** + * Not Instantiatable. + * @hide + */ + private Preference() {} + + /** Preference to enable area update info alert */ + public static final @NonNull String ENABLE_AREA_UPDATE_INFO_PREF = + "enable_area_update_info_alerts"; + + /** Preference to enable test alert */ + public static final @NonNull String ENABLE_TEST_ALERT_PREF = + "enable_test_alerts"; + + /** Preference to enable state local test alert */ + public static final @NonNull String ENABLE_STATE_LOCAL_TEST_PREF + = "enable_state_local_test_alerts"; + + /** Preference to enable public safety alert */ + public static final @NonNull String ENABLE_PUBLIC_SAFETY_PREF + = "enable_public_safety_messages"; + + /** Preference to enable amber alert */ + public static final @NonNull String ENABLE_CMAS_AMBER_PREF + = "enable_cmas_amber_alerts"; + + /** Preference to enable severe threat alert */ + public static final @NonNull String ENABLE_CMAS_SEVERE_THREAT_PREF + = "enable_cmas_severe_threat_alerts"; + + /** Preference to enable extreme threat alert */ + public static final @NonNull String ENABLE_CMAS_EXTREME_THREAT_PREF = + "enable_cmas_extreme_threat_alerts"; + + /** Preference to enable presidential alert */ + public static final @NonNull String ENABLE_CMAS_PRESIDENTIAL_PREF = + "enable_cmas_presidential_alerts"; + + /** Preference to enable alert vibration */ + public static final @NonNull String ENABLE_ALERT_VIBRATION_PREF = + "enable_alert_vibrate"; + + /** Preference to enable emergency alert */ + public static final @NonNull String ENABLE_EMERGENCY_PERF = + "enable_emergency_alerts"; + + /** Preference to enable volume for alerts */ + public static final @NonNull String ENABLE_FULL_VOLUME_PREF = + "use_full_volume"; + + /** Preference to enable receive alerts in second language */ + public static final @NonNull String ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF = + "receive_cmas_in_second_language"; + } + + /** * The subscription which received this cell broadcast message. * <P>Type: INTEGER</P> */ diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index d53e62a4fc90..d827b30f27b6 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -20,6 +20,7 @@ import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.IntentSender; import android.os.Parcel; import android.os.Parcelable; @@ -56,6 +57,10 @@ import java.util.regex.Pattern; * all datasets pairs that have that view's {@link AutofillId}. Then, when the user selects a * dataset from the UI, all views in that dataset are autofilled. * + * <p>If both the current Input Method and autofill service supports inline suggestions, the Dataset + * can be shown by the keyboard as a suggestion. To use this feature, the Dataset should contain + * an {@link InlinePresentation} representing how the inline suggestion UI will be rendered. + * * <a name="Authentication"></a> * <h3>Dataset authentication</h3> * @@ -99,8 +104,10 @@ public final class Dataset implements Parcelable { private final ArrayList<AutofillId> mFieldIds; private final ArrayList<AutofillValue> mFieldValues; private final ArrayList<RemoteViews> mFieldPresentations; + private final ArrayList<InlinePresentation> mFieldInlinePresentations; private final ArrayList<DatasetFieldFilter> mFieldFilters; private final RemoteViews mPresentation; + @Nullable private final InlinePresentation mInlinePresentation; private final IntentSender mAuthentication; @Nullable String mId; @@ -108,8 +115,10 @@ public final class Dataset implements Parcelable { mFieldIds = builder.mFieldIds; mFieldValues = builder.mFieldValues; mFieldPresentations = builder.mFieldPresentations; + mFieldInlinePresentations = builder.mFieldInlinePresentations; mFieldFilters = builder.mFieldFilters; mPresentation = builder.mPresentation; + mInlinePresentation = builder.mInlinePresentation; mAuthentication = builder.mAuthentication; mId = builder.mId; } @@ -132,6 +141,13 @@ public final class Dataset implements Parcelable { /** @hide */ @Nullable + public InlinePresentation getFieldInlinePresentation(int index) { + final InlinePresentation inlinePresentation = mFieldInlinePresentations.get(index); + return inlinePresentation != null ? inlinePresentation : mInlinePresentation; + } + + /** @hide */ + @Nullable public DatasetFieldFilter getFilter(int index) { return mFieldFilters.get(index); } @@ -165,7 +181,9 @@ public final class Dataset implements Parcelable { } if (mFieldPresentations != null) { builder.append(", fieldPresentations=").append(mFieldPresentations.size()); - + } + if (mFieldInlinePresentations != null) { + builder.append(", fieldInlinePresentations=").append(mFieldInlinePresentations.size()); } if (mFieldFilters != null) { builder.append(", fieldFilters=").append(mFieldFilters.size()); @@ -173,6 +191,9 @@ public final class Dataset implements Parcelable { if (mPresentation != null) { builder.append(", hasPresentation"); } + if (mInlinePresentation != null) { + builder.append(", hasInlinePresentation"); + } if (mAuthentication != null) { builder.append(", hasAuthentication"); } @@ -198,8 +219,10 @@ public final class Dataset implements Parcelable { private ArrayList<AutofillId> mFieldIds; private ArrayList<AutofillValue> mFieldValues; private ArrayList<RemoteViews> mFieldPresentations; + private ArrayList<InlinePresentation> mFieldInlinePresentations; private ArrayList<DatasetFieldFilter> mFieldFilters; private RemoteViews mPresentation; + @Nullable private InlinePresentation mInlinePresentation; private IntentSender mAuthentication; private boolean mDestroyed; @Nullable private String mId; @@ -208,10 +231,39 @@ public final class Dataset implements Parcelable { * Creates a new builder. * * @param presentation The presentation used to visualize this dataset. + * @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset + * as inline suggestions. If the dataset supports inline suggestions, + * this should not be null. */ - public Builder(@NonNull RemoteViews presentation) { + public Builder(@NonNull RemoteViews presentation, + @NonNull InlinePresentation inlinePresentation) { Preconditions.checkNotNull(presentation, "presentation must be non-null"); mPresentation = presentation; + mInlinePresentation = inlinePresentation; + } + + /** + * Creates a new builder. + * + * @param presentation The presentation used to visualize this dataset. + */ + public Builder(@NonNull RemoteViews presentation) { + this(presentation, null); + } + + /** + * Creates a new builder. + * + * <p>Only called by augmented autofill. + * + * @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset + * as inline suggestions. If the dataset supports inline suggestions, + * this should not be null. + * @hide + */ + @SystemApi + public Builder(@NonNull InlinePresentation inlinePresentation) { + mInlinePresentation = inlinePresentation; } /** @@ -325,7 +377,7 @@ public final class Dataset implements Parcelable { */ public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) { throwIfDestroyed(); - setLifeTheUniverseAndEverything(id, value, null, null); + setLifeTheUniverseAndEverything(id, value, null, null, null); return this; } @@ -353,7 +405,7 @@ public final class Dataset implements Parcelable { @NonNull RemoteViews presentation) { throwIfDestroyed(); Preconditions.checkNotNull(presentation, "presentation cannot be null"); - setLifeTheUniverseAndEverything(id, value, presentation, null); + setLifeTheUniverseAndEverything(id, value, presentation, null, null); return this; } @@ -389,7 +441,7 @@ public final class Dataset implements Parcelable { throwIfDestroyed(); Preconditions.checkState(mPresentation != null, "Dataset presentation not set on constructor"); - setLifeTheUniverseAndEverything(id, value, null, new DatasetFieldFilter(filter)); + setLifeTheUniverseAndEverything(id, value, null, null, new DatasetFieldFilter(filter)); return this; } @@ -424,13 +476,119 @@ public final class Dataset implements Parcelable { @Nullable Pattern filter, @NonNull RemoteViews presentation) { throwIfDestroyed(); Preconditions.checkNotNull(presentation, "presentation cannot be null"); - setLifeTheUniverseAndEverything(id, value, presentation, + setLifeTheUniverseAndEverything(id, value, presentation, null, + new DatasetFieldFilter(filter)); + return this; + } + + /** + * Sets the value of a field, using a custom {@link RemoteViews presentation} to + * visualize it and an {@link InlinePresentation} to visualize it as an inline suggestion. + * + * <p><b>Note:</b> If the dataset requires authentication but the service knows its text + * value it's easier to filter by calling + * {@link #setValue(AutofillId, AutofillValue, RemoteViews)} and using the value to filter. + * + * @param id id returned by {@link + * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. + * @param value the value to be autofilled. Pass {@code null} if you do not have the value + * but the target view is a logical part of the dataset. For example, if + * the dataset needs authentication and you have no access to the value. + * @param presentation the presentation used to visualize this field. + * @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset + * as inline suggestions. If the dataset supports inline suggestions, + * this should not be null. + * + * @return this builder. + */ + public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, + @NonNull RemoteViews presentation, @NonNull InlinePresentation inlinePresentation) { + throwIfDestroyed(); + Preconditions.checkNotNull(presentation, "presentation cannot be null"); + Preconditions.checkNotNull(inlinePresentation, "inlinePresentation cannot be null"); + setLifeTheUniverseAndEverything(id, value, presentation, inlinePresentation, null); + return this; + } + + /** + * Sets the value of a field, using a custom {@link RemoteViews presentation} to + * visualize it and a <a href="#Filtering">explicit filter</a>, and an + * {@link InlinePresentation} to visualize it as an inline suggestion. + * + * <p>This method is typically used when the dataset requires authentication and the service + * does not know its value but wants to hide the dataset after the user enters a minimum + * number of characters. For example, if the dataset represents a credit card number and the + * service does not want to show the "Tap to authenticate" message until the user tapped + * 4 digits, in which case the filter would be {@code Pattern.compile("\\d.{4,}")}. + * + * <p><b>Note:</b> If the dataset requires authentication but the service knows its text + * value it's easier to filter by calling + * {@link #setValue(AutofillId, AutofillValue, RemoteViews)} and using the value to filter. + * + * @param id id returned by {@link + * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. + * @param value the value to be autofilled. Pass {@code null} if you do not have the value + * but the target view is a logical part of the dataset. For example, if + * the dataset needs authentication and you have no access to the value. + * @param filter regex used to determine if the dataset should be shown in the autofill UI; + * when {@code null}, it disables filtering on that dataset (this is the recommended + * approach when {@code value} is not {@code null} and field contains sensitive data + * such as passwords). + * @param presentation the presentation used to visualize this field. + * @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset + * as inline suggestions. If the dataset supports inline suggestions, this + * should not be null. + * + * @return this builder. + */ + public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, + @Nullable Pattern filter, @NonNull RemoteViews presentation, + @NonNull InlinePresentation inlinePresentation) { + throwIfDestroyed(); + Preconditions.checkNotNull(presentation, "presentation cannot be null"); + Preconditions.checkNotNull(inlinePresentation, "inlinePresentation cannot be null"); + setLifeTheUniverseAndEverything(id, value, presentation, inlinePresentation, + new DatasetFieldFilter(filter)); + return this; + } + + /** + * Sets the value of a field with an <a href="#Filtering">explicit filter</a>, and using an + * {@link InlinePresentation} to visualize it as an inline suggestion. + * + * <p>Only called by augmented autofill. + * + * @param id id returned by {@link + * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. + * @param value the value to be autofilled. Pass {@code null} if you do not have the value + * but the target view is a logical part of the dataset. For example, if + * the dataset needs authentication and you have no access to the value. + * @param filter regex used to determine if the dataset should be shown in the autofill UI; + * when {@code null}, it disables filtering on that dataset (this is the recommended + * approach when {@code value} is not {@code null} and field contains sensitive data + * such as passwords). + * @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset + * as inline suggestions. If the dataset supports inline suggestions, this + * should not be null. + * + * @return this builder. + * + * @hide + */ + @SystemApi + public @NonNull Builder setInlinePresentation(@NonNull AutofillId id, + @Nullable AutofillValue value, @Nullable Pattern filter, + @NonNull InlinePresentation inlinePresentation) { + throwIfDestroyed(); + Preconditions.checkNotNull(inlinePresentation, "inlinePresentation cannot be null"); + setLifeTheUniverseAndEverything(id, value, null, inlinePresentation, new DatasetFieldFilter(filter)); return this; } private void setLifeTheUniverseAndEverything(@NonNull AutofillId id, @Nullable AutofillValue value, @Nullable RemoteViews presentation, + @Nullable InlinePresentation inlinePresentation, @Nullable DatasetFieldFilter filter) { Preconditions.checkNotNull(id, "id cannot be null"); if (mFieldIds != null) { @@ -438,6 +596,7 @@ public final class Dataset implements Parcelable { if (existingIdx >= 0) { mFieldValues.set(existingIdx, value); mFieldPresentations.set(existingIdx, presentation); + mFieldInlinePresentations.set(existingIdx, inlinePresentation); mFieldFilters.set(existingIdx, filter); return; } @@ -445,11 +604,13 @@ public final class Dataset implements Parcelable { mFieldIds = new ArrayList<>(); mFieldValues = new ArrayList<>(); mFieldPresentations = new ArrayList<>(); + mFieldInlinePresentations = new ArrayList<>(); mFieldFilters = new ArrayList<>(); } mFieldIds.add(id); mFieldValues.add(value); mFieldPresentations.add(presentation); + mFieldInlinePresentations.add(inlinePresentation); mFieldFilters.add(filter); } @@ -460,7 +621,8 @@ public final class Dataset implements Parcelable { * * @throws IllegalStateException if no field was set (through * {@link #setValue(AutofillId, AutofillValue)} or - * {@link #setValue(AutofillId, AutofillValue, RemoteViews)}). + * {@link #setValue(AutofillId, AutofillValue, RemoteViews)} or + * {@link #setValue(AutofillId, AutofillValue, RemoteViews, InlinePresentation)}). * * @return The built dataset. */ @@ -492,38 +654,49 @@ public final class Dataset implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeParcelable(mPresentation, flags); + parcel.writeParcelable(mInlinePresentation, flags); parcel.writeTypedList(mFieldIds, flags); parcel.writeTypedList(mFieldValues, flags); parcel.writeTypedList(mFieldPresentations, flags); + parcel.writeTypedList(mFieldInlinePresentations, flags); parcel.writeTypedList(mFieldFilters, flags); parcel.writeParcelable(mAuthentication, flags); parcel.writeString(mId); } - public static final @android.annotation.NonNull Creator<Dataset> CREATOR = new Creator<Dataset>() { + public static final @NonNull Creator<Dataset> CREATOR = new Creator<Dataset>() { @Override public Dataset createFromParcel(Parcel parcel) { // Always go through the builder to ensure the data ingested by // the system obeys the contract of the builder to avoid attacks // using specially crafted parcels. final RemoteViews presentation = parcel.readParcelable(null); - final Builder builder = (presentation == null) - ? new Builder() - : new Builder(presentation); + final InlinePresentation inlinePresentation = parcel.readParcelable(null); + final Builder builder = presentation == null + ? new Builder(inlinePresentation) + : inlinePresentation == null + ? new Builder(presentation) + : new Builder(presentation, inlinePresentation); final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR); final ArrayList<AutofillValue> values = parcel.createTypedArrayList(AutofillValue.CREATOR); final ArrayList<RemoteViews> presentations = parcel.createTypedArrayList(RemoteViews.CREATOR); + final ArrayList<InlinePresentation> inlinePresentations = + parcel.createTypedArrayList(InlinePresentation.CREATOR); final ArrayList<DatasetFieldFilter> filters = parcel.createTypedArrayList(DatasetFieldFilter.CREATOR); + final int inlinePresentationsSize = inlinePresentations.size(); for (int i = 0; i < ids.size(); i++) { final AutofillId id = ids.get(i); final AutofillValue value = values.get(i); final RemoteViews fieldPresentation = presentations.get(i); + final InlinePresentation fieldInlinePresentation = + i < inlinePresentationsSize ? inlinePresentations.get(i) : null; final DatasetFieldFilter filter = filters.get(i); - builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, filter); + builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, + fieldInlinePresentation, filter); } builder.setAuthentication(parcel.readParcelable(null)); builder.setId(parcel.readString()); diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 02a6390a08bb..d51e4ca6398f 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -25,7 +25,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.Activity; -import android.app.slice.Slice; import android.content.IntentSender; import android.content.pm.ParceledListSlice; import android.os.Bundle; @@ -87,7 +86,7 @@ public final class FillResponse implements Parcelable { private int mRequestId; private final @Nullable UserData mUserData; private final @Nullable int[] mCancelIds; - private final @Nullable ParceledListSlice<Slice> mInlineSuggestionSlices; + private final boolean mSupportsInlineSuggestions; private FillResponse(@NonNull Builder builder) { mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null; @@ -105,8 +104,7 @@ public final class FillResponse implements Parcelable { mRequestId = INVALID_REQUEST_ID; mUserData = builder.mUserData; mCancelIds = builder.mCancelIds; - mInlineSuggestionSlices = (builder.mInlineSuggestionSlices != null) - ? new ParceledListSlice<>(builder.mInlineSuggestionSlices) : null; + mSupportsInlineSuggestions = builder.mSupportsInlineSuggestions; } /** @hide */ @@ -200,8 +198,8 @@ public final class FillResponse implements Parcelable { } /** @hide */ - public List<Slice> getInlineSuggestionSlices() { - return (mInlineSuggestionSlices != null) ? mInlineSuggestionSlices.getList() : null; + public boolean supportsInlineSuggestions() { + return mSupportsInlineSuggestions; } /** @@ -224,7 +222,7 @@ public final class FillResponse implements Parcelable { private boolean mDestroyed; private UserData mUserData; private int[] mCancelIds; - private ArrayList<Slice> mInlineSuggestionSlices; + private boolean mSupportsInlineSuggestions; /** * Triggers a custom UI before before autofilling the screen with any data set in this @@ -580,20 +578,6 @@ public final class FillResponse implements Parcelable { } /** - * TODO(b/137800469): add javadoc - */ - @NonNull - public Builder addInlineSuggestionSlice(@NonNull Slice inlineSuggestionSlice) { - throwIfDestroyed(); - throwIfAuthenticationCalled(); - if (mInlineSuggestionSlices == null) { - mInlineSuggestionSlices = new ArrayList<>(); - } - mInlineSuggestionSlices.add(inlineSuggestionSlice); - return this; - } - - /** * Builds a new {@link FillResponse} instance. * * @throws IllegalStateException if any of the following conditions occur: @@ -624,6 +608,14 @@ public final class FillResponse implements Parcelable { throw new IllegalStateException( "must add at least 1 dataset when using header or footer"); } + + for (final Dataset dataset : mDatasets) { + if (dataset.getFieldInlinePresentation(0) != null) { + mSupportsInlineSuggestions = true; + break; + } + } + mDestroyed = true; return new FillResponse(this); } @@ -694,9 +686,6 @@ public final class FillResponse implements Parcelable { if (mCancelIds != null) { builder.append(", mCancelIds=").append(mCancelIds.length); } - if (mInlineSuggestionSlices != null) { - builder.append(", inlinedSuggestions=").append(mInlineSuggestionSlices.getList()); - } return builder.append("]").toString(); } @@ -725,7 +714,6 @@ public final class FillResponse implements Parcelable { parcel.writeParcelableArray(mFieldClassificationIds, flags); parcel.writeInt(mFlags); parcel.writeIntArray(mCancelIds); - parcel.writeParcelable(mInlineSuggestionSlices, flags); parcel.writeInt(mRequestId); } @@ -781,16 +769,6 @@ public final class FillResponse implements Parcelable { final int[] cancelIds = parcel.createIntArray(); builder.setCancelTargetIds(cancelIds); - final ParceledListSlice<Slice> parceledInlineSuggestionSlices = - parcel.readParcelable(null); - if (parceledInlineSuggestionSlices != null) { - final List<Slice> inlineSuggestionSlices = parceledInlineSuggestionSlices.getList(); - final int size = inlineSuggestionSlices.size(); - for (int i = 0; i < size; i++) { - builder.addInlineSuggestionSlice(inlineSuggestionSlices.get(i)); - } - } - final FillResponse response = builder.build(); response.setRequestId(parcel.readInt()); diff --git a/core/java/android/service/autofill/InlinePresentation.aidl b/core/java/android/service/autofill/InlinePresentation.aidl new file mode 100644 index 000000000000..eeddcc0d8c02 --- /dev/null +++ b/core/java/android/service/autofill/InlinePresentation.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +parcelable InlinePresentation; diff --git a/core/java/android/service/autofill/InlinePresentation.java b/core/java/android/service/autofill/InlinePresentation.java new file mode 100644 index 000000000000..1568fb3af4c0 --- /dev/null +++ b/core/java/android/service/autofill/InlinePresentation.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +import android.annotation.NonNull; +import android.app.slice.Slice; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.inline.InlinePresentationSpec; + +import com.android.internal.util.DataClass; + +/** + * Wrapper class holding a {@link Slice} and an {@link InlinePresentationSpec} for rendering UI + * for an Inline Suggestion. + */ +@DataClass( + genToString = true, + genHiddenConstDefs = true, + genEqualsHashCode = true) +public final class InlinePresentation implements Parcelable { + + private final @NonNull Slice mSlice; + + private final @NonNull InlinePresentationSpec mInlinePresentationSpec; + + + + // Code below generated by codegen v1.0.14. + // + // DO NOT MODIFY! + // CHECKSTYLE:OFF Generated code + // + // To regenerate run: + // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/InlinePresentation.java + // + // To exclude the generated code from IntelliJ auto-formatting enable (one-time): + // Settings > Editor > Code Style > Formatter Control + //@formatter:off + + + @DataClass.Generated.Member + public InlinePresentation( + @NonNull Slice slice, + @NonNull InlinePresentationSpec inlinePresentationSpec) { + this.mSlice = slice; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mSlice); + this.mInlinePresentationSpec = inlinePresentationSpec; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mInlinePresentationSpec); + + // onConstructed(); // You can define this method to get a callback + } + + @DataClass.Generated.Member + public @NonNull Slice getSlice() { + return mSlice; + } + + @DataClass.Generated.Member + public @NonNull InlinePresentationSpec getInlinePresentationSpec() { + return mInlinePresentationSpec; + } + + @Override + @DataClass.Generated.Member + public String toString() { + // You can override field toString logic by defining methods like: + // String fieldNameToString() { ... } + + return "InlinePresentation { " + + "slice = " + mSlice + ", " + + "inlinePresentationSpec = " + mInlinePresentationSpec + + " }"; + } + + @Override + @DataClass.Generated.Member + public boolean equals(@android.annotation.Nullable Object o) { + // You can override field equality logic by defining either of the methods like: + // boolean fieldNameEquals(InlinePresentation other) { ... } + // boolean fieldNameEquals(FieldType otherValue) { ... } + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + @SuppressWarnings("unchecked") + InlinePresentation that = (InlinePresentation) o; + //noinspection PointlessBooleanExpression + return true + && java.util.Objects.equals(mSlice, that.mSlice) + && java.util.Objects.equals(mInlinePresentationSpec, that.mInlinePresentationSpec); + } + + @Override + @DataClass.Generated.Member + public int hashCode() { + // You can override field hashCode logic by defining methods like: + // int fieldNameHashCode() { ... } + + int _hash = 1; + _hash = 31 * _hash + java.util.Objects.hashCode(mSlice); + _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentationSpec); + return _hash; + } + + @Override + @DataClass.Generated.Member + public void writeToParcel(@NonNull Parcel dest, int flags) { + // You can override field parcelling by defining methods like: + // void parcelFieldName(Parcel dest, int flags) { ... } + + dest.writeTypedObject(mSlice, flags); + dest.writeTypedObject(mInlinePresentationSpec, flags); + } + + @Override + @DataClass.Generated.Member + public int describeContents() { return 0; } + + /** @hide */ + @SuppressWarnings({"unchecked", "RedundantCast"}) + @DataClass.Generated.Member + /* package-private */ InlinePresentation(@NonNull Parcel in) { + // You can override field unparcelling by defining methods like: + // static FieldType unparcelFieldName(Parcel in) { ... } + + Slice slice = (Slice) in.readTypedObject(Slice.CREATOR); + InlinePresentationSpec inlinePresentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR); + + this.mSlice = slice; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mSlice); + this.mInlinePresentationSpec = inlinePresentationSpec; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mInlinePresentationSpec); + + // onConstructed(); // You can define this method to get a callback + } + + @DataClass.Generated.Member + public static final @NonNull Parcelable.Creator<InlinePresentation> CREATOR + = new Parcelable.Creator<InlinePresentation>() { + @Override + public InlinePresentation[] newArray(int size) { + return new InlinePresentation[size]; + } + + @Override + public InlinePresentation createFromParcel(@NonNull Parcel in) { + return new InlinePresentation(in); + } + }; + + @DataClass.Generated( + time = 1578081082387L, + codegenVersion = "1.0.14", + sourceFile = "frameworks/base/core/java/android/service/autofill/InlinePresentation.java", + inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mInlinePresentationSpec\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)") + @Deprecated + private void __metadata() {} + + + //@formatter:on + // End of generated code + +} diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 4314eb6efb18..566c3850bf14 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -237,7 +237,7 @@ static int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_me return err; } -static void load_maps(int pid, stats_t* stats, bool* foundSwapPss) +static bool load_maps(int pid, stats_t* stats, bool* foundSwapPss) { *foundSwapPss = false; uint64_t prev_end = 0; @@ -407,17 +407,19 @@ static void load_maps(int pid, stats_t* stats, bool* foundSwapPss) } }; - meminfo::ForEachVmaFromFile(smaps_path, vma_scan); + return meminfo::ForEachVmaFromFile(smaps_path, vma_scan); } -static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, +static jboolean android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, jint pid, jobject object) { bool foundSwapPss; stats_t stats[_NUM_HEAP]; memset(&stats, 0, sizeof(stats)); - load_maps(pid, stats, &foundSwapPss); + if (!load_maps(pid, stats, &foundSwapPss)) { + return JNI_FALSE; + } struct graphics_memory_pss graphics_mem; if (read_memtrack_memory(pid, &graphics_mem) == 0) { @@ -462,7 +464,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0); if (otherArray == NULL) { - return; + return JNI_FALSE; } int j=0; @@ -479,6 +481,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, } env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0); + return JNI_TRUE; } static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object) @@ -508,6 +511,8 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, rss += stats.rss; swapPss = stats.swap_pss; pss += swapPss; // Also in swap, those pages would be accounted as Pss without SWAP + } else { + return 0; } if (outUssSwapPssRss != NULL) { @@ -866,7 +871,7 @@ static const JNINativeMethod gMethods[] = { (void*) android_os_Debug_getNativeHeapFreeSize }, { "getMemoryInfo", "(Landroid/os/Debug$MemoryInfo;)V", (void*) android_os_Debug_getDirtyPages }, - { "getMemoryInfo", "(ILandroid/os/Debug$MemoryInfo;)V", + { "getMemoryInfo", "(ILandroid/os/Debug$MemoryInfo;)Z", (void*) android_os_Debug_getDirtyPagesPid }, { "getPss", "()J", (void*) android_os_Debug_getPss }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1c48a74b8dc7..697066ff1e4b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2549,17 +2549,17 @@ <permission android:name="android.permission.READ_WALLPAPER_INTERNAL" android:protectionLevel="signature|privileged" /> - <!-- ============================================ --> - <!-- Permissions for changing the system clock --> - <!-- ============================================ --> + <!-- ===================================================== --> + <!-- Permissions for changing the system clock / time zone --> + <!-- ===================================================== --> <eat-comment /> - <!-- Allows applications to set the system time. - <p>Not for use by third-party applications. --> + <!-- Allows applications to set the system time directly. + <p>Not for use by third-party applications. --> <permission android:name="android.permission.SET_TIME" android:protectionLevel="signature|privileged" /> - <!-- Allows applications to set the system time zone. + <!-- Allows applications to set the system time zone directly. <p>Not for use by third-party applications. --> <permission android:name="android.permission.SET_TIME_ZONE" @@ -2567,6 +2567,20 @@ android:description="@string/permdesc_setTimeZone" android:protectionLevel="signature|privileged" /> + <!-- Allows telephony to suggest the time / time zone. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE" + android:protectionLevel="signature|telephony" /> + + <!-- Allows applications like settings to suggest the user's manually chosen time / time zone. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE" + android:protectionLevel="signature" /> + <!-- ==================================================== --> <!-- Permissions related to changing status bar --> <!-- ==================================================== --> diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml index ee989cca1787..70b61e0e2552 100644 --- a/data/etc/com.android.settings.xml +++ b/data/etc/com.android.settings.xml @@ -42,8 +42,8 @@ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <permission name="android.permission.READ_SEARCH_INDEXABLES"/> <permission name="android.permission.REBOOT"/> - <permission name="android.permission.SET_TIME"/> <permission name="android.permission.STATUS_BAR"/> + <permission name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"/> <permission name="android.permission.TETHER_PRIVILEGED"/> <permission name="android.permission.USE_RESERVED_DISK"/> <permission name="android.permission.USER_ACTIVITY"/> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 38a9f4653c40..eb1d1ab1089c 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -160,12 +160,12 @@ applications that come with the platform <permission name="android.permission.REGISTER_CALL_PROVIDER"/> <permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/> <permission name="android.permission.SEND_RESPOND_VIA_MESSAGE"/> - <permission name="android.permission.SET_TIME"/> <permission name="android.permission.SET_TIME_ZONE"/> <permission name="android.permission.SHUTDOWN"/> <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> <permission name="android.permission.STATUS_BAR"/> <permission name="android.permission.STOP_APP_SWITCHES"/> + <permission name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"/> <permission name="android.permission.UPDATE_APP_OPS_STATS"/> <permission name="android.permission.UPDATE_DEVICE_STATS"/> <permission name="android.permission.UPDATE_LOCK"/> diff --git a/media/java/android/media/tv/DvbDeviceInfo.java b/media/java/android/media/tv/DvbDeviceInfo.java index a574fe18fb63..96c852812a74 100644 --- a/media/java/android/media/tv/DvbDeviceInfo.java +++ b/media/java/android/media/tv/DvbDeviceInfo.java @@ -16,6 +16,8 @@ package android.media.tv; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -26,10 +28,11 @@ import android.util.Log; * * @hide */ +@SystemApi public final class DvbDeviceInfo implements Parcelable { static final String TAG = "DvbDeviceInfo"; - public static final @android.annotation.NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR = + public static final @NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR = new Parcelable.Creator<DvbDeviceInfo>() { @Override public DvbDeviceInfo createFromParcel(Parcel source) { @@ -86,7 +89,7 @@ public final class DvbDeviceInfo implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mAdapterId); dest.writeInt(mDeviceId); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index d22a29893540..854ea43f17c3 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -103,6 +103,12 @@ public final class TvInputManager { /** @hide */ @Retention(RetentionPolicy.SOURCE) + @IntDef({DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_FRONTEND}) + public @interface DvbDeviceType {} + + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) @IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING, VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING, VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY}) @@ -1663,6 +1669,9 @@ public final class TvInputManager { * @return the list of {@link DvbDeviceInfo} objects representing available DVB devices. * @hide */ + @SystemApi + @RequiresPermission(android.Manifest.permission.DVB_DEVICE) + @NonNull public List<DvbDeviceInfo> getDvbDeviceList() { try { return mService.getDvbDeviceList(); @@ -1676,19 +1685,24 @@ public final class TvInputManager { * {@link DvbDeviceInfo} * * @param info A {@link DvbDeviceInfo} to open a DVB device. - * @param device A DVB device. The DVB device can be {@link #DVB_DEVICE_DEMUX}, + * @param deviceType A DVB device type. The type can be {@link #DVB_DEVICE_DEMUX}, * {@link #DVB_DEVICE_DVR} or {@link #DVB_DEVICE_FRONTEND}. * @return a {@link ParcelFileDescriptor} of a specified DVB device for a given - * {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo} was invalid - * or the specified DVB device was busy with a previous request. + * {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo} + * failed to open. + * @throws IllegalArgumentException if {@code deviceType} is invalid or the device is not found. * @hide */ - public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) { + @SystemApi + @RequiresPermission(android.Manifest.permission.DVB_DEVICE) + @Nullable + public ParcelFileDescriptor openDvbDevice(@NonNull DvbDeviceInfo info, + @DvbDeviceType int deviceType) { try { - if (DVB_DEVICE_START > device || DVB_DEVICE_END < device) { - throw new IllegalArgumentException("Invalid DVB device: " + device); + if (DVB_DEVICE_START > deviceType || DVB_DEVICE_END < deviceType) { + throw new IllegalArgumentException("Invalid DVB device: " + deviceType); } - return mService.openDvbDevice(info, device); + return mService.openDvbDevice(info, deviceType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index b8ab7eea248e..fcb03c0305a8 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -110,6 +110,10 @@ public final class Tuner implements AutoCloseable { private native int nativeSetLnb(int lnbId); private native int nativeSetLna(boolean enable); private native FrontendStatus[] nativeGetFrontendStatus(int[] statusTypes); + private native int nativeGetAvSyncHwId(Filter filter); + private native long nativeGetAvSyncTime(int avSyncId); + private native int nativeConnectCiCam(int ciCamId); + private native int nativeDisconnectCiCam(); private native Filter nativeOpenFilter(int type, int subType, int bufferSize); private native List<Integer> nativeGetLnbIds(); @@ -351,6 +355,59 @@ public final class Tuner implements AutoCloseable { return nativeGetFrontendStatus(statusTypes); } + /** + * Gets hardware sync ID for audio and video. + * + * @param filter the filter instance for the hardware sync ID. + * @return the id of hardware A/V sync. + * @hide + */ + public int getAvSyncHwId(Filter filter) { + return nativeGetAvSyncHwId(filter); + } + /** + * Gets the current timestamp for A/V sync + * + * The timestamp is maintained by hardware. The timestamp based on 90KHz, and it's format is the + * same as PTS (Presentation Time Stamp). + * + * @param avSyncHwId the hardware id of A/V sync. + * @return the current timestamp of hardware A/V sync. + * @hide + */ + public long getAvSyncTime(int avSyncHwId) { + return nativeGetAvSyncTime(avSyncHwId); + } + + + /** + * Connects Conditional Access Modules (CAM) through Common Interface (CI) + * + * The demux uses the output from the frontend as the input by default, and must change to use + * the output from CI-CAM as the input after this call. + * + * @param ciCamId specify CI-CAM Id to connect. + * @return result status of the operation. + * @hide + */ + @Result + public int connectCiCam(int ciCamId) { + return nativeConnectCiCam(ciCamId); + } + + /** + * Disconnects Conditional Access Modules (CAM) + * + * The demux will use the output from the frontend as the input after this call. + * + * @return result status of the operation. + * @hide + */ + @Result + public int disconnectCiCam() { + return nativeDisconnectCiCam(); + } + private List<Integer> getFrontendIds() { mFrontendIds = nativeGetFrontendIds(); return mFrontendIds; diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index da52696506b5..9d2e85539da8 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -636,6 +636,22 @@ static jobjectArray android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, return NULL; } +static int android_media_tv_Tuner_gat_av_sync_hw_id(JNIEnv*, jobject, jobject) { + return 0; +} + +static jlong android_media_tv_Tuner_gat_av_sync_time(JNIEnv*, jobject, jint) { + return 0; +} + +static int android_media_tv_Tuner_connect_cicam(JNIEnv*, jobject, jint) { + return 0; +} + +static int android_media_tv_Tuner_disconnect_cicam(JNIEnv*, jobject) { + return 0; +} + static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) { sp<JTuner> tuner = getTuner(env, thiz); return tuner->getLnbIds(); @@ -944,6 +960,11 @@ static const JNINativeMethod gTunerMethods[] = { { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna }, { "nativeGetFrontendStatus", "([I)[Landroid/media/tv/tuner/FrontendStatus;", (void *)android_media_tv_Tuner_get_frontend_status }, + { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner$Filter;)I", + (void *)android_media_tv_Tuner_gat_av_sync_hw_id }, + { "nativeGetAvSyncTime", "(I)J", (void *)android_media_tv_Tuner_gat_av_sync_time }, + { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam }, + { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam }, { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;", (void *)android_media_tv_Tuner_open_filter }, { "nativeGetLnbIds", "()Ljava/util/List;", diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index 09ebb6468a11..ce1123ee67e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -70,7 +70,6 @@ public final class DozeServiceHost implements DozeHost { boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean( "persist.sysui.wake_performs_auth", true); private boolean mDozingRequested; - private boolean mDozing; private boolean mPulsing; private WakefulnessLifecycle mWakefulnessLifecycle; private final SysuiStatusBarStateController mStatusBarStateController; @@ -196,8 +195,8 @@ public final class DozeServiceHost implements DozeHost { public void startDozing() { if (!mDozingRequested) { mDozingRequested = true; - mDozeLog.traceDozing(mDozing); updateDozing(); + mDozeLog.traceDozing(mStatusBarStateController.isDozing()); mStatusBar.updateIsKeyguard(); } } @@ -281,8 +280,8 @@ public final class DozeServiceHost implements DozeHost { public void stopDozing() { if (mDozingRequested) { mDozingRequested = false; - mDozeLog.traceDozing(mDozing); updateDozing(); + mDozeLog.traceDozing(mStatusBarStateController.isDozing()); } } @@ -292,7 +291,7 @@ public final class DozeServiceHost implements DozeHost { mDozeLog.tracePulseTouchDisabledByProx(ignore); } mIgnoreTouchWhilePulsing = ignore; - if (mDozing && ignore) { + if (mStatusBarStateController.isDozing() && ignore) { mStatusBarWindowViewController.cancelCurrentTouch(); } } @@ -448,10 +447,6 @@ public final class DozeServiceHost implements DozeHost { return mAnimateScreenOff; } - public void setDozing(boolean dozing) { - mDozing = dozing; - } - boolean getIgnoreTouchWhilePulsing() { return mIgnoreTouchWhilePulsing; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index a6a734a542f0..862c9cbc1fe7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3491,7 +3491,6 @@ public class StatusBar extends SystemUI implements DemoMode, public void onDozingChanged(boolean isDozing) { Trace.beginSection("StatusBar#updateDozing"); mDozing = isDozing; - mDozeServiceHost.setDozing(mDozing); // Collapse the notification panel if open boolean dozingAnimated = mDozeServiceHost.getDozingRequested() diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 3b513298f638..95cd8fc47944 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -42,8 +42,6 @@ import android.app.IAssistDataReceiver; import android.app.assist.AssistStructure; import android.app.assist.AssistStructure.AutofillOverlay; import android.app.assist.AssistStructure.ViewNode; -import android.app.slice.Slice; -import android.app.slice.SliceItem; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -72,6 +70,7 @@ import android.service.autofill.FieldClassificationUserData; import android.service.autofill.FillContext; import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; +import android.service.autofill.InlinePresentation; import android.service.autofill.InternalSanitizer; import android.service.autofill.InternalValidator; import android.service.autofill.SaveInfo; @@ -83,7 +82,6 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; import android.util.Log; -import android.util.Size; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; @@ -2637,9 +2635,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - final List<Slice> inlineSuggestionSlices = response.getInlineSuggestionSlices(); - if (inlineSuggestionSlices != null) { - if (requestShowInlineSuggestions(inlineSuggestionSlices, response)) { + if (response.supportsInlineSuggestions()) { + if (requestShowInlineSuggestions(response)) { //TODO(b/137800469): Add logging instead of bypassing below logic. return; } @@ -2680,10 +2677,22 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * Returns whether we made a request to show inline suggestions. */ - private boolean requestShowInlineSuggestions(List<Slice> inlineSuggestionSlices, - FillResponse response) { - final IInlineSuggestionsResponseCallback inlineContentCallback = - getInlineSuggestionsResponseCallback(); + private boolean requestShowInlineSuggestions(FillResponse response) { + IInlineSuggestionsResponseCallback inlineContentCallback = null; + synchronized (mLock) { + if (mInlineSuggestionsResponseCallbackFuture != null) { + try { + inlineContentCallback = mInlineSuggestionsResponseCallbackFuture.get( + INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + Log.w(TAG, "Exception getting inline suggestions callback in time: " + e); + } catch (CancellationException e) { + Log.w(TAG, "Inline suggestions callback cancelled"); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + } if (inlineContentCallback == null) { Log.w(TAG, "Session input method callback is not set yet"); @@ -2696,54 +2705,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return false; } + final int size = datasets.size(); final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>(); - final int slicesSize = inlineSuggestionSlices.size(); - if (datasets.size() < slicesSize) { - Log.w(TAG, "Too many slices provided, not enough corresponding datasets"); - return false; - } - - for (int sliceIndex = 0; sliceIndex < slicesSize; sliceIndex++) { - Log.i(TAG, "Reading slice-" + sliceIndex + " at requestshowinlinesuggestions"); - final Slice inlineSuggestionSlice = inlineSuggestionSlices.get(sliceIndex); - final List<SliceItem> sliceItems = inlineSuggestionSlice.getItems(); - - final int itemsSize = sliceItems.size(); - int minWidth = -1; - int maxWidth = -1; - int minHeight = -1; - int maxHeight = -1; - for (int itemIndex = 0; itemIndex < itemsSize; itemIndex++) { - final SliceItem item = sliceItems.get(itemIndex); - final String subtype = item.getSubType(); - switch (item.getSubType()) { - case "SUBTYPE_MIN_WIDTH": - minWidth = item.getInt(); - break; - case "SUBTYPE_MAX_WIDTH": - maxWidth = item.getInt(); - break; - case "SUBTYPE_MIN_HEIGHT": - minHeight = item.getInt(); - break; - case "SUBTYPE_MAX_HEIGHT": - maxHeight = item.getInt(); - break; - default: - Log.i(TAG, "unrecognized inline suggestions subtype: " + subtype); - } - } - if (minWidth < 0 || maxWidth < 0 || minHeight < 0 || maxHeight < 0) { - Log.w(TAG, "missing inline suggestion requirements"); - return false; + for (int index = 0; index < size; index++) { + final Dataset dataset = datasets.get(index); + //TODO(b/146453536): Use the proper presentation/spec for currently focused view. + final InlinePresentation inlinePresentation = dataset.getFieldInlinePresentation(0); + if (inlinePresentation == null) { + if (sDebug) Log.d(TAG, "Missing InlinePresentation on dataset=" + dataset); + continue; } - - final InlinePresentationSpec spec = new InlinePresentationSpec.Builder( - new Size(minWidth, minHeight), new Size(maxWidth, maxHeight)).build(); + final InlinePresentationSpec spec = inlinePresentation.getInlinePresentationSpec(); final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo( spec, InlineSuggestionInfo.SOURCE_AUTOFILL, new String[] { "" }); - final Dataset dataset = datasets.get(sliceIndex); inlineSuggestions.add(new InlineSuggestion(inlineSuggestionInfo, new IInlineContentProvider.Stub() { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dd1f3704e46f..4e9bc8f16815 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -12594,7 +12594,7 @@ public class ActivityManagerService extends IActivityManager.Stub ArrayList<ProcessRecord> procs, PrintWriter categoryPw) { long uptime = SystemClock.uptimeMillis(); long realtime = SystemClock.elapsedRealtime(); - final long[] tmpLong = new long[1]; + final long[] tmpLong = new long[3]; if (procs == null) { // No Java processes. Maybe they want to print a native process. @@ -12627,17 +12627,25 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) { final ProcessCpuTracker.Stats r = nativeProcs.get(i); final int pid = r.pid; - if (!opts.isCheckinRequest && opts.dumpDetails) { - pw.println("\n** MEMINFO in pid " + pid + " [" + r.baseName + "] **"); - } if (mi == null) { mi = new Debug.MemoryInfo(); } if (opts.dumpDetails || (!brief && !opts.oomOnly)) { - Debug.getMemoryInfo(pid, mi); + if (!Debug.getMemoryInfo(pid, mi)) { + continue; + } } else { - mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null); - mi.dalvikPrivateDirty = (int)tmpLong[0]; + long pss = Debug.getPss(pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.nativePss = (int) pss; + mi.nativePrivateDirty = (int) tmpLong[0]; + mi.nativeRss = (int) tmpLong[2]; + } + if (!opts.isCheckinRequest && opts.dumpDetails) { + pw.println("\n** MEMINFO in pid " + pid + " [" + + r.baseName + "] **"); } ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest, opts.dumpFullDetails, opts.dumpDalvik, opts.dumpSummaryOnly, @@ -12715,9 +12723,6 @@ public class ActivityManagerService extends IActivityManager.Stub hasActivities = r.hasActivities(); } if (thread != null) { - if (!opts.isCheckinRequest && opts.dumpDetails) { - pw.println("\n** MEMINFO in pid " + pid + " [" + r.processName + "] **"); - } if (mi == null) { mi = new Debug.MemoryInfo(); } @@ -12727,17 +12732,26 @@ public class ActivityManagerService extends IActivityManager.Stub if (opts.dumpDetails || (!brief && !opts.oomOnly)) { reportType = ProcessStats.ADD_PSS_EXTERNAL_SLOW; startTime = SystemClock.currentThreadTimeMillis(); - Debug.getMemoryInfo(pid, mi); + if (!Debug.getMemoryInfo(pid, mi)) { + continue; + } endTime = SystemClock.currentThreadTimeMillis(); hasSwapPss = mi.hasSwappedOutPss; } else { reportType = ProcessStats.ADD_PSS_EXTERNAL; startTime = SystemClock.currentThreadTimeMillis(); - mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null); + long pss = Debug.getPss(pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.dalvikPss = (int) pss; endTime = SystemClock.currentThreadTimeMillis(); - mi.dalvikPrivateDirty = (int)tmpLong[0]; + mi.dalvikPrivateDirty = (int) tmpLong[0]; mi.dalvikRss = (int) tmpLong[2]; } + if (!opts.isCheckinRequest && opts.dumpDetails) { + pw.println("\n** MEMINFO in pid " + pid + " [" + r.processName + "] **"); + } if (opts.dumpDetails) { if (opts.localOnly) { ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest, opts.dumpFullDetails, @@ -12867,10 +12881,17 @@ public class ActivityManagerService extends IActivityManager.Stub mi = new Debug.MemoryInfo(); } if (!brief && !opts.oomOnly) { - Debug.getMemoryInfo(st.pid, mi); + if (!Debug.getMemoryInfo(st.pid, mi)) { + continue; + } } else { - mi.nativePss = (int)Debug.getPss(st.pid, tmpLong, null); - mi.nativePrivateDirty = (int)tmpLong[0]; + long pss = Debug.getPss(st.pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.nativePss = (int) pss; + mi.nativePrivateDirty = (int) tmpLong[0]; + mi.nativeRss = (int) tmpLong[2]; } final long myTotalPss = mi.getTotalPss(); @@ -13174,7 +13195,7 @@ public class ActivityManagerService extends IActivityManager.Stub ArrayList<ProcessRecord> procs) { final long uptimeMs = SystemClock.uptimeMillis(); final long realtimeMs = SystemClock.elapsedRealtime(); - final long[] tmpLong = new long[1]; + final long[] tmpLong = new long[3]; if (procs == null) { // No Java processes. Maybe they want to print a native process. @@ -13209,20 +13230,29 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) { final ProcessCpuTracker.Stats r = nativeProcs.get(i); final int pid = r.pid; - final long nToken = proto.start(MemInfoDumpProto.NATIVE_PROCESSES); - - proto.write(MemInfoDumpProto.ProcessMemory.PID, pid); - proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME, r.baseName); if (mi == null) { mi = new Debug.MemoryInfo(); } if (opts.dumpDetails || (!brief && !opts.oomOnly)) { - Debug.getMemoryInfo(pid, mi); + if (!Debug.getMemoryInfo(pid, mi)) { + continue; + } } else { - mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null); - mi.dalvikPrivateDirty = (int)tmpLong[0]; + long pss = Debug.getPss(pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.nativePss = (int) pss; + mi.nativePrivateDirty = (int) tmpLong[0]; + mi.nativeRss = (int) tmpLong[2]; } + + final long nToken = proto.start(MemInfoDumpProto.NATIVE_PROCESSES); + + proto.write(MemInfoDumpProto.ProcessMemory.PID, pid); + proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME, r.baseName); + ActivityThread.dumpMemInfoTable(proto, mi, opts.dumpDalvik, opts.dumpSummaryOnly, 0, 0, 0, 0, 0, 0); @@ -13313,13 +13343,19 @@ public class ActivityManagerService extends IActivityManager.Stub if (opts.dumpDetails || (!brief && !opts.oomOnly)) { reportType = ProcessStats.ADD_PSS_EXTERNAL_SLOW; startTime = SystemClock.currentThreadTimeMillis(); - Debug.getMemoryInfo(pid, mi); + if (!Debug.getMemoryInfo(pid, mi)) { + continue; + } endTime = SystemClock.currentThreadTimeMillis(); hasSwapPss = mi.hasSwappedOutPss; } else { reportType = ProcessStats.ADD_PSS_EXTERNAL; startTime = SystemClock.currentThreadTimeMillis(); - mi.dalvikPss = (int) Debug.getPss(pid, tmpLong, null); + long pss = Debug.getPss(pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.dalvikPss = (int) pss; endTime = SystemClock.currentThreadTimeMillis(); mi.dalvikPrivateDirty = (int) tmpLong[0]; mi.dalvikRss = (int) tmpLong[2]; @@ -13447,10 +13483,17 @@ public class ActivityManagerService extends IActivityManager.Stub mi = new Debug.MemoryInfo(); } if (!brief && !opts.oomOnly) { - Debug.getMemoryInfo(st.pid, mi); + if (!Debug.getMemoryInfo(st.pid, mi)) { + continue; + } } else { - mi.nativePss = (int)Debug.getPss(st.pid, tmpLong, null); - mi.nativePrivateDirty = (int)tmpLong[0]; + long pss = Debug.getPss(st.pid, tmpLong, null); + if (pss == 0) { + continue; + } + mi.nativePss = (int) pss; + mi.nativePrivateDirty = (int) tmpLong[0]; + mi.nativeRss = (int) tmpLong[2]; } final long myTotalPss = mi.getTotalPss(); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index c38072661cee..5e48dcf91676 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -88,6 +88,11 @@ class AppErrors { private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>(); /** + * The last time that various processes have crashed and shown an error dialog. + */ + private final ProcessMap<Long> mProcessCrashShowDialogTimes = new ProcessMap<>(); + + /** * Set of applications that we consider to be bad, and will reject * incoming broadcasts from (which the user has no control over). * Processes are added to this set when they have crashed twice within @@ -820,6 +825,11 @@ class AppErrors { } return; } + Long crashShowErrorTime = null; + if (!proc.isolated) { + crashShowErrorTime = mProcessCrashShowDialogTimes.get(proc.info.processName, + proc.uid); + } final boolean showFirstCrash = Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0; @@ -830,10 +840,16 @@ class AppErrors { mService.mUserController.getCurrentUserId()) != 0; final boolean crashSilenced = mAppsNotReportingCrashes != null && mAppsNotReportingCrashes.contains(proc.info.packageName); + final long now = SystemClock.uptimeMillis(); + final boolean shouldThottle = crashShowErrorTime != null + && now < crashShowErrorTime + ProcessList.MIN_CRASH_INTERVAL; if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground) - && !crashSilenced + && !crashSilenced && !shouldThottle && (showFirstCrash || showFirstCrashDevOption || data.repeating)) { proc.getDialogController().showCrashDialogs(data); + if (!proc.isolated) { + mProcessCrashShowDialogTimes.put(proc.info.processName, proc.uid, now); + } } else { // The device is asleep, so just pretend that the user // saw a crash dialog and hit "force quit". diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 12f46569bd20..0fc885a2e61f 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1541,12 +1541,12 @@ public final class OomAdjuster { trackedProcState = true; } } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0 - && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ - && adj > ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { + && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ + && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ; } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ - && adj > ProcessList.PERCEPTIBLE_APP_ADJ) { + && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) { newAdj = ProcessList.PERCEPTIBLE_APP_ADJ; } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) { newAdj = clientAdj; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 2390da5e001c..fbbc67c10a6a 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -3046,12 +3046,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Verify they're not lying about package name mAppOps.checkPackage(callingUid, callingPackage); + final SubscriptionManager sm; final SubscriptionInfo si; final PersistableBundle config; final long token = Binder.clearCallingIdentity(); try { - si = mContext.getSystemService(SubscriptionManager.class) - .getActiveSubscriptionInfo(subId); + sm = mContext.getSystemService(SubscriptionManager.class); + si = sm.getActiveSubscriptionInfo(subId); config = mCarrierConfigManager.getConfigForSubId(subId); } finally { Binder.restoreCallingIdentity(token); @@ -3059,7 +3060,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // First check: is caller the CarrierService? if (si != null) { - if (si.isEmbedded() && si.canManageSubscription(mContext, callingPackage)) { + if (si.isEmbedded() && sm.canManageSubscription(si, callingPackage)) { return; } } diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index 59a58042011e..f5f40090d467 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -48,6 +48,44 @@ "include-filter": "android.permission.cts.PermissionUpdateListenerTest" } ] + }, + { + "name": "FrameworksServicesTests", + "options": [ + { + "install-arg": "-t" + }, + { + "include-filter": "com.android.server.pm.UserDataPreparerTest" + }, + { + "include-filter": "com.android.server.pm.UserLifecycleStressTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerServiceCreateProfileTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerServiceIdRecyclingTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerServiceTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerServiceUserInfoTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerServiceUserTypeTest" + }, + { + "include-filter": "com.android.server.pm.UserManagerTest" + }, + { + "include-filter": "com.android.server.pm.UserRestrictionsUtilsTest" + }, + { + "include-filter": "com.android.server.pm.UserSystemPackageInstallerTest" + } + ] } ], "imports": [ diff --git a/services/core/java/com/android/server/stats/StatsPullAtomService.java b/services/core/java/com/android/server/stats/StatsPullAtomService.java new file mode 100644 index 000000000000..e367f284b39a --- /dev/null +++ b/services/core/java/com/android/server/stats/StatsPullAtomService.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.stats; + +import android.content.Context; +import android.util.Slog; + +import com.android.internal.os.BackgroundThread; +import com.android.server.SystemService; + +/** + * SystemService containing PullAtomCallbacks that are registered with statsd. + * + * @hide + */ +public class StatsPullAtomService extends SystemService { + private static final String TAG = "StatsPullAtomService"; + private static final boolean DEBUG = true; + + public StatsPullAtomService(Context context) { + super(context); + } + + @Override + public void onStart() { + // No op. + } + + @Override + public void onBootPhase(int phase) { + super.onBootPhase(phase); + if (phase == PHASE_SYSTEM_SERVICES_READY) { + BackgroundThread.getHandler().post(() -> { + registerAllPullers(); + }); + } + } + + void registerAllPullers() { + if (DEBUG) { + Slog.d(TAG, "Registering all pullers with statsd"); + } + } +} diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java index 172367a128cc..668630e06cf0 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java @@ -119,10 +119,14 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub { } private void enforceSuggestPhoneTimePermission() { - mContext.enforceCallingPermission(android.Manifest.permission.SET_TIME, "set time"); + mContext.enforceCallingPermission( + android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE, + "suggest phone time and time zone"); } private void enforceSuggestManualTimePermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SET_TIME, "set time"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE, + "suggest manual time and time zone"); } } diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java index c50248d4b402..e30ac8aa0b0c 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java @@ -167,6 +167,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { ipw.increaseIndent(); // level 1 ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet); + ipw.println("mCallback.isAutoTimeDetectionEnabled()=" + + mCallback.isAutoTimeDetectionEnabled()); + ipw.println("mCallback.elapsedRealtimeMillis()=" + mCallback.elapsedRealtimeMillis()); + ipw.println("mCallback.systemClockMillis()=" + mCallback.systemClockMillis()); + ipw.println("mCallback.systemClockUpdateThresholdMillis()=" + + mCallback.systemClockUpdateThresholdMillis()); ipw.println("Time change log:"); ipw.increaseIndent(); // level 2 diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 18ed51a6cd5e..5b58199aec4f 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -1814,8 +1814,8 @@ public final class TvInputManagerService extends SystemService { } @Override - public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) - throws RemoteException { + public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, + @TvInputManager.DvbDeviceType int deviceType) throws RemoteException { if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires DVB_DEVICE permission"); @@ -1852,7 +1852,7 @@ public final class TvInputManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { String deviceFileName; - switch (device) { + switch (deviceType) { case TvInputManager.DVB_DEVICE_DEMUX: deviceFileName = String.format(dvbDeviceFound ? "/dev/dvb/adapter%d/demux%d" : "/dev/dvb%d.demux%d", @@ -1869,14 +1869,14 @@ public final class TvInputManagerService extends SystemService { info.getAdapterId(), info.getDeviceId()); break; default: - throw new IllegalArgumentException("Invalid DVB device: " + device); + throw new IllegalArgumentException("Invalid DVB device: " + deviceType); } try { // The DVB frontend device only needs to be opened in read/write mode, which // allows performing tuning operations. The DVB demux and DVR device are enough // to be opened in read only mode. return ParcelFileDescriptor.open(new File(deviceFileName), - TvInputManager.DVB_DEVICE_FRONTEND == device + TvInputManager.DVB_DEVICE_FRONTEND == deviceType ? ParcelFileDescriptor.MODE_READ_WRITE : ParcelFileDescriptor.MODE_READ_ONLY); } catch (FileNotFoundException e) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index cfe131899987..08221f927531 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -214,6 +214,8 @@ public final class SystemServer { "com.android.server.companion.CompanionDeviceManagerService"; private static final String STATS_COMPANION_LIFECYCLE_CLASS = "com.android.server.stats.StatsCompanion$Lifecycle"; + private static final String STATS_PULL_ATOM_SERVICE_CLASS = + "com.android.server.stats.StatsPullAtomService"; private static final String USB_SERVICE_CLASS = "com.android.server.usb.UsbService$Lifecycle"; private static final String MIDI_SERVICE_CLASS = @@ -1975,6 +1977,11 @@ public final class SystemServer { mSystemServiceManager.startService(STATS_COMPANION_LIFECYCLE_CLASS); t.traceEnd(); + // Statsd pulled atoms + t.traceBegin("StartStatsPullAtomService"); + mSystemServiceManager.startService(STATS_PULL_ATOM_SERVICE_CLASS); + t.traceEnd(); + // Incidentd and dumpstated helper t.traceBegin("StartIncidentCompanionService"); mSystemServiceManager.startService(IncidentCompanionService.class); diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 015e574f2309..12323401c664 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -43,6 +43,10 @@ android_test { "servicestests-utils", "service-appsearch", "service-jobscheduler", + // TODO: remove once Android migrates to JUnit 4.12, + // which provides assertThrows + "testng", + ], aidl: { diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 06b3dc1d9deb..a7275fc74734 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; +import static org.testng.Assert.assertThrows; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -140,20 +141,15 @@ public final class UserManagerTest { assertThat(userInfo).isNotNull(); List<UserInfo> list = mUserManager.getUsers(); - boolean found = false; for (UserInfo user : list) { if (user.id == userInfo.id && user.name.equals("Guest 1") && user.isGuest() && !user.isAdmin() && !user.isPrimary()) { - found = true; - Bundle restrictions = mUserManager.getUserRestrictions(user.getUserHandle()); - assertWithMessage("Guest user should have DISALLOW_CONFIG_WIFI=true by default") - .that(restrictions.getBoolean(UserManager.DISALLOW_CONFIG_WIFI)) - .isTrue(); + return; } } - assertThat(found).isTrue(); + fail("Didn't find a guest: " + list); } @MediumTest @@ -206,14 +202,7 @@ public final class UserManagerTest { @MediumTest @Test public void testRemoveUserByHandle_ThrowsException() { - synchronized (mUserRemoveLock) { - try { - mUserManager.removeUser(null); - fail("Expected IllegalArgumentException on passing in a null UserHandle."); - } catch (IllegalArgumentException expected) { - // Do nothing - exception is expected. - } - } + assertThrows(IllegalArgumentException.class, () -> mUserManager.removeUser(null)); } /** Tests creating a FULL user via specifying userType. */ @@ -343,7 +332,6 @@ public final class UserManagerTest { UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId); assertThat(userInfo).isNotNull(); final int userId = userInfo.id; - final UserHandle userHandle = new UserHandle(userId); assertThat(mUserManager.hasBadge(userId)).isEqualTo(userTypeDetails.hasBadge()); assertThat(mUserManager.getUserIconBadgeResId(userId)) @@ -353,13 +341,13 @@ public final class UserManagerTest { assertThat(mUserManager.getUserBadgeNoBackgroundResId(userId)) .isEqualTo(userTypeDetails.getBadgeNoBackground()); assertThat(mUserManager.isProfile(userId)).isEqualTo(userTypeDetails.isProfile()); - assertThat(mUserManager.getUserTypeForUser(userHandle)) + assertThat(mUserManager.getUserTypeForUser(asHandle(userId))) .isEqualTo(userTypeDetails.getName()); final int badgeIndex = userInfo.profileBadge; assertThat(mUserManager.getUserBadgeColor(userId)).isEqualTo( Resources.getSystem().getColor(userTypeDetails.getBadgeColor(badgeIndex), null)); - assertThat(mUserManager.getBadgedLabelForUser("Test", userHandle)).isEqualTo( + assertThat(mUserManager.getBadgedLabelForUser("Test", asHandle(userId))).isEqualTo( Resources.getSystem().getString(userTypeDetails.getBadgeLabel(badgeIndex), "Test")); } @@ -438,9 +426,8 @@ public final class UserManagerTest { @MediumTest @Test public void testCreateUser_disallowAddUser() throws Exception { - final int creatorId = isAutomotive() ? ActivityManager.getCurrentUser() - : mUserManager.getPrimaryUser().id; - final UserHandle creatorHandle = new UserHandle(creatorId); + final int creatorId = ActivityManager.getCurrentUser(); + final UserHandle creatorHandle = asHandle(creatorId); mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, creatorHandle); try { UserInfo createadInfo = createUser("SecondaryUser", /*flags=*/ 0); @@ -457,7 +444,7 @@ public final class UserManagerTest { public void testCreateProfileForUser_disallowAddManagedProfile() throws Exception { assumeManagedUsersSupported(); final int primaryUserId = mUserManager.getPrimaryUser().id; - final UserHandle primaryUserHandle = new UserHandle(primaryUserId); + final UserHandle primaryUserHandle = asHandle(primaryUserId); mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true, primaryUserHandle); try { @@ -476,7 +463,7 @@ public final class UserManagerTest { public void testCreateProfileForUserEvenWhenDisallowed() throws Exception { assumeManagedUsersSupported(); final int primaryUserId = mUserManager.getPrimaryUser().id; - final UserHandle primaryUserHandle = new UserHandle(primaryUserId); + final UserHandle primaryUserHandle = asHandle(primaryUserId); mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true, primaryUserHandle); try { @@ -495,7 +482,7 @@ public final class UserManagerTest { public void testCreateProfileForUser_disallowAddUser() throws Exception { assumeManagedUsersSupported(); final int primaryUserId = mUserManager.getPrimaryUser().id; - final UserHandle primaryUserHandle = new UserHandle(primaryUserId); + final UserHandle primaryUserHandle = asHandle(primaryUserId); mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle); try { UserInfo userInfo = createProfileForUser("Managed", @@ -540,8 +527,7 @@ public final class UserManagerTest { @MediumTest @Test - public void testGetUserCreationTime() throws Exception { - // TODO: should add a regular user instead of a profile, so it can be tested everywhere + public void testGetManagedProfileCreationTime() throws Exception { assumeManagedUsersSupported(); final int primaryUserId = mUserManager.getPrimaryUser().id; final long startTime = System.currentTimeMillis(); @@ -556,38 +542,40 @@ public final class UserManagerTest { assertWithMessage("creationTime must be 0 if the time is not > EPOCH_PLUS_30_years") .that(profile.creationTime).isEqualTo(0); } - assertThat(mUserManager.getUserCreationTime( - new UserHandle(profile.id))).isEqualTo(profile.creationTime); + assertThat(mUserManager.getUserCreationTime(asHandle(profile.id))) + .isEqualTo(profile.creationTime); long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime; - assertThat(mUserManager.getUserCreationTime( - new UserHandle(primaryUserId))).isEqualTo(ownerCreationTime); + assertThat(mUserManager.getUserCreationTime(asHandle(primaryUserId))) + .isEqualTo(ownerCreationTime); + } + + @MediumTest + @Test + public void testGetUserCreationTime() throws Exception { + long startTime = System.currentTimeMillis(); + UserInfo user = createUser("User", /* flags= */ 0); + long endTime = System.currentTimeMillis(); + assertThat(user).isNotNull(); + assertWithMessage("creationTime must be set when the user is created") + .that(user.creationTime).isIn(Range.closed(startTime, endTime)); } @SmallTest @Test public void testGetUserCreationTime_nonExistentUser() throws Exception { - try { - int noSuchUserId = 100500; - mUserManager.getUserCreationTime(new UserHandle(noSuchUserId)); - fail("SecurityException should be thrown for nonexistent user"); - } catch (Exception e) { - assertWithMessage("SecurityException should be thrown for nonexistent user").that(e) - .isInstanceOf(SecurityException.class); - } + int noSuchUserId = 100500; + assertThrows(SecurityException.class, + () -> mUserManager.getUserCreationTime(asHandle(noSuchUserId))); } @SmallTest @Test public void testGetUserCreationTime_otherUser() throws Exception { UserInfo user = createUser("User 1", 0); - try { - mUserManager.getUserCreationTime(new UserHandle(user.id)); - fail("SecurityException should be thrown for other user"); - } catch (Exception e) { - assertWithMessage("SecurityException should be thrown for other user").that(e) - .isInstanceOf(SecurityException.class); - } + assertThat(user).isNotNull(); + assertThrows(SecurityException.class, + () -> mUserManager.getUserCreationTime(asHandle(user.id))); } private boolean findUser(int id) { @@ -658,11 +646,11 @@ public final class UserManagerTest { UserInfo testUser = createUser("User 1", 0); mUserManager.setUserRestriction( - UserManager.DISALLOW_INSTALL_APPS, true, new UserHandle(testUser.id)); + UserManager.DISALLOW_INSTALL_APPS, true, asHandle(testUser.id)); mUserManager.setUserRestriction( - UserManager.DISALLOW_CONFIG_WIFI, false, new UserHandle(testUser.id)); + UserManager.DISALLOW_CONFIG_WIFI, false, asHandle(testUser.id)); - Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id)); + Bundle stored = mUserManager.getUserRestrictions(asHandle(testUser.id)); // Note this will fail if DO already sets those restrictions. assertThat(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI)).isFalse(); assertThat(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS)).isFalse(); @@ -738,15 +726,8 @@ public final class UserManagerTest { @Test public void testSwitchUserByHandle_ThrowsException() { - synchronized (mUserSwitchLock) { - try { - ActivityManager am = mContext.getSystemService(ActivityManager.class); - am.switchUser(null); - fail("Expected IllegalArgumentException on passing in a null UserHandle."); - } catch (IllegalArgumentException expected) { - // Do nothing - exception is expected. - } - } + ActivityManager am = mContext.getSystemService(ActivityManager.class); + assertThrows(IllegalArgumentException.class, () -> am.switchUser(null)); } @MediumTest @@ -903,4 +884,8 @@ public final class UserManagerTest { private boolean isAutomotive() { return mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); } + + private static UserHandle asHandle(int userId) { + return new UserHandle(userId); + } } diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java index 72a7f508772b..3456cc361eb4 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -18,10 +18,12 @@ package com.android.server.timedetector; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -77,6 +79,22 @@ public class TimeDetectorServiceTest { mHandlerThread.join(); } + @Test(expected = SecurityException.class) + public void testSuggestPhoneTime_withoutPermission() { + doThrow(new SecurityException("Mock")) + .when(mMockContext).enforceCallingPermission(anyString(), any()); + PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion(); + + try { + mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion); + fail(); + } finally { + verify(mMockContext).enforceCallingPermission( + eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE), + anyString()); + } + } + @Test public void testSuggestPhoneTime() throws Exception { doNothing().when(mMockContext).enforceCallingPermission(anyString(), any()); @@ -86,13 +104,29 @@ public class TimeDetectorServiceTest { mTestHandler.assertTotalMessagesEnqueued(1); verify(mMockContext).enforceCallingPermission( - eq(android.Manifest.permission.SET_TIME), + eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE), anyString()); mTestHandler.waitForEmptyQueue(); mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion); } + @Test(expected = SecurityException.class) + public void testSuggestManualTime_withoutPermission() { + doThrow(new SecurityException("Mock")) + .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion(); + + try { + mTimeDetectorService.suggestManualTime(manualTimeSuggestion); + fail(); + } finally { + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), + anyString()); + } + } + @Test public void testSuggestManualTime() throws Exception { doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); @@ -102,7 +136,7 @@ public class TimeDetectorServiceTest { mTestHandler.assertTotalMessagesEnqueued(1); verify(mMockContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.SET_TIME), + eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString()); mTestHandler.waitForEmptyQueue(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index eea08dc6c76b..fdf88497db02 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2481,7 +2481,6 @@ public class CarrierConfigManager { */ public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int"; - /** * Key identifying if the CDMA Caller ID presentation and suppression MMI codes * should be converted to 3GPP CLIR codes when a multimode (CDMA+UMTS+LTE) device is roaming @@ -3120,6 +3119,16 @@ public class CarrierConfigManager { "data_switch_validation_timeout_long"; /** + * Specifies whether the system should prefix the EAP method to the anonymous identity. + * The following prefix will be added if this key is set to TRUE: + * EAP-AKA: "0" + * EAP-SIM: "1" + * EAP-AKA_PRIME: "6" + * @hide + */ + public static final String ENABLE_EAP_METHOD_PREFIX_BOOL = "enable_eap_method_prefix_bool"; + + /** * GPS configs. See the GNSS HAL documentation for more details. */ public static final class Gps { @@ -3934,6 +3943,7 @@ public class CarrierConfigManager { CellSignalStrengthLte.USE_RSRP | CellSignalStrengthLte.USE_RSSNR); // Default wifi configurations. sDefaults.putAll(Wifi.getDefaults()); + sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false); } /** |