diff options
68 files changed, 1268 insertions, 308 deletions
diff --git a/api/Android.bp b/api/Android.bp index c16bce5a1aea..e9cc40513221 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -83,6 +83,7 @@ combined_apis { "framework-configinfrastructure", "framework-connectivity", "framework-connectivity-t", + "framework-crashrecovery", "framework-devicelock", "framework-graphics", "framework-healthfitness", @@ -104,6 +105,7 @@ combined_apis { system_server_classpath: [ "service-art", "service-configinfrastructure", + "service-crashrecovery", "service-healthfitness", "service-media-s", "service-permission", diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp index 7142eb5bef53..e1621008cc33 100644 --- a/api/ApiDocs.bp +++ b/api/ApiDocs.bp @@ -131,13 +131,7 @@ droidstubs { defaults: ["framework-doc-stubs-sources-default"], args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ", - api_levels_annotations_enabled: true, - api_levels_annotations_dirs: [ - "sdk-dir", - "api-versions-jars-dir", - ], - api_levels_sdk_type: "system", - extensions_info_file: ":sdk-extensions-info", + api_levels_module: "api_versions_system", } ///////////////////////////////////////////////////////////////////// diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 79efaced998a..a410a58218c4 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -677,6 +677,7 @@ java_api_library { "api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -692,6 +693,7 @@ java_api_library { "system-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -709,6 +711,7 @@ java_api_library { "test-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -724,6 +727,7 @@ java_api_library { "api-stubs-docs-non-updatable.api.contribution", "system-api-stubs-docs-non-updatable.api.contribution", ], + enable_validation: false, } java_api_library { @@ -743,6 +747,7 @@ java_api_library { "module-lib-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -756,6 +761,7 @@ java_api_library { "stub-annotations", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -780,6 +786,7 @@ java_api_library { visibility: [ "//visibility:private", ], + enable_validation: false, } java_api_library { @@ -796,6 +803,7 @@ java_api_library { "android_module_lib_stubs_current.from-text", ], visibility: ["//visibility:public"], + enable_validation: false, } //////////////////////////////////////////////////////////////////////// diff --git a/boot/Android.bp b/boot/Android.bp index 8a3d35e2d0eb..b33fab6e1a9f 100644 --- a/boot/Android.bp +++ b/boot/Android.bp @@ -84,6 +84,10 @@ custom_platform_bootclasspath { module: "com.android.conscrypt-bootclasspath-fragment", }, { + apex: "com.android.crashrecovery", + module: "com.android.crashrecovery-bootclasspath-fragment", + }, + { apex: "com.android.devicelock", module: "com.android.devicelock-bootclasspath-fragment", }, diff --git a/core/api/current.txt b/core/api/current.txt index e8988dcf3f17..7c1751ffe815 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android { public final class Manifest { @@ -5677,6 +5675,7 @@ package android.app { ctor @Deprecated public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet); ctor @Deprecated public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet, int); method @Deprecated public void onBackStackChanged(); + method @Deprecated protected void onLayout(boolean, int, int, int, int); method @Deprecated public void setActivity(android.app.Activity); method @Deprecated public void setMaxVisible(int); method @Deprecated public void setOnBreadCrumbClickListener(android.app.FragmentBreadCrumbs.OnBreadCrumbClickListener); @@ -13542,6 +13541,7 @@ package android.content.res { public interface XmlResourceParser extends org.xmlpull.v1.XmlPullParser android.util.AttributeSet java.lang.AutoCloseable { method public void close(); + method public String getAttributeNamespace(int); } } @@ -20227,7 +20227,7 @@ package android.inputmethodservice { method @Deprecated public boolean isPreviewEnabled(); method @Deprecated public boolean isProximityCorrectionEnabled(); method @Deprecated public boolean isShifted(); - method public void onClick(android.view.View); + method @Deprecated public void onClick(android.view.View); method @Deprecated public void onDetachedFromWindow(); method @Deprecated public void onDraw(android.graphics.Canvas); method @Deprecated protected boolean onLongPress(android.inputmethodservice.Keyboard.Key); @@ -24759,7 +24759,7 @@ package android.media { @Deprecated public class RemoteControlClient.MetadataEditor extends android.media.MediaMetadataEditor { method @Deprecated public void apply(); - method public Object clone() throws java.lang.CloneNotSupportedException; + method @Deprecated public Object clone() throws java.lang.CloneNotSupportedException; method @Deprecated public android.media.RemoteControlClient.MetadataEditor putBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException; method @Deprecated public android.media.RemoteControlClient.MetadataEditor putLong(int, long) throws java.lang.IllegalArgumentException; method @Deprecated public android.media.RemoteControlClient.MetadataEditor putObject(int, Object) throws java.lang.IllegalArgumentException; @@ -27613,6 +27613,7 @@ package android.media.tv { method @NonNull public java.util.List<android.media.AudioPresentation> getAudioPresentations(); method public String getSelectedTrack(int); method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int); + method protected void onLayout(boolean, int, int, int, int); method public boolean onUnhandledInputEvent(android.view.InputEvent); method public void overrideTvAppAttributionSource(@NonNull android.content.AttributionSource); method public void reset(); @@ -44040,7 +44041,6 @@ package android.telephony { method public int getLongitude(); method public int getNetworkId(); method public int getSystemId(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityCdma> CREATOR; } @@ -44056,7 +44056,6 @@ package android.telephony { method @Nullable public String getMncString(); method @Nullable public String getMobileNetworkOperator(); method @Deprecated public int getPsc(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityGsm> CREATOR; } @@ -44074,7 +44073,6 @@ package android.telephony { method @Nullable public String getMobileNetworkOperator(); method public int getPci(); method public int getTac(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR; } @@ -44087,7 +44085,6 @@ package android.telephony { method @IntRange(from=0, to=3279165) public int getNrarfcn(); method @IntRange(from=0, to=1007) public int getPci(); method @IntRange(from=0, to=16777215) public int getTac(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR; } @@ -44101,7 +44098,6 @@ package android.telephony { method @Nullable public String getMncString(); method @Nullable public String getMobileNetworkOperator(); method public int getUarfcn(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR; } @@ -44117,7 +44113,6 @@ package android.telephony { method @Nullable public String getMobileNetworkOperator(); method public int getPsc(); method public int getUarfcn(); - method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR; } @@ -44201,6 +44196,7 @@ package android.telephony { public final class CellSignalStrengthCdma extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method public int getCdmaDbm(); method public int getCdmaEcio(); @@ -44211,24 +44207,28 @@ package android.telephony { method public int getEvdoLevel(); method public int getEvdoSnr(); method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthCdma> CREATOR; } public final class CellSignalStrengthGsm extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method public int getBitErrorRate(); method public int getDbm(); method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel(); method public int getRssi(); method public int getTimingAdvance(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthGsm> CREATOR; } public final class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method @IntRange(from=0, to=15) public int getCqi(); method @IntRange(from=1, to=6) public int getCqiTableIndex(); @@ -44239,12 +44239,14 @@ package android.telephony { method public int getRssi(); method public int getRssnr(); method public int getTimingAdvance(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthLte> CREATOR; } public final class CellSignalStrengthNr extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method @IntRange(from=0, to=15) @NonNull public java.util.List<java.lang.Integer> getCsiCqiReport(); method @IntRange(from=1, to=3) public int getCsiCqiTableIndex(); @@ -44257,26 +44259,31 @@ package android.telephony { method public int getSsRsrq(); method public int getSsSinr(); method @IntRange(from=0, to=1282) public int getTimingAdvanceMicros(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthNr> CREATOR; } public final class CellSignalStrengthTdscdma extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method public int getDbm(); method @IntRange(from=0, to=4) public int getLevel(); method public int getRscp(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthTdscdma> CREATOR; } public final class CellSignalStrengthWcdma extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); + method public boolean equals(Object); method public int getAsuLevel(); method public int getDbm(); method public int getEcNo(); method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel(); + method public int hashCode(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR; } @@ -47056,6 +47063,7 @@ package android.text { method @Deprecated public int length(); method @Deprecated public static android.text.AlteredCharSequence make(CharSequence, char[], int, int); method @Deprecated public CharSequence subSequence(int, int); + method @Deprecated public String toString(); } @Deprecated public class AndroidCharacter { @@ -47469,6 +47477,7 @@ package android.text { method public void removeSpan(Object); method public void setSpan(Object, int, int, int); method public CharSequence subSequence(int, int); + method public String toString(); } public static final class PrecomputedText.Params { @@ -47598,6 +47607,7 @@ package android.text { method public void setFilters(android.text.InputFilter[]); method public void setSpan(Object, int, int, int); method public CharSequence subSequence(int, int); + method public String toString(); method public static android.text.SpannableStringBuilder valueOf(CharSequence); } @@ -49224,7 +49234,9 @@ package android.util { method public boolean containsValue(Object); method public void ensureCapacity(int); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public boolean equals(@Nullable Object); method public V get(Object); + method public int hashCode(); method public int indexOfKey(Object); method public int indexOfValue(Object); method public boolean isEmpty(); @@ -49256,7 +49268,9 @@ package android.util { method public boolean contains(Object); method public boolean containsAll(java.util.Collection<?>); method public void ensureCapacity(int); + method public boolean equals(@Nullable Object); method public void forEach(java.util.function.Consumer<? super E>); + method public int hashCode(); method public int indexOf(Object); method public boolean isEmpty(); method public java.util.Iterator<E> iterator(); @@ -57952,6 +57966,7 @@ package android.widget { ctor @Deprecated public AbsoluteLayout(android.content.Context, android.util.AttributeSet); ctor @Deprecated public AbsoluteLayout(android.content.Context, android.util.AttributeSet, int); ctor @Deprecated public AbsoluteLayout(android.content.Context, android.util.AttributeSet, int, int); + method @Deprecated protected void onLayout(boolean, int, int, int, int); } @Deprecated public static class AbsoluteLayout.LayoutParams extends android.view.ViewGroup.LayoutParams { @@ -58030,6 +58045,7 @@ package android.widget { method public long getSelectedItemId(); method public int getSelectedItemPosition(); method public abstract android.view.View getSelectedView(); + method protected void onLayout(boolean, int, int, int, int); method public boolean performItemClick(android.view.View, int, long); method public abstract void setAdapter(T); method public void setEmptyView(android.view.View); @@ -58676,6 +58692,7 @@ package android.widget { method public android.widget.FrameLayout.LayoutParams generateLayoutParams(android.util.AttributeSet); method @Deprecated public boolean getConsiderGoneChildrenWhenMeasuring(); method public boolean getMeasureAllChildren(); + method protected void onLayout(boolean, int, int, int, int); method public void setMeasureAllChildren(boolean); } @@ -58729,6 +58746,7 @@ package android.widget { method public boolean getUseDefaultMargins(); method public boolean isColumnOrderPreserved(); method public boolean isRowOrderPreserved(); + method protected void onLayout(boolean, int, int, int, int); method public void setAlignmentMode(int); method public void setColumnCount(int); method public void setColumnOrderPreserved(boolean); @@ -58951,6 +58969,7 @@ package android.widget { method public float getWeightSum(); method public boolean isBaselineAligned(); method public boolean isMeasureWithLargestChildEnabled(); + method protected void onLayout(boolean, int, int, int, int); method public void setBaselineAligned(boolean); method public void setBaselineAlignedChildIndex(int); method public void setDividerDrawable(android.graphics.drawable.Drawable); @@ -59499,6 +59518,7 @@ package android.widget { method public android.widget.RelativeLayout.LayoutParams generateLayoutParams(android.util.AttributeSet); method public int getGravity(); method public int getIgnoreGravity(); + method protected void onLayout(boolean, int, int, int, int); method public void setGravity(int); method public void setHorizontalGravity(int); method public void setIgnoreGravity(int); @@ -59953,6 +59973,7 @@ package android.widget { method @Deprecated public boolean isMoving(); method @Deprecated public boolean isOpened(); method @Deprecated public void lock(); + method @Deprecated protected void onLayout(boolean, int, int, int, int); method @Deprecated public void open(); method @Deprecated public void setOnDrawerCloseListener(android.widget.SlidingDrawer.OnDrawerCloseListener); method @Deprecated public void setOnDrawerOpenListener(android.widget.SlidingDrawer.OnDrawerOpenListener); @@ -60597,6 +60618,7 @@ package android.widget { method public boolean hideOverflowMenu(); method public void inflateMenu(@MenuRes int); method public boolean isOverflowMenuShowing(); + method protected void onLayout(boolean, int, int, int, int); method public void setCollapseContentDescription(@StringRes int); method public void setCollapseContentDescription(@Nullable CharSequence); method public void setCollapseIcon(@DrawableRes int); @@ -60751,7 +60773,7 @@ package android.widget { method @Deprecated public android.view.View getZoomControls(); method @Deprecated public boolean isAutoDismissed(); method @Deprecated public boolean isVisible(); - method public boolean onTouch(android.view.View, android.view.MotionEvent); + method @Deprecated public boolean onTouch(android.view.View, android.view.MotionEvent); method @Deprecated public void setAutoDismissed(boolean); method @Deprecated public void setFocusable(boolean); method @Deprecated public void setOnZoomListener(android.widget.ZoomButtonsController.OnZoomListener); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 01cf77abd3ed..7cfa1e377933 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { diff --git a/core/api/module-lib-removed.txt b/core/api/module-lib-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/core/api/module-lib-removed.txt +++ b/core/api/module-lib-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/core/api/removed.txt b/core/api/removed.txt index ede88a29624d..8b3696a1e6d9 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.app { public class Notification implements android.os.Parcelable { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 40eee4c277ac..64734f4dc762 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { @@ -4042,7 +4040,9 @@ package android.content.pm { } public static final class PackageManager.UninstallCompleteCallback implements android.os.Parcelable { + method public int describeContents(); method public void onUninstallComplete(@NonNull String, int, @Nullable String); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageManager.UninstallCompleteCallback> CREATOR; } @@ -5941,6 +5941,7 @@ package android.hardware.soundtrigger { public static final class SoundTrigger.Keyphrase implements android.os.Parcelable { ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]); + method public int describeContents(); method public int getId(); method @NonNull public java.util.Locale getLocale(); method public int getRecognitionModes(); @@ -5963,6 +5964,7 @@ package android.hardware.soundtrigger { public static final class SoundTrigger.KeyphraseSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable { ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int); ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[]); + method public int describeContents(); method @NonNull public android.hardware.soundtrigger.SoundTrigger.Keyphrase[] getKeyphrases(); method @NonNull public static android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel readFromParcel(@NonNull android.os.Parcel); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -5970,6 +5972,7 @@ package android.hardware.soundtrigger { } public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable { + method public int describeContents(); method public int getEnd(); method public int getStart(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -7412,6 +7415,7 @@ package android.media.musicrecognition { public abstract class MusicRecognitionService extends android.app.Service { ctor public MusicRecognitionService(); + method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback); } @@ -7470,6 +7474,7 @@ package android.media.soundtrigger { public abstract class SoundTriggerDetectionService extends android.app.Service { ctor public SoundTriggerDetectionService(); + method public final android.os.IBinder onBind(android.content.Intent); method @MainThread public void onConnected(@NonNull java.util.UUID, @Nullable android.os.Bundle); method @MainThread public void onDisconnected(@NonNull java.util.UUID, @Nullable android.os.Bundle); method @MainThread public void onError(@NonNull java.util.UUID, @Nullable android.os.Bundle, int, int); @@ -8183,6 +8188,7 @@ package android.media.tv.tuner.filter { } public class MediaEvent extends android.media.tv.tuner.filter.FilterEvent { + method protected void finalize(); method public long getAudioHandle(); method @NonNull public java.util.List<android.media.AudioPresentation> getAudioPresentations(); method public long getAvDataId(); @@ -9577,6 +9583,8 @@ package android.net { package android.net.metrics { @Deprecated public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event { + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); } @Deprecated public static final class ApfProgramEvent.Builder { @@ -9591,6 +9599,8 @@ package android.net.metrics { } @Deprecated public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event { + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); } @Deprecated public static final class ApfStats.Builder { @@ -9609,6 +9619,8 @@ package android.net.metrics { } @Deprecated public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event { + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); } @Deprecated public static final class DhcpClientEvent.Builder { @@ -9620,7 +9632,9 @@ package android.net.metrics { @Deprecated public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event { ctor @Deprecated public DhcpErrorEvent(int); + method @Deprecated public int describeContents(); method @Deprecated public static int errorCodeWithOption(int, int); + method @Deprecated public void writeToParcel(android.os.Parcel, int); field @Deprecated public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000 field @Deprecated public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000 field @Deprecated public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000 @@ -9658,6 +9672,8 @@ package android.net.metrics { @Deprecated public final class IpManagerEvent implements android.net.metrics.IpConnectivityLog.Event { ctor @Deprecated public IpManagerEvent(int, long); + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); field @Deprecated public static final int COMPLETE_LIFECYCLE = 3; // 0x3 field @Deprecated public static final int ERROR_INTERFACE_NOT_FOUND = 8; // 0x8 field @Deprecated public static final int ERROR_INVALID_PROVISIONING = 7; // 0x7 @@ -9670,6 +9686,8 @@ package android.net.metrics { @Deprecated public final class IpReachabilityEvent implements android.net.metrics.IpConnectivityLog.Event { ctor @Deprecated public IpReachabilityEvent(int); + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); field @Deprecated public static final int NUD_FAILED = 512; // 0x200 field @Deprecated public static final int NUD_FAILED_ORGANIC = 1024; // 0x400 field @Deprecated public static final int PROBE = 256; // 0x100 @@ -9680,6 +9698,8 @@ package android.net.metrics { @Deprecated public final class NetworkEvent implements android.net.metrics.IpConnectivityLog.Event { ctor @Deprecated public NetworkEvent(int, long); ctor @Deprecated public NetworkEvent(int); + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); field @Deprecated public static final int NETWORK_CAPTIVE_PORTAL_FOUND = 4; // 0x4 field @Deprecated public static final int NETWORK_CONNECTED = 1; // 0x1 field @Deprecated public static final int NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND = 12; // 0xc @@ -9696,6 +9716,8 @@ package android.net.metrics { } @Deprecated public final class RaEvent implements android.net.metrics.IpConnectivityLog.Event { + method @Deprecated public int describeContents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); } @Deprecated public static final class RaEvent.Builder { @@ -9710,7 +9732,9 @@ package android.net.metrics { } @Deprecated public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event { + method @Deprecated public int describeContents(); method @Deprecated @NonNull public static String getProbeName(int); + method @Deprecated public void writeToParcel(android.os.Parcel, int); field @Deprecated public static final int DNS_FAILURE = 0; // 0x0 field @Deprecated public static final int DNS_SUCCESS = 1; // 0x1 field @Deprecated public static final int PROBE_DNS = 0; // 0x0 @@ -12108,6 +12132,7 @@ package android.service.assist.classification { public abstract class FieldClassificationService extends android.app.Service { ctor public FieldClassificationService(); + method public final android.os.IBinder onBind(android.content.Intent); method public abstract void onClassificationRequest(@NonNull android.service.assist.classification.FieldClassificationRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.assist.classification.FieldClassificationResponse,java.lang.Exception>); method public void onConnected(); method public void onDisconnected(); @@ -12186,6 +12211,7 @@ package android.service.autofill.augmented { method protected final void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]); method protected void dump(@NonNull java.io.PrintWriter, @NonNull String[]); method @Nullable public final android.service.autofill.FillEventHistory getFillEventHistory(); + method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); method public void onFillRequest(@NonNull android.service.autofill.augmented.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.augmented.FillController, @NonNull android.service.autofill.augmented.FillCallback); @@ -12224,6 +12250,7 @@ package android.service.autofill.augmented { public final class FillWindow implements java.lang.AutoCloseable { ctor public FillWindow(); + method public void close(); method public void destroy(); method public boolean update(@NonNull android.service.autofill.augmented.PresentationParams.Area, @NonNull android.view.View, long); } @@ -12249,6 +12276,7 @@ package android.service.carrier { public final class CarrierMessagingServiceWrapper implements java.lang.AutoCloseable { ctor public CarrierMessagingServiceWrapper(); method public boolean bindToCarrierMessagingService(@NonNull android.content.Context, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull Runnable); + method public void close(); method public void disconnect(); method public void downloadMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallback); method public void receiveSms(@NonNull android.service.carrier.MessagePdu, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallback); @@ -12299,6 +12327,7 @@ package android.service.contentcapture { method public final void disableSelf(); method public void onActivityEvent(@NonNull android.service.contentcapture.ActivityEvent); method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData); + method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent); method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId); @@ -12337,6 +12366,7 @@ package android.service.contentsuggestions { public abstract class ContentSuggestionsService extends android.app.Service { ctor public ContentSuggestionsService(); + method public final android.os.IBinder onBind(android.content.Intent); method public abstract void onClassifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback); method public abstract void onNotifyInteraction(@NonNull String, @NonNull android.os.Bundle); method public abstract void onProcessContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle); @@ -12350,6 +12380,7 @@ package android.service.dataloader { public abstract class DataLoaderService extends android.app.Service { ctor public DataLoaderService(); + method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(@NonNull android.content.pm.DataLoaderParams); } @@ -13022,6 +13053,7 @@ package android.service.tracing { public class TraceReportService extends android.app.Service { ctor public TraceReportService(); + method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); method public void onReportTrace(@NonNull android.service.tracing.TraceReportService.TraceParams); } @@ -13610,6 +13642,7 @@ package android.telecom { method @Nullable public android.content.ComponentName getCallScreeningComponent(); method public boolean isBlocked(); method public boolean isInContacts(); + method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telecom.Connection.CallFilteringCompletionInfo> CREATOR; } @@ -13918,6 +13951,7 @@ package android.telephony { method public int getReason(); method public int getTimeoutSeconds(); method public boolean isEnabled(); + method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR; field public static final int REASON_ALL = 4; // 0x4 field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5 @@ -14202,6 +14236,7 @@ package android.telephony { method public int getDownlinkCapacityKbps(); method public int getType(); method public int getUplinkCapacityKbps(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LinkCapacityEstimate> CREATOR; field public static final int INVALID = -1; // 0xffffffff field public static final int LCE_TYPE_COMBINED = 2; // 0x2 @@ -14211,8 +14246,10 @@ package android.telephony { public final class LteVopsSupportInfo extends android.telephony.VopsSupportInfo { ctor public LteVopsSupportInfo(int, int); + method public boolean equals(@Nullable Object); method public int getEmcBearerSupport(); method public int getVopsSupport(); + method public int hashCode(); method public boolean isEmergencyServiceFallbackSupported(); method public boolean isEmergencyServiceSupported(); method public boolean isVopsSupported(); @@ -14312,9 +14349,11 @@ package android.telephony { public final class NrVopsSupportInfo extends android.telephony.VopsSupportInfo { ctor public NrVopsSupportInfo(int, int, int); + method public boolean equals(@Nullable Object); method public int getEmcSupport(); method public int getEmfSupport(); method public int getVopsSupport(); + method public int hashCode(); method public boolean isEmergencyServiceFallbackSupported(); method public boolean isEmergencyServiceSupported(); method public boolean isVopsSupported(); @@ -15427,6 +15466,7 @@ package android.telephony.data { public abstract class QualifiedNetworksService extends android.app.Service { ctor public QualifiedNetworksService(); + method public android.os.IBinder onBind(android.content.Intent); method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int); field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService"; } @@ -15618,6 +15658,7 @@ package android.telephony.gba { public class GbaService extends android.app.Service { ctor public GbaService(); method public void onAuthenticationRequest(int, int, int, @NonNull android.net.Uri, @NonNull byte[], boolean); + method public android.os.IBinder onBind(android.content.Intent); method public final void reportAuthenticationFailure(int, int) throws java.lang.RuntimeException; method public final void reportKeysAvailable(int, @NonNull byte[], @NonNull String) throws java.lang.RuntimeException; field public static final String SERVICE_INTERFACE = "android.telephony.gba.GbaService"; @@ -16120,6 +16161,7 @@ package android.telephony.ims { method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int); method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); + method public android.os.IBinder onBind(android.content.Intent); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); method public void readyForFeatureCreation(); diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt index 4161330dcb37..1c10356c6b03 100644 --- a/core/api/system-removed.txt +++ b/core/api/system-removed.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.app { public class AppOpsManager { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8d0e396f110d..7742b86447e6 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { @@ -3932,7 +3930,9 @@ package android.widget.inline { package android.window { public final class BackNavigationInfo implements android.os.Parcelable { + method public int describeContents(); method @NonNull public static String typeToString(int); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.window.BackNavigationInfo> CREATOR; field public static final String KEY_TRIGGER_BACK = "TriggerBack"; field public static final int TYPE_CALLBACK = 4; // 0x4 @@ -3993,11 +3993,13 @@ package android.window { } public final class TaskFragmentCreationParams implements android.os.Parcelable { + method public int describeContents(); method @NonNull public android.os.IBinder getFragmentToken(); method @NonNull public android.graphics.Rect getInitialRelativeBounds(); method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizer(); method @NonNull public android.os.IBinder getOwnerToken(); method public int getWindowingMode(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskFragmentCreationParams> CREATOR; } @@ -4009,6 +4011,7 @@ package android.window { } public final class TaskFragmentInfo implements android.os.Parcelable { + method public int describeContents(); method public boolean equalsForTaskFragmentOrganizer(@Nullable android.window.TaskFragmentInfo); method @NonNull public java.util.List<android.os.IBinder> getActivities(); method @NonNull public java.util.List<android.os.IBinder> getActivitiesRequestedInTaskFragment(); @@ -4022,6 +4025,7 @@ package android.window { method public boolean isEmpty(); method public boolean isTaskClearedForReuse(); method public boolean isVisible(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskFragmentInfo> CREATOR; } @@ -4044,6 +4048,8 @@ package android.window { } public final class TaskFragmentOrganizerToken implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskFragmentOrganizerToken> CREATOR; } diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt index cf0264353159..726871eccc6c 100644 --- a/core/api/test-lint-baseline.txt +++ b/core/api/test-lint-baseline.txt @@ -761,6 +761,8 @@ MissingNullability: android.widget.TimePicker#getMinuteView(): Missing nullability on method `getMinuteView` return MissingNullability: android.widget.TimePicker#getPmView(): Missing nullability on method `getPmView` return +MissingNullability: android.window.TaskFragmentOrganizerToken#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `dest` in method `writeToParcel` MutableBareField: android.content.AutofillOptions#appDisabledExpiration: diff --git a/core/api/test-removed.txt b/core/api/test-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/core/api/test-removed.txt +++ b/core/api/test-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 6a51171b8f90..2d554031ab48 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -115,6 +115,26 @@ public class KeyguardManager { "android.app.action.CONFIRM_REMOTE_DEVICE_CREDENTIAL"; /** + * Intent used to prompt user for device credential for entering repair + * mode. If the credential is verified successfully, then the information + * needed to verify the credential again will be written to a location that + * is available to repair mode. This makes it possible for repair mode to + * require that the same credential be provided to exit repair mode. + * @hide + */ + public static final String ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL = + "android.app.action.PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL"; + + /** + * Intent used to prompt user for device credential that is written by + * {@link #ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL} for exiting + * repair mode. + * @hide + */ + public static final String ACTION_CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL = + "android.app.action.CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL"; + + /** * A CharSequence dialog title to show to the user when used with a * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. * @hide diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 92be4c0c7dc3..e6bdfe1b95c4 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -116,6 +116,8 @@ public class GraphicsEnvironment { private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle"; private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; + private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported"; + private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; @@ -123,6 +125,7 @@ public class GraphicsEnvironment { private int mAngleOptInIndex = -1; private boolean mEnabledByGameMode = false; + private boolean mShouldUseAngle = false; /** * Set up GraphicsEnvironment @@ -141,19 +144,16 @@ public class GraphicsEnvironment { // Setup ANGLE and pass down ANGLE details to the C++ code Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle"); - boolean useAngle = false; if (setupAngle(context, coreSettings, pm, packageName)) { - if (shouldUseAngle(context, coreSettings, packageName)) { - useAngle = true; - setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, - 0, packageName, getVulkanVersion(pm)); - } + mShouldUseAngle = true; + setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, + 0, packageName, getVulkanVersion(pm)); } Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver"); if (!chooseDriver(context, coreSettings, pm, packageName, appInfoWithMetaData)) { - if (!useAngle) { + if (!mShouldUseAngle) { setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE, SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), @@ -503,10 +503,12 @@ public class GraphicsEnvironment { final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); if (resolveInfos.size() != 1) { - Log.e(TAG, "Invalid number of ANGLE packages. Required: 1, Found: " + Log.v(TAG, "Invalid number of ANGLE packages. Required: 1, Found: " + resolveInfos.size()); - for (ResolveInfo resolveInfo : resolveInfos) { - Log.e(TAG, "Found ANGLE package: " + resolveInfo.activityInfo.packageName); + if (DEBUG) { + for (ResolveInfo resolveInfo : resolveInfos) { + Log.d(TAG, "Found ANGLE package: " + resolveInfo.activityInfo.packageName); + } } return ""; } @@ -541,26 +543,42 @@ public class GraphicsEnvironment { } /** - * Determine whether ANGLE should be used, set it up if so, and pass ANGLE details down to - * the C++ GraphicsEnv class. - * - * If ANGLE will be used, GraphicsEnv::setAngleInfo() will be called to enable ANGLE to be - * properly used. + * Determine whether ANGLE should be used, attempt to set up from apk first, if ANGLE can be + * set up from apk, pass ANGLE details down to the C++ GraphicsEnv class via + * GraphicsEnv::setAngleInfo(). If apk setup fails, attempt to set up to use system ANGLE. + * Return false if both fail. * - * @param context - * @param bundle - * @param pm + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageManager - PackageManager of the application process. * @param packageName - package name of the application. - * @return true: ANGLE setup successfully - * false: ANGLE not setup (not on allowlist, ANGLE not present, etc.) + * @return true: can set up to use ANGLE successfully. + * false: can not set up to use ANGLE (not on allowlist, ANGLE not present, etc.) */ - private boolean setupAngle(Context context, Bundle bundle, PackageManager pm, + private boolean setupAngle(Context context, Bundle bundle, PackageManager packageManager, String packageName) { if (!shouldUseAngle(context, bundle, packageName)) { return false; } + return setupAngleFromApk(context, bundle, packageManager, packageName) + || setupAngleFromSystem(context, bundle, packageName); + } + + /** + * Attempt to set up ANGLE from the packaged apk, if the apk can be found, pass ANGLE details to + * the C++ GraphicsEnv class. + * + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageManager - PackageManager of the application process. + * @param packageName - package name of the application. + * @return true: can set up to use ANGLE apk. + * false: can not set up to use ANGLE apk (ANGLE apk not present, etc.) + */ + private boolean setupAngleFromApk(Context context, Bundle bundle, PackageManager packageManager, + String packageName) { ApplicationInfo angleInfo = null; // If the developer has specified a debug package over ADB, attempt to find it @@ -569,7 +587,7 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE debug package enabled: " + anglePkgName); try { // Note the debug package does not have to be pre-installed - angleInfo = pm.getApplicationInfo(anglePkgName, 0); + angleInfo = packageManager.getApplicationInfo(anglePkgName, 0); } catch (PackageManager.NameNotFoundException e) { // If the debug package is specified but not found, abort. Log.v(TAG, "ANGLE debug package '" + anglePkgName + "' not installed"); @@ -579,7 +597,7 @@ public class GraphicsEnvironment { // Otherwise, check to see if ANGLE is properly installed if (angleInfo == null) { - anglePkgName = getAnglePackageName(pm); + anglePkgName = getAnglePackageName(packageManager); if (TextUtils.isEmpty(anglePkgName)) { Log.v(TAG, "Failed to find ANGLE package."); return false; @@ -588,7 +606,7 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE package enabled: " + anglePkgName); try { // Production ANGLE libraries must be pre-installed as a system app - angleInfo = pm.getApplicationInfo(anglePkgName, + angleInfo = packageManager.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { Log.v(TAG, "ANGLE package '" + anglePkgName + "' not installed"); @@ -612,8 +630,32 @@ public class GraphicsEnvironment { // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name, // and features to use. final String[] features = getAngleEglFeatures(context, bundle); - setAngleInfo(paths, packageName, ANGLE_GL_DRIVER_CHOICE_ANGLE, features); + setAngleInfo(paths, false, packageName, features); + + return true; + } + + /** + * Attempt to set up ANGLE from system, if the apk can be found, pass ANGLE details to + * the C++ GraphicsEnv class. + * + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageName - package name of the application. + * @return true: can set up to use system ANGLE. + * false: can not set up to use system ANGLE because it doesn't exist. + */ + private boolean setupAngleFromSystem(Context context, Bundle bundle, String packageName) { + final boolean systemAngleSupported = SystemProperties + .getBoolean(PROPERTY_RO_ANGLE_SUPPORTED, false); + if (!systemAngleSupported) { + return false; + } + // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name, + // and features to use. + final String[] features = getAngleEglFeatures(context, bundle); + setAngleInfo("", true, packageName, features); return true; } @@ -636,7 +678,10 @@ public class GraphicsEnvironment { } /** - * Show the ANGLE in Use Dialog Box + * Show the ANGLE in use dialog box. + * The ANGLE in use dialog box will show up as long as the application + * should use ANGLE. It does not mean the application has successfully + * loaded ANGLE because this check happens before the loading completes. * @param context */ public void showAngleInUseDialogBox(Context context) { @@ -644,14 +689,15 @@ public class GraphicsEnvironment { return; } - final String packageName = context.getPackageName(); - if (!getShouldUseAngle(packageName)) { + if (!mShouldUseAngle) { return; } final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE); final String anglePkg = getAnglePackageName(context.getPackageManager()); - intent.setPackage(anglePkg); + if (anglePkg.isEmpty()) { + return; + } context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { @Override @@ -890,9 +936,8 @@ public class GraphicsEnvironment { private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion); - private static native void setAngleInfo(String path, String appPackage, - String devOptIn, String[] features); - private static native boolean getShouldUseAngle(String packageName); + private static native void setAngleInfo(String path, boolean useSystemAngle, String packageName, + String[] features); private static native boolean setInjectLayersPrSetDumpable(); private static native void nativeToggleAngleAsSystemDriver(boolean enabled); diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 1a3dcee427d8..a49ee7d00751 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -104,16 +104,6 @@ interface INetworkManagementService void setIPv6AddrGenMode(String iface, int mode); /** - * Add the specified route to the interface. - */ - void addRoute(int netId, in RouteInfo route); - - /** - * Remove the specified route from the interface. - */ - void removeRoute(int netId, in RouteInfo route); - - /** * Shuts down the service */ @EnforcePermission("SHUTDOWN") diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 9cdb9cefdc43..bcd8c7df196f 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -17965,6 +17965,15 @@ public final class Settings { "review_permissions_notification_state"; /** + * Whether repair mode is active on the device. + * <p> + * Set to 1 for true and 0 for false. + * + * @hide + */ + public static final String REPAIR_MODE_ACTIVE = "repair_mode_active"; + + /** * Settings migrated from Wear OS settings provider. * @hide */ diff --git a/core/java/android/service/rotationresolver/OWNERS b/core/java/android/service/rotationresolver/OWNERS index 5b57fc7fa528..dce874dcd982 100644 --- a/core/java/android/service/rotationresolver/OWNERS +++ b/core/java/android/service/rotationresolver/OWNERS @@ -1,9 +1,7 @@ # Bug component: 814982 asalo@google.com -augale@google.com eejiang@google.com payamp@google.com siddikap@google.com -svetoslavganov@google.com tgadh@google.com diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index a1f8de41cfce..d5b8f62aaf2b 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -47,6 +47,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; @@ -160,9 +161,17 @@ public class LockPatternUtils { */ public static final int VERIFY_FLAG_REQUEST_GK_PW_HANDLE = 1 << 0; + /** + * Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the + * method writes the password data to the repair mode file after the credential is verified + * successfully. + */ + public static final int VERIFY_FLAG_WRITE_REPAIR_MODE_PW = 1 << 1; + @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { - VERIFY_FLAG_REQUEST_GK_PW_HANDLE + VERIFY_FLAG_REQUEST_GK_PW_HANDLE, + VERIFY_FLAG_WRITE_REPAIR_MODE_PW }) public @interface VerifyFlag {} @@ -171,6 +180,11 @@ public class LockPatternUtils { */ public static final int USER_FRP = UserHandle.USER_NULL + 1; + /** + * Special user id for triggering the exiting repair mode verification flow. + */ + public static final int USER_REPAIR_MODE = UserHandle.USER_NULL + 2; + public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; @Deprecated public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate"; @@ -200,6 +214,8 @@ public class LockPatternUtils { public static final String CURRENT_LSKF_BASED_PROTECTOR_ID_KEY = "sp-handle"; public static final String PASSWORD_HISTORY_DELIMITER = ","; + private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; + /** * drives the pin auto confirmation feature availability in code logic. */ @@ -388,7 +404,7 @@ public class LockPatternUtils { @UnsupportedAppUsage public void reportFailedPasswordAttempt(int userId) { - if (userId == USER_FRP && frpCredentialEnabled(mContext)) { + if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { return; } getDevicePolicyManager().reportFailedPasswordAttempt(userId); @@ -397,7 +413,7 @@ public class LockPatternUtils { @UnsupportedAppUsage public void reportSuccessfulPasswordAttempt(int userId) { - if (userId == USER_FRP && frpCredentialEnabled(mContext)) { + if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { return; } getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); @@ -405,21 +421,21 @@ public class LockPatternUtils { } public void reportPasswordLockout(int timeoutMs, int userId) { - if (userId == USER_FRP && frpCredentialEnabled(mContext)) { + if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { return; } getTrustManager().reportUnlockLockout(timeoutMs, userId); } public int getCurrentFailedPasswordAttempts(int userId) { - if (userId == USER_FRP && frpCredentialEnabled(mContext)) { + if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { return 0; } return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); } public int getMaximumFailedPasswordsForWipe(int userId) { - if (userId == USER_FRP && frpCredentialEnabled(mContext)) { + if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { return 0; } return getDevicePolicyManager().getMaximumFailedPasswordsForWipe( @@ -739,6 +755,17 @@ public class LockPatternUtils { } } + /** Returns the credential type corresponding to the given PIN or password quality. */ + public static int pinOrPasswordQualityToCredentialType(int quality) { + if (isQualityAlphabeticPassword(quality)) { + return CREDENTIAL_TYPE_PASSWORD; + } + if (isQualityNumericPin(quality)) { + return CREDENTIAL_TYPE_PIN; + } + throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality); + } + /** * Save a new lockscreen credential. * @@ -971,7 +998,7 @@ public class LockPatternUtils { } @Override public boolean shouldBypassCache(Integer userHandle) { - return userHandle == USER_FRP; + return isSpecialUserId(userHandle); } }; @@ -1078,9 +1105,10 @@ public class LockPatternUtils { @UnsupportedAppUsage public long setLockoutAttemptDeadline(int userId, int timeoutMs) { final long deadline = SystemClock.elapsedRealtime() + timeoutMs; - if (userId == USER_FRP) { - // For secure password storage (that is required for FRP), the underlying storage also - // enforces the deadline. Since we cannot store settings for the FRP user, don't. + if (isSpecialUserId(userId)) { + // For secure password storage (that is required for special users such as FRP), the + // underlying storage also enforces the deadline. Since we cannot store settings + // for special users, don't. return deadline; } mLockoutDeadlines.put(userId, deadline); @@ -1819,6 +1847,64 @@ public class LockPatternUtils { } /** + * Return {@code true} if repair mode is supported by the device. + */ + public static boolean isRepairModeSupported(Context context) { + return context.getResources().getBoolean( + com.android.internal.R.bool.config_repairModeSupported); + } + + /** + * Return {@code true} if repair mode is active on the device. + */ + public static boolean isRepairModeActive(Context context) { + return Settings.Global.getInt(context.getContentResolver(), + Settings.Global.REPAIR_MODE_ACTIVE, /* def= */ 0) > 0; + } + + /** + * Return {@code true} if repair mode is supported by the device and the user has been granted + * admin privileges. + */ + public static boolean canUserEnterRepairMode(Context context, UserInfo info) { + return info != null && info.isAdmin() && isRepairModeSupported(context); + } + + /** + * Return {@code true} if GSI is running on the device. + */ + public static boolean isGsiRunning() { + return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; + } + + /** + * Return {@code true} if the given user id is a special user such as {@link #USER_FRP}. + */ + public static boolean isSpecialUserId(int userId) { + return isSpecialUserId(/* context= */ null, userId, /* checkDeviceSupported= */ false); + } + + /** + * Return {@code true} if the given user id is a special user for the verification flow. + * + * @param checkDeviceSupported {@code true} to check the specified user is supported + * by the device. + */ + private static boolean isSpecialUserId(@Nullable Context context, int userId, + boolean checkDeviceSupported) { + switch (userId) { + case USER_FRP: + if (checkDeviceSupported) return frpCredentialEnabled(context); + return true; + + case USER_REPAIR_MODE: + if (checkDeviceSupported) return isRepairModeSupported(context); + return true; + } + return false; + } + + /** * Attempt to rederive the unified work challenge for the specified profile user and unlock the * user. If successful, this would allow the user to leave quiet mode automatically without * additional user authentication. diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index 01dbceb38d3a..afc3cbd15f88 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -16,11 +16,12 @@ #define LOG_TAG "GraphicsEnvironment" -#include <vector> - #include <graphicsenv/GraphicsEnv.h> #include <nativehelper/ScopedUtfChars.h> #include <nativeloader/native_loader.h> + +#include <vector> + #include "core_jni_helpers.h" namespace { @@ -49,11 +50,10 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, appPackageNameChars.c_str(), vulkanVersion); } -void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, - jstring devOptIn, jobjectArray featuresObj) { +void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useSystemAngle, + jstring packageName, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); - ScopedUtfChars appNameChars(env, appName); - ScopedUtfChars devOptInChars(env, devOptIn); + ScopedUtfChars packageNameChars(env, packageName); std::vector<std::string> features; if (featuresObj != nullptr) { @@ -73,13 +73,8 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appNa } } - android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(), - devOptInChars.c_str(), features); -} - -bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) { - ScopedUtfChars appNameChars(env, appName); - return android::GraphicsEnv::getInstance().shouldUseAngle(appNameChars.c_str()); + android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useSystemAngle, + packageNameChars.c_str(), features); } void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) { @@ -123,11 +118,8 @@ const JNINativeMethod g_methods[] = { reinterpret_cast<void*>(setGpuStats_native)}, {"setInjectLayersPrSetDumpable", "()Z", reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)}, - {"setAngleInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", + {"setAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V", reinterpret_cast<void*>(setAngleInfo_native)}, - {"getShouldUseAngle", "(Ljava/lang/String;)Z", - reinterpret_cast<void*>(shouldUseAngle_native)}, {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native)}, {"setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native)}, diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 93048ea4fc85..a872efefed00 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -6467,4 +6467,9 @@ <!-- Whether the AOSP support for app cloning building blocks is to be enabled for the device. --> <bool name="config_enableAppCloningBuildingBlocks">true</bool> + + <!-- Enables or disables support for repair mode. The feature creates a secure + environment to protect the user's privacy when the device is being repaired. + Off by default, since OEMs may have had a similar feature on their devices. --> + <bool name="config_repairModeSupported">false</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9bb338773e53..e81dfe74c2f0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4917,6 +4917,8 @@ <java-symbol type="bool" name="config_safetyProtectionEnabled" /> + <java-symbol type="bool" name="config_repairModeSupported" /> + <java-symbol type="string" name="config_devicePolicyManagementUpdater" /> <java-symbol type="string" name="config_deviceSpecificDeviceStatePolicyProvider" /> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index af8c69ea1441..3a2e50aa06e8 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -54,6 +54,9 @@ <!-- Azerbaijan: 4-5 digits, known premium codes listed --> <shortcode country="az" pattern="\\d{4,5}" premium="330[12]|87744|901[234]|93(?:94|101)|9426|9525" /> + <!-- Bangladesh: 1-5 digits (standard system default, not country specific) --> + <shortcode country="bd" pattern="\\d{1,5}" free="16672" /> + <!-- Belgium: 4 digits, plus EU: http://www.mobileweb.be/en/mobileweb/sms-numberplan.asp --> <shortcode country="be" premium="\\d{4}" free="8\\d{3}|116\\d{3}" /> @@ -145,7 +148,7 @@ <shortcode country="in" pattern="\\d{1,5}" free="59336|53969" /> <!-- Indonesia: 1-5 digits (standard system default, not country specific) --> - <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363" /> + <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363|93457" /> <!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU: http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf --> @@ -190,7 +193,7 @@ <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" /> <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed --> - <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101" /> + <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453" /> <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf --> <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" /> @@ -205,7 +208,7 @@ <shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" /> <!-- New Zealand: 3-4 digits, known premium codes listed --> - <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|176|2141|3067|3068|3110|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" /> + <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|176|2141|3067|3068|3110|3876|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" /> <!-- Peru: 4-5 digits (not confirmed), known premium codes listed --> <shortcode country="pe" pattern="\\d{4,5}" free="9963|40778" /> diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java index 6167c4b80cee..1a668f7bdc8f 100644 --- a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java @@ -37,10 +37,23 @@ public class LockPatternUtilsTest { } @Test + public void testUserRepairMode_isNotRegularUser() { + assertTrue(LockPatternUtils.USER_REPAIR_MODE < 0); + } + + @Test public void testUserFrp_isNotAReservedSpecialUser() throws Exception { assertNotEquals(UserHandle.USER_NULL, LockPatternUtils.USER_FRP); assertNotEquals(UserHandle.USER_ALL, LockPatternUtils.USER_FRP); assertNotEquals(UserHandle.USER_CURRENT, LockPatternUtils.USER_FRP); assertNotEquals(UserHandle.USER_CURRENT_OR_SELF, LockPatternUtils.USER_FRP); } + + @Test + public void testUserRepairMode_isNotAReservedSpecialUser() throws Exception { + assertNotEquals(UserHandle.USER_NULL, LockPatternUtils.USER_REPAIR_MODE); + assertNotEquals(UserHandle.USER_ALL, LockPatternUtils.USER_REPAIR_MODE); + assertNotEquals(UserHandle.USER_CURRENT, LockPatternUtils.USER_REPAIR_MODE); + assertNotEquals(UserHandle.USER_CURRENT_OR_SELF, LockPatternUtils.USER_REPAIR_MODE); + } } diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 96c257b304a0..1ba41b106f56 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -75,16 +75,18 @@ import javax.security.auth.x500.X500Principal; * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey} * interfaces. * - * <p>For asymmetric key pairs, a self-signed X.509 certificate will be also generated and stored in - * the Android Keystore. This is because the {@link java.security.KeyStore} abstraction does not - * support storing key pairs without a certificate. The subject, serial number, and validity dates - * of the certificate can be customized in this spec. The self-signed certificate may be replaced at - * a later time by a certificate signed by a Certificate Authority (CA). + * <p>For asymmetric key pairs, a X.509 certificate will be also generated and stored in the Android + * Keystore. This is because the {@link java.security.KeyStore} abstraction does not support storing + * key pairs without a certificate. The subject, serial number, and validity dates of the + * certificate can be customized in this spec. The certificate may be replaced at a later time by a + * certificate signed by a Certificate Authority (CA). * - * <p>NOTE: If a private key is not authorized to sign the self-signed certificate, then the - * certificate will be created with an invalid signature which will not verify. Such a certificate - * is still useful because it provides access to the public key. To generate a valid signature for - * the certificate the key needs to be authorized for all of the following: + * <p>NOTE: If attestation is not requested using {@link Builder#setAttestationChallenge(byte[])}, + * generated certificate may be self-signed. If a private key is not authorized to sign the + * certificate, then the certificate will be created with an invalid signature which will not + * verify. Such a certificate is still useful because it provides access to the public key. To + * generate a valid signature for the certificate the key needs to be authorized for all of the + * following: * <ul> * <li>{@link KeyProperties#PURPOSE_SIGN},</li> * <li>operation without requiring the user to be authenticated (see @@ -989,12 +991,6 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @param purposes set of purposes (e.g., encrypt, decrypt, sign) for which the key can be * used. Attempts to use the key for any other purpose will be rejected. * - * <p>If the set of purposes for which the key can be used does not contain - * {@link KeyProperties#PURPOSE_SIGN}, the self-signed certificate generated by - * {@link KeyPairGenerator} of {@code AndroidKeyStore} provider will contain an - * invalid signature. This is OK if the certificate is only used for obtaining the - * public key from Android KeyStore. - * * <p>See {@link KeyProperties}.{@code PURPOSE} flags. */ public Builder(@NonNull String keystoreAlias, @KeyProperties.PurposeEnum int purposes) { @@ -1140,7 +1136,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the subject used for the self-signed certificate of the generated key pair. + * Sets the subject used for the certificate of the generated key pair. * * <p>By default, the subject is {@code CN=fake}. */ @@ -1154,7 +1150,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the serial number used for the self-signed certificate of the generated key pair. + * Sets the serial number used for the certificate of the generated key pair. * * <p>By default, the serial number is {@code 1}. */ @@ -1168,8 +1164,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the start of the validity period for the self-signed certificate of the generated - * key pair. + * Sets the start of the validity period for the certificate of the generated key pair. * * <p>By default, this date is {@code Jan 1 1970}. */ @@ -1183,8 +1178,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the end of the validity period for the self-signed certificate of the generated key - * pair. + * Sets the end of the validity period for the certificate of the generated key pair. * * <p>By default, this date is {@code Jan 1 2048}. */ diff --git a/libs/hwui/api/current.txt b/libs/hwui/api/current.txt index 794082124344..c396a2032eed 100644 --- a/libs/hwui/api/current.txt +++ b/libs/hwui/api/current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.graphics { public class ColorMatrix { diff --git a/libs/hwui/api/module-lib-current.txt b/libs/hwui/api/module-lib-current.txt index 14191ebcb080..d802177e249b 100644 --- a/libs/hwui/api/module-lib-current.txt +++ b/libs/hwui/api/module-lib-current.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/module-lib-removed.txt b/libs/hwui/api/module-lib-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/libs/hwui/api/module-lib-removed.txt +++ b/libs/hwui/api/module-lib-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/removed.txt b/libs/hwui/api/removed.txt index 14191ebcb080..d802177e249b 100644 --- a/libs/hwui/api/removed.txt +++ b/libs/hwui/api/removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/system-current.txt b/libs/hwui/api/system-current.txt index 14191ebcb080..d802177e249b 100644 --- a/libs/hwui/api/system-current.txt +++ b/libs/hwui/api/system-current.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/system-removed.txt b/libs/hwui/api/system-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/libs/hwui/api/system-removed.txt +++ b/libs/hwui/api/system-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp index 06ec949e6736..bdd7afeb2f65 100644 --- a/media/tests/MediaFrameworkTest/Android.bp +++ b/media/tests/MediaFrameworkTest/Android.bp @@ -20,7 +20,9 @@ android_test { "androidx.test.ext.junit", "androidx.test.rules", "android-ex-camera2", + "testables", "testng", + "truth", ], jni_libs: [ "libdexmakerjvmtiagent", diff --git a/omapi/aidl/Android.bp b/omapi/aidl/Android.bp index 58bcd1d49c69..e71597a27a39 100644 --- a/omapi/aidl/Android.bp +++ b/omapi/aidl/Android.bp @@ -24,6 +24,11 @@ aidl_interface { backend: { java: { sdk_version: "module_current", + apex_available: [ + "//apex_available:platform", + "com.android.nfcservices", + ], + }, rust: { enabled: true, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 873b434aa4fd..57585e55def0 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -590,6 +590,7 @@ public class SettingsBackupTest { Settings.Global.APPOP_HISTORY_BASE_INTERVAL_MILLIS, Settings.Global.AUTO_REVOKE_PARAMETERS, Settings.Global.ENABLE_RADIO_BUG_DETECTION, + Settings.Global.REPAIR_MODE_ACTIVE, Settings.Global.RADIO_BUG_WAKELOCK_TIMEOUT_COUNT_THRESHOLD, Settings.Global.RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD, Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT, diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f21ad2204d74..579d35ccc9d0 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2712,8 +2712,7 @@ public class OomAdjuster { } } - if (ppr.getLastProviderTime() > 0 - && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) { + if ((ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) { if (adj > PREVIOUS_APP_ADJ) { adj = PREVIOUS_APP_ADJ; schedGroup = SCHED_GROUP_BACKGROUND; diff --git a/services/core/java/com/android/server/am/ProcessProviderRecord.java b/services/core/java/com/android/server/am/ProcessProviderRecord.java index 751e8a821ab1..9b72a3afcfd9 100644 --- a/services/core/java/com/android/server/am/ProcessProviderRecord.java +++ b/services/core/java/com/android/server/am/ProcessProviderRecord.java @@ -34,7 +34,7 @@ final class ProcessProviderRecord { /** * The last time someone else was using a provider in this process. */ - private long mLastProviderTime; + private long mLastProviderTime = Long.MIN_VALUE; /** * class (String) -> ContentProviderRecord. diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java index db341d253818..265ab0496f4d 100644 --- a/services/core/java/com/android/server/am/ProcessStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessStateRecord.java @@ -280,7 +280,7 @@ final class ProcessStateRecord { * The last time the process was in the TOP state or greater. */ @GuardedBy("mService") - private long mLastTopTime; + private long mLastTopTime = Long.MIN_VALUE; /** * Is this an empty background process? diff --git a/services/core/java/com/android/server/biometrics/BiometricCameraManager.java b/services/core/java/com/android/server/biometrics/BiometricCameraManager.java new file mode 100644 index 000000000000..058ea6bbb696 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/BiometricCameraManager.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 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.biometrics; + +/** + * Interface for biometrics to get camera status. + */ +public interface BiometricCameraManager { + /** + * Returns true if any camera is in use. + */ + boolean isAnyCameraUnavailable(); + + /** + * Returns true if privacy is enabled and camera access is disabled. + */ + boolean isCameraPrivacyEnabled(); +} diff --git a/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java b/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java new file mode 100644 index 000000000000..000ee5446962 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 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.biometrics; + +import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; + +import android.annotation.NonNull; +import android.hardware.SensorPrivacyManager; +import android.hardware.camera2.CameraManager; + +import java.util.concurrent.ConcurrentHashMap; + +public class BiometricCameraManagerImpl implements BiometricCameraManager { + + private final CameraManager mCameraManager; + private final SensorPrivacyManager mSensorPrivacyManager; + private final ConcurrentHashMap<String, Boolean> mIsCameraAvailable = new ConcurrentHashMap<>(); + + private final CameraManager.AvailabilityCallback mCameraAvailabilityCallback = + new CameraManager.AvailabilityCallback() { + @Override + public void onCameraAvailable(@NonNull String cameraId) { + mIsCameraAvailable.put(cameraId, true); + } + + @Override + public void onCameraUnavailable(@NonNull String cameraId) { + mIsCameraAvailable.put(cameraId, false); + } + }; + + public BiometricCameraManagerImpl(@NonNull CameraManager cameraManager, + @NonNull SensorPrivacyManager sensorPrivacyManager) { + mCameraManager = cameraManager; + mSensorPrivacyManager = sensorPrivacyManager; + mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, null); + } + + @Override + public boolean isAnyCameraUnavailable() { + for (String cameraId : mIsCameraAvailable.keySet()) { + if (!mIsCameraAvailable.get(cameraId)) { + return true; + } + } + return false; + } + + @Override + public boolean isCameraPrivacyEnabled() { + return mSensorPrivacyManager != null && mSensorPrivacyManager + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, CAMERA); + } +} diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 0942d8527565..e8ffe4feb458 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -33,6 +33,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; +import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; @@ -47,6 +48,7 @@ import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorPropertiesInternal; +import android.hardware.camera2.CameraManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.net.Uri; @@ -124,6 +126,8 @@ public class BiometricService extends SystemService { AuthSession mAuthSession; private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final BiometricCameraManager mBiometricCameraManager; + /** * Tracks authenticatorId invalidation. For more details, see * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}. @@ -933,7 +937,7 @@ public class BiometricService extends SystemService { return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */, - getContext()); + getContext(), mBiometricCameraManager); } /** @@ -1026,6 +1030,11 @@ public class BiometricService extends SystemService { public UserManager getUserManager(Context context) { return context.getSystemService(UserManager.class); } + + public BiometricCameraManager getBiometricCameraManager(Context context) { + return new BiometricCameraManagerImpl(context.getSystemService(CameraManager.class), + context.getSystemService(SensorPrivacyManager.class)); + } } /** @@ -1054,6 +1063,7 @@ public class BiometricService extends SystemService { mRequestCounter = mInjector.getRequestGenerator(); mBiometricContext = injector.getBiometricContext(context); mUserManager = injector.getUserManager(context); + mBiometricCameraManager = injector.getBiometricCameraManager(context); try { injector.getActivityManagerService().registerUserSwitchObserver( @@ -1290,7 +1300,7 @@ public class BiometricService extends SystemService { final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo, opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(), - getContext()); + getContext(), mBiometricCameraManager); final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus(); @@ -1300,9 +1310,7 @@ public class BiometricService extends SystemService { + promptInfo.isIgnoreEnrollmentState()); // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can // be shown for this case. - if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS - || preAuthStatus.second - == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) { + if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) { // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but // CREDENTIAL is requested and available, set the bundle to only request // CREDENTIAL. diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index 3813fd1971a6..b603fcb498be 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -27,7 +27,6 @@ import android.annotation.NonNull; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustManager; import android.content.Context; -import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.PromptInfo; @@ -73,13 +72,16 @@ class PreAuthInfo { final Context context; private final boolean mBiometricRequested; private final int mBiometricStrengthRequested; + private final BiometricCameraManager mBiometricCameraManager; + private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, boolean confirmationRequested, boolean ignoreEnrollmentState, int userId, - Context context) { + Context context, BiometricCameraManager biometricCameraManager) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; + mBiometricCameraManager = biometricCameraManager; this.credentialRequested = credentialRequested; this.eligibleSensors = eligibleSensors; @@ -96,7 +98,8 @@ class PreAuthInfo { BiometricService.SettingObserver settingObserver, List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, String opPackageName, - boolean checkDevicePolicyManager, Context context) + boolean checkDevicePolicyManager, Context context, + BiometricCameraManager biometricCameraManager) throws RemoteException { final boolean confirmationRequested = promptInfo.isConfirmationRequested(); @@ -124,7 +127,7 @@ class PreAuthInfo { checkDevicePolicyManager, requestedStrength, promptInfo.getAllowedSensorIds(), promptInfo.isIgnoreEnrollmentState(), - context); + biometricCameraManager); Slog.d(TAG, "Package: " + opPackageName + " Sensor ID: " + sensor.id @@ -138,7 +141,7 @@ class PreAuthInfo { // // Note: if only a certain sensor is required and the privacy is enabled, // canAuthenticate() will return false. - if (status == AUTHENTICATOR_OK || status == BIOMETRIC_SENSOR_PRIVACY_ENABLED) { + if (status == AUTHENTICATOR_OK) { eligibleSensors.add(sensor); } else { ineligibleSensors.add(new Pair<>(sensor, status)); @@ -148,7 +151,7 @@ class PreAuthInfo { return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested, - promptInfo.isIgnoreEnrollmentState(), userId, context); + promptInfo.isIgnoreEnrollmentState(), userId, context, biometricCameraManager); } /** @@ -165,12 +168,16 @@ class PreAuthInfo { BiometricSensor sensor, int userId, String opPackageName, boolean checkDevicePolicyManager, int requestedStrength, @NonNull List<Integer> requestedSensorIds, - boolean ignoreEnrollmentState, Context context) { + boolean ignoreEnrollmentState, BiometricCameraManager biometricCameraManager) { if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) { return BIOMETRIC_NO_HARDWARE; } + if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) { + return BIOMETRIC_HARDWARE_NOT_DETECTED; + } + final boolean wasStrongEnough = Utils.isAtLeastStrength(sensor.oemStrength, requestedStrength); final boolean isStrongEnough = @@ -191,12 +198,10 @@ class PreAuthInfo { && !ignoreEnrollmentState) { return BIOMETRIC_NOT_ENROLLED; } - final SensorPrivacyManager sensorPrivacyManager = context - .getSystemService(SensorPrivacyManager.class); - if (sensorPrivacyManager != null && sensor.modality == TYPE_FACE) { - if (sensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId)) { + if (biometricCameraManager != null && sensor.modality == TYPE_FACE) { + if (biometricCameraManager.isCameraPrivacyEnabled()) { + //Camera privacy is enabled as the access is disabled return BIOMETRIC_SENSOR_PRIVACY_ENABLED; } } @@ -292,13 +297,9 @@ class PreAuthInfo { @AuthenticatorStatus final int status; @BiometricAuthenticator.Modality int modality = TYPE_NONE; - final SensorPrivacyManager sensorPrivacyManager = context - .getSystemService(SensorPrivacyManager.class); - boolean cameraPrivacyEnabled = false; - if (sensorPrivacyManager != null) { - cameraPrivacyEnabled = sensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId); + if (mBiometricCameraManager != null) { + cameraPrivacyEnabled = mBiometricCameraManager.isCameraPrivacyEnabled(); } if (mBiometricRequested && credentialRequested) { @@ -315,7 +316,7 @@ class PreAuthInfo { // and the face sensor privacy is enabled then return // BIOMETRIC_SENSOR_PRIVACY_ENABLED. // - // Note: This sensor will still be eligible for calls to authenticate. + // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; @@ -340,7 +341,7 @@ class PreAuthInfo { // If the only modality requested is face and the privacy is enabled // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED. // - // Note: This sensor will still be eligible for calls to authenticate. + // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 83e90b987ef5..f92d46ce502d 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -31,7 +31,6 @@ import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_SYSTEM; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; -import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN; import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY; @@ -40,8 +39,12 @@ import static com.android.internal.widget.LockPatternUtils.PIN_LENGTH_UNAVAILABL import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE; import static com.android.internal.widget.LockPatternUtils.USER_FRP; +import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE; import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE; +import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW; import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; +import static com.android.internal.widget.LockPatternUtils.isSpecialUserId; +import static com.android.internal.widget.LockPatternUtils.pinOrPasswordQualityToCredentialType; import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_STRONG; import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_WEAK; @@ -312,8 +315,6 @@ public class LockSettingsService extends ILockSettings.Stub { protected IGateKeeperService mGateKeeperService; protected IAuthSecret mAuthSecretService; - private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; - /** * The UIDs that are used for system credential storage in keystore. */ @@ -344,6 +345,8 @@ public class LockSettingsService extends ILockSettings.Stub { super.onBootPhase(phase); if (phase == PHASE_ACTIVITY_MANAGER_READY) { mLockSettingsService.migrateOldDataAfterSystemReady(); + mLockSettingsService.deleteRepairModePersistentDataIfNeeded(); + } else if (phase == PHASE_BOOT_COMPLETED) { mLockSettingsService.loadEscrowData(); } } @@ -575,7 +578,7 @@ public class LockSettingsService extends ILockSettings.Stub { } public boolean isGsiRunning() { - return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; + return LockPatternUtils.isGsiRunning(); } public FingerprintManager getFingerprintManager() { @@ -983,6 +986,16 @@ public class LockSettingsService extends ILockSettings.Stub { return success; } + @VisibleForTesting + void deleteRepairModePersistentDataIfNeeded() { + if (!LockPatternUtils.isRepairModeSupported(mContext) + || LockPatternUtils.isRepairModeActive(mContext) + || mInjector.isGsiRunning()) { + return; + } + mStorage.deleteRepairModePersistentData(); + } + // This is called when Weaver is guaranteed to be available (if the device supports Weaver). // It does any synthetic password related work that was delayed from earlier in the boot. private void onThirdPartyAppsStarted() { @@ -1309,8 +1322,8 @@ public class LockSettingsService extends ILockSettings.Stub { * {@link #CREDENTIAL_TYPE_PASSWORD} */ private int getCredentialTypeInternal(int userId) { - if (userId == USER_FRP) { - return getFrpCredentialType(); + if (isSpecialUserId(userId)) { + return mSpManager.getSpecialUserCredentialType(userId); } synchronized (mSpManager) { final long protectorId = getCurrentLskfBasedProtectorId(userId); @@ -1326,29 +1339,6 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private int getFrpCredentialType() { - PersistentData data = mStorage.readPersistentDataBlock(); - if (data.type != PersistentData.TYPE_SP_GATEKEEPER && - data.type != PersistentData.TYPE_SP_WEAVER) { - return CREDENTIAL_TYPE_NONE; - } - int credentialType = SyntheticPasswordManager.getFrpCredentialType(data.payload); - if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) { - return credentialType; - } - return pinOrPasswordQualityToCredentialType(data.qualityForUi); - } - - private static int pinOrPasswordQualityToCredentialType(int quality) { - if (LockPatternUtils.isQualityAlphabeticPassword(quality)) { - return CREDENTIAL_TYPE_PASSWORD; - } - if (LockPatternUtils.isQualityNumericPin(quality)) { - return CREDENTIAL_TYPE_PIN; - } - throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality); - } - private boolean isUserSecure(int userId) { return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE; } @@ -1590,8 +1580,8 @@ public class LockSettingsService extends ILockSettings.Stub { * unlock operation. */ private void sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId) { - // Don't send credentials during the factory reset protection flow. - if (userId == USER_FRP) { + // Don't send credentials during the special user flow. + if (isSpecialUserId(userId)) { return; } @@ -2213,15 +2203,19 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; } + if (userId == USER_REPAIR_MODE && !LockPatternUtils.isRepairModeActive(mContext)) { + Slog.e(TAG, "Repair mode is not active on the device."); + return VerifyCredentialResponse.ERROR; + } Slogf.i(TAG, "Verifying lockscreen credential for user %d", userId); final AuthenticationResult authResult; VerifyCredentialResponse response; synchronized (mSpManager) { - if (userId == USER_FRP) { - return mSpManager.verifyFrpCredential(getGateKeeperService(), credential, - progressCallback); + if (isSpecialUserId(userId)) { + return mSpManager.verifySpecialUserCredential(userId, getGateKeeperService(), + credential, progressCallback); } long protectorId = getCurrentLskfBasedProtectorId(userId); @@ -2230,6 +2224,12 @@ public class LockSettingsService extends ILockSettings.Stub { response = authResult.gkResponse; if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + if ((flags & VERIFY_FLAG_WRITE_REPAIR_MODE_PW) != 0) { + if (!mSpManager.writeRepairModeCredentialLocked(protectorId, userId)) { + Slog.e(TAG, "Failed to write repair mode credential"); + return VerifyCredentialResponse.ERROR; + } + } // credential has matched mBiometricDeferredQueue.addPendingLockoutResetForUser(userId, authResult.syntheticPassword.deriveGkPassword()); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 18f84c03d04f..1e8b387fc189 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -19,7 +19,7 @@ package com.android.server.locksettings; import static android.content.Context.USER_SERVICE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; -import static com.android.internal.widget.LockPatternUtils.USER_FRP; +import static com.android.internal.widget.LockPatternUtils.isSpecialUserId; import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; @@ -90,6 +90,9 @@ class LockSettingsStorage { private static final String SYNTHETIC_PASSWORD_DIRECTORY = "spblob/"; + private static final String REPAIR_MODE_DIRECTORY = "repair-mode/"; + private static final String REPAIR_MODE_PERSISTENT_FILE = "pst"; + private static final Object DEFAULT = new Object(); private static final String[] SETTINGS_TO_BACKUP = new String[] { @@ -390,6 +393,29 @@ class LockSettingsStorage { } } + @VisibleForTesting + File getRepairModePersistentDataFile() { + final File directory = new File(Environment.getMetadataDirectory(), REPAIR_MODE_DIRECTORY); + return new File(directory, REPAIR_MODE_PERSISTENT_FILE); + } + + public PersistentData readRepairModePersistentData() { + final byte[] data = readFile(getRepairModePersistentDataFile()); + if (data == null) { + return PersistentData.NONE; + } + return PersistentData.fromBytes(data); + } + + public void writeRepairModePersistentData(int persistentType, int userId, byte[] payload) { + writeFile(getRepairModePersistentDataFile(), + PersistentData.toBytes(persistentType, userId, /* qualityForUi= */0, payload)); + } + + public void deleteRepairModePersistentData() { + deleteFile(getRepairModePersistentDataFile()); + } + /** * Writes the synthetic password state file for the given user ID, protector ID, and state name. * If the file already exists, then it is atomically replaced. @@ -510,7 +536,8 @@ class LockSettingsStorage { } public void setString(String key, String value, int userId) { - Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user"); + Preconditions.checkArgument(!isSpecialUserId(userId), + "cannot store lock settings for special user: %d", userId); writeKeyValue(key, value, userId); if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) { @@ -535,7 +562,7 @@ class LockSettingsStorage { } public String getString(String key, String defaultValue, int userId) { - if (userId == USER_FRP) { + if (isSpecialUserId(userId)) { return null; } return readKeyValue(key, defaultValue, userId); @@ -583,6 +610,17 @@ class LockSettingsStorage { } } + /** + * Provides a concrete data structure to represent the minimal information from + * a user's LSKF-based SP protector that is needed to verify the user's LSKF, + * in combination with the corresponding Gatekeeper enrollment or Weaver slot. + * It can be stored in {@link com.android.server.PersistentDataBlockService} for + * FRP to live across factory resets not initiated via the Settings UI. + * Written to {@link #REPAIR_MODE_PERSISTENT_FILE} to support verification for + * exiting repair mode, since the device runs with an empty data partition in + * repair mode and the same credential be provided to exit repair mode is + * required. + */ public static class PersistentData { static final byte VERSION_1 = 1; static final int VERSION_1_HEADER_SIZE = 1 + 1 + 4 + 4; @@ -685,6 +723,19 @@ class LockSettingsStorage { } pw.decreaseIndent(); } + // Dump repair mode file states + final File repairModeFile = getRepairModePersistentDataFile(); + if (repairModeFile.exists()) { + pw.println(TextUtils.formatSimple("Repair Mode [%s]:", repairModeFile.getParent())); + pw.increaseIndent(); + pw.println(TextUtils.formatSimple("%6d %s %s", repairModeFile.length(), + LockSettingsService.timestampToString(repairModeFile.lastModified()), + repairModeFile.getName())); + final PersistentData data = readRepairModePersistentData(); + pw.println(TextUtils.formatSimple("type: %d, user id: %d, payload size: %d", + data.type, data.userId, data.payload != null ? data.payload.length : 0)); + pw.decreaseIndent(); + } } static class DatabaseHelper extends SQLiteOpenHelper { diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 3d3703aa6b01..8e9c21f5f35f 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -16,9 +16,14 @@ package com.android.server.locksettings; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN; import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; import static com.android.internal.widget.LockPatternUtils.PIN_LENGTH_UNAVAILABLE; +import static com.android.internal.widget.LockPatternUtils.USER_FRP; +import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE; +import static com.android.internal.widget.LockPatternUtils.pinOrPasswordQualityToCredentialType; import android.annotation.IntDef; import android.annotation.NonNull; @@ -768,11 +773,30 @@ class SyntheticPasswordManager { return PasswordData.fromBytes(passwordData).credentialType; } - static int getFrpCredentialType(byte[] payload) { - if (payload == null) { + int getSpecialUserCredentialType(int userId) { + final PersistentData data = getSpecialUserPersistentData(userId); + if (data.type != PersistentData.TYPE_SP_GATEKEEPER + && data.type != PersistentData.TYPE_SP_WEAVER) { + return CREDENTIAL_TYPE_NONE; + } + if (data.payload == null) { return LockPatternUtils.CREDENTIAL_TYPE_NONE; } - return PasswordData.fromBytes(payload).credentialType; + final int credentialType = PasswordData.fromBytes(data.payload).credentialType; + if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) { + return credentialType; + } + return pinOrPasswordQualityToCredentialType(data.qualityForUi); + } + + private PersistentData getSpecialUserPersistentData(int userId) { + if (userId == USER_FRP) { + return mStorage.readPersistentDataBlock(); + } + if (userId == USER_REPAIR_MODE) { + return mStorage.readRepairModePersistentData(); + } + throw new IllegalArgumentException("Unknown special user id " + userId); } /** @@ -1057,10 +1081,10 @@ class SyntheticPasswordManager { return sizeOfCredential; } - public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper, - LockscreenCredential userCredential, + public VerifyCredentialResponse verifySpecialUserCredential(int sourceUserId, + IGateKeeperService gatekeeper, LockscreenCredential userCredential, ICheckCredentialProgressCallback progressCallback) { - PersistentData persistentData = mStorage.readPersistentDataBlock(); + final PersistentData persistentData = getSpecialUserPersistentData(sourceUserId); if (persistentData.type == PersistentData.TYPE_SP_GATEKEEPER) { PasswordData pwd = PasswordData.fromBytes(persistentData.payload); byte[] stretchedLskf = stretchLskf(userCredential, pwd); @@ -1071,14 +1095,14 @@ class SyntheticPasswordManager { 0 /* challenge */, pwd.passwordHandle, stretchedLskfToGkPassword(stretchedLskf)); } catch (RemoteException e) { - Slog.e(TAG, "FRP verifyChallenge failed", e); + Slog.e(TAG, "Persistent data credential verifyChallenge failed", e); return VerifyCredentialResponse.ERROR; } return VerifyCredentialResponse.fromGateKeeperResponse(response); } else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) { final IWeaver weaver = getWeaverService(); if (weaver == null) { - Slog.e(TAG, "No weaver service to verify SP-based FRP credential"); + Slog.e(TAG, "No weaver service to verify SP-based persistent data credential"); return VerifyCredentialResponse.ERROR; } PasswordData pwd = PasswordData.fromBytes(persistentData.payload); @@ -1168,6 +1192,57 @@ class SyntheticPasswordManager { } } + /** + * Writes the user's synthetic password data to the repair mode file. + * + * @param protectorId current LSKF based protectorId + * @param userId user id of the user + */ + public boolean writeRepairModeCredentialLocked(long protectorId, int userId) { + if (!shouldWriteRepairModeCredential(userId)) { + return false; + } + final byte[] data = loadState(PASSWORD_DATA_NAME, protectorId, userId); + if (data == null) { + Slogf.w(TAG, "Password data not found for user %d", userId); + return false; + } + final PasswordData pwd = PasswordData.fromBytes(data); + if (isNoneCredential(pwd)) { + Slogf.w(TAG, "User %d has NONE credential", userId); + return false; + } + Slogf.d(TAG, "Writing repair mode credential tied to user %d", userId); + final int weaverSlot = loadWeaverSlot(protectorId, userId); + if (weaverSlot != INVALID_WEAVER_SLOT) { + // write weaver password + mStorage.writeRepairModePersistentData( + PersistentData.TYPE_SP_WEAVER, weaverSlot, pwd.toBytes()); + } else { + // write gatekeeper password + mStorage.writeRepairModePersistentData( + PersistentData.TYPE_SP_GATEKEEPER, userId, pwd.toBytes()); + } + return true; + } + + private boolean shouldWriteRepairModeCredential(int userId) { + final UserInfo userInfo = mUserManager.getUserInfo(userId); + if (!LockPatternUtils.canUserEnterRepairMode(mContext, userInfo)) { + Slogf.w(TAG, "User %d can't enter repair mode", userId); + return false; + } + if (LockPatternUtils.isRepairModeActive(mContext)) { + Slog.w(TAG, "Can't write repair mode credential while repair mode is already active"); + return false; + } + if (LockPatternUtils.isGsiRunning()) { + Slog.w(TAG, "Can't write repair mode credential while GSI is running"); + return false; + } + return true; + } + private ArrayMap<Integer, ArrayMap<Long, TokenData>> tokenMap = new ArrayMap<>(); /** diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java index ec0d9856486d..77a60289d7a9 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java @@ -123,7 +123,7 @@ public class KeySyncTask implements Runnable { * @param userId The uid of the user whose profile has been unlocked. * @param credentialType The type of credential as defined in {@code LockPatternUtils} * @param credential The credential, encoded as a byte array - * @param credentialUpdated signals weather credentials were updated. + * @param credentialUpdated indicates credentials change. * @param platformKeyManager platform key manager * @param testOnlyInsecureCertificateHelper utility class used for end-to-end tests */ @@ -143,7 +143,7 @@ public class KeySyncTask implements Runnable { mRecoverableKeyStoreDb = recoverableKeyStoreDb; mUserId = userId; mCredentialType = credentialType; - mCredential = credential; + mCredential = credential != null ? Arrays.copyOf(credential, credential.length) : null; mCredentialUpdated = credentialUpdated; mPlatformKeyManager = platformKeyManager; mRecoverySnapshotStorage = snapshotStorage; @@ -160,6 +160,10 @@ public class KeySyncTask implements Runnable { } } catch (Exception e) { Log.e(TAG, "Unexpected exception thrown during KeySyncTask", e); + } finally { + if (mCredential != null) { + Arrays.fill(mCredential, (byte) 0); // no longer needed. + } } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java index 7009a41726e2..ce3fb850b517 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java @@ -166,6 +166,7 @@ public class PlatformKeyManager { * @param userId The ID of the user to whose lock screen the platform key must be bound. * @throws NoSuchAlgorithmException if AES is unavailable - should never happen. * @throws KeyStoreException if there is an error in AndroidKeyStore. + * @throws InsecureUserException if the user does not have a lock screen set. * @throws IOException if there was an issue with local database update. * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}. * @@ -174,7 +175,7 @@ public class PlatformKeyManager { @VisibleForTesting void regenerate(int userId) throws NoSuchAlgorithmException, KeyStoreException, IOException, - RemoteException { + RemoteException, InsecureUserException { int generationId = getGenerationId(userId); int nextId; if (generationId == -1) { @@ -195,13 +196,14 @@ public class PlatformKeyManager { * @throws UnrecoverableKeyException if the key could not be recovered. * @throws NoSuchAlgorithmException if AES is unavailable - should never occur. * @throws IOException if there was an issue with local database update. + * @throws InsecureUserException if the user does not have a lock screen set. * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}. * * @hide */ public PlatformEncryptionKey getEncryptKey(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, - IOException, RemoteException { + IOException, RemoteException, InsecureUserException { init(userId); try { // Try to see if the decryption key is still accessible before using the encryption key. @@ -254,7 +256,7 @@ public class PlatformKeyManager { */ public PlatformDecryptionKey getDecryptKey(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, - IOException, RemoteException { + IOException, InsecureUserException, RemoteException { init(userId); try { PlatformDecryptionKey decryptionKey = getDecryptKeyInternal(userId); @@ -328,7 +330,7 @@ public class PlatformKeyManager { */ void init(int userId) throws KeyStoreException, NoSuchAlgorithmException, IOException, - RemoteException { + RemoteException, InsecureUserException { int generationId = getGenerationId(userId); if (isKeyLoaded(userId, generationId)) { Log.i(TAG, String.format( @@ -414,7 +416,8 @@ public class PlatformKeyManager { * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}. */ private void generateAndLoadKey(int userId, int generationId) - throws NoSuchAlgorithmException, KeyStoreException, IOException, RemoteException { + throws NoSuchAlgorithmException, KeyStoreException, IOException, RemoteException, + InsecureUserException { String encryptAlias = getEncryptAlias(userId, generationId); String decryptAlias = getDecryptAlias(userId, generationId); // SecretKey implementation doesn't provide reliable way to destroy the secret @@ -427,23 +430,31 @@ public class PlatformKeyManager { .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE); // Skip UserAuthenticationRequired for main user if (userId == UserHandle.USER_SYSTEM) { + // attempt to store key will fail if screenlock is not set. decryptionKeyProtection.setUnlockedDeviceRequired(true); } else { // Don't set protection params to prevent losing key. } // Store decryption key first since it is more likely to fail. - mKeyStore.setEntry( - decryptAlias, - new KeyStore.SecretKeyEntry(secretKey), - decryptionKeyProtection.build()); - mKeyStore.setEntry( - encryptAlias, - new KeyStore.SecretKeyEntry(secretKey), - new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT) - .setBlockModes(KeyProperties.BLOCK_MODE_GCM) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) - .build()); - + try { + mKeyStore.setEntry( + decryptAlias, + new KeyStore.SecretKeyEntry(secretKey), + decryptionKeyProtection.build()); + mKeyStore.setEntry( + encryptAlias, + new KeyStore.SecretKeyEntry(secretKey), + new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .build()); + } catch (KeyStoreException e) { + if (!isDeviceSecure(userId)) { + throw new InsecureUserException("Screenlock is not set"); + } else { + throw e; + } + } setGenerationId(userId, generationId); } @@ -477,4 +488,8 @@ public class PlatformKeyManager { return keyStore; } + private boolean isDeviceSecure(int userId) { + return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId); + } + } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index 24dbce49eace..10b6052bec69 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -19,6 +19,7 @@ package com.android.server.locksettings.recoverablekeystore; import static android.security.keystore.recovery.RecoveryController.ERROR_BAD_CERTIFICATE_FORMAT; import static android.security.keystore.recovery.RecoveryController.ERROR_DECRYPTION_FAILED; import static android.security.keystore.recovery.RecoveryController.ERROR_DOWNGRADE_CERTIFICATE; +import static android.security.keystore.recovery.RecoveryController.ERROR_INSECURE_USER; import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_CERTIFICATE; import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_KEY_FORMAT; import static android.security.keystore.recovery.RecoveryController.ERROR_NO_SNAPSHOT_PENDING; @@ -194,8 +195,12 @@ public class RecoverableKeyStoreManager { mApplicationKeyStorage = applicationKeyStorage; mTestCertHelper = testOnlyInsecureCertificateHelper; mCleanupManager = cleanupManager; - // Clears data for removed users. - mCleanupManager.verifyKnownUsers(); + try { + // Clears data for removed users. + mCleanupManager.verifyKnownUsers(); + } catch (Exception e) { + Log.e(TAG, "Failed to verify known users", e); + } try { mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase); } catch (NoSuchAlgorithmException e) { @@ -750,6 +755,8 @@ public class RecoverableKeyStoreManager { throw new RuntimeException(e); } catch (KeyStoreException | UnrecoverableKeyException | IOException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); + } catch (InsecureUserException e) { + throw new ServiceSpecificException(ERROR_INSECURE_USER, e.getMessage()); } try { @@ -817,6 +824,8 @@ public class RecoverableKeyStoreManager { throw new RuntimeException(e); } catch (KeyStoreException | UnrecoverableKeyException | IOException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); + } catch (InsecureUserException e) { + throw new ServiceSpecificException(ERROR_INSECURE_USER, e.getMessage()); } try { diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java index 06db6b8a38f8..ef56a1e26854 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java @@ -138,7 +138,7 @@ public class ApplicationKeyStorage { } catch (android.security.KeyStoreException e) { if (e.getNumericErrorCode() == android.security.KeyStoreException.ERROR_KEY_DOES_NOT_EXIST) { - Log.e(TAG, "Failed to get grant for KeyStore key - key not found", e); + Log.w(TAG, "Failed to get grant for KeyStore key - key not found"); throw new ServiceSpecificException(ERROR_KEY_NOT_FOUND, e.getMessage()); } Log.e(TAG, "Failed to get grant for KeyStore key.", e); diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java index 36adea7e0112..a5a934f78420 100644 --- a/services/core/java/com/android/server/net/NetworkManagementService.java +++ b/services/core/java/com/android/server/net/NetworkManagementService.java @@ -75,7 +75,6 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.HexDump; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.NetdUtils; -import com.android.net.module.util.NetdUtils.ModifyOperation; import com.android.net.module.util.PermissionUtils; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -758,18 +757,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } } - @Override - public void addRoute(int netId, RouteInfo route) { - PermissionUtils.enforceNetworkStackPermission(mContext); - NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route); - } - - @Override - public void removeRoute(int netId, RouteInfo route) { - PermissionUtils.enforceNetworkStackPermission(mContext); - NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route); - } - @android.annotation.EnforcePermission(android.Manifest.permission.SHUTDOWN) @Override public void shutdown() { diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS index 174ad3ad2e25..c33f3d9fa264 100644 --- a/services/core/java/com/android/server/stats/OWNERS +++ b/services/core/java/com/android/server/stats/OWNERS @@ -1,11 +1,10 @@ jeffreyhuang@google.com joeo@google.com -jtnguyen@google.com +monicamwang@google.com muhammadq@google.com +rayhdez@google.com rslawik@google.com -ruchirr@google.com sharaienko@google.com singhtejinder@google.com tsaichristine@google.com yaochen@google.com -yro@google.com diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index f6c364008c62..f8c39d0906a0 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -16,6 +16,7 @@ lihongyu@google.com mariiasand@google.com rgl@google.com yunfanc@google.com +wilsonshih@google.com per-file BackgroundActivityStartController.java = set noparent per-file BackgroundActivityStartController.java = brufino@google.com, topjohnwu@google.com, achim@google.com, ogunwale@google.com, louischang@google.com, lus@google.com diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index c6a914b37206..ccbaf78bfc95 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -2530,7 +2530,7 @@ public class MockingOomAdjusterTests { PROCESS_STATE_NONEXISTENT, PROCESS_STATE_NONEXISTENT, 0, 0, false, false, false, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE, false, false, false, hasShownUi, false, false, false, false, false, false, null, - 0, 0, 0, true, 0, null, false); + 0, Long.MIN_VALUE, Long.MIN_VALUE, true, 0, null, false); } private ProcessRecord makeProcessRecord(ActivityManagerService service, int pid, int uid, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java index 662477ddbbe9..2aabb1bc24b2 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java @@ -104,6 +104,7 @@ public class AuthSessionTest { @Mock private KeyStore mKeyStore; @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver; @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger; + @Mock private BiometricCameraManager mBiometricCameraManager; private Random mRandom; private IBinder mToken; @@ -571,7 +572,8 @@ public class AuthSessionTest { promptInfo, TEST_PACKAGE, checkDevicePolicyManager, - mContext); + mContext, + mBiometricCameraManager); } private AuthSession createAuthSession(List<BiometricSensor> sensors, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index 67be37616d5f..6f4791af43f0 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -152,6 +152,8 @@ public class BiometricServiceTest { private AuthSessionCoordinator mAuthSessionCoordinator; @Mock private UserManager mUserManager; + @Mock + private BiometricCameraManager mBiometricCameraManager; BiometricContextProvider mBiometricContextProvider; @@ -178,6 +180,7 @@ public class BiometricServiceTest { when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager); when(mInjector.getRequestGenerator()).thenReturn(() -> TEST_REQUEST_ID); when(mInjector.getUserManager(any())).thenReturn(mUserManager); + when(mInjector.getBiometricCameraManager(any())).thenReturn(mBiometricCameraManager); when(mResources.getString(R.string.biometric_error_hw_unavailable)) .thenReturn(ERROR_HW_UNAVAILABLE); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java new file mode 100644 index 000000000000..c2bdf501198e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2023 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.biometrics; + +import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; + +import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import android.app.admin.DevicePolicyManager; +import android.app.trust.ITrustManager; +import android.content.Context; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.IBiometricAuthenticator; +import android.hardware.biometrics.PromptInfo; +import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +@Presubmit +@SmallTest +public class PreAuthInfoTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private static final int SENSOR_ID_FACE = 1; + private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage"; + + @Mock + IBiometricAuthenticator mFaceAuthenticator; + @Mock + Context mContext; + @Mock + ITrustManager mTrustManager; + @Mock + DevicePolicyManager mDevicePolicyManager; + @Mock + BiometricService.SettingObserver mSettingObserver; + @Mock + BiometricCameraManager mBiometricCameraManager; + + @Before + public void setup() throws RemoteException { + when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); + when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt())) + .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE); + when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); + when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); + when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); + when(mFaceAuthenticator.getLockoutModeForUser(anyInt())) + .thenReturn(LOCKOUT_NONE); + when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(false); + when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(false); + } + + @Test + public void testFaceAuthentication_whenCameraPrivacyIsEnabled() throws Exception { + when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(true); + + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).isEmpty(); + } + + @Test + public void testFaceAuthentication_whenCameraPrivacyIsDisabledAndCameraIsAvailable() + throws Exception { + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).hasSize(1); + } + + @Test + public void testFaceAuthentication_whenCameraIsUnavailable() throws RemoteException { + when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(true); + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).hasSize(0); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index e960e995f6ce..fe2ac176949d 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -254,6 +254,8 @@ public abstract class BaseLockSettingsServiceTests { .thenReturn(true); when(res.getBoolean(eq(com.android.internal.R.bool.config_strongAuthRequiredOnBoot))) .thenReturn(true); + when(res.getBoolean(eq(com.android.internal.R.bool.config_repairModeSupported))) + .thenReturn(true); return res; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java index cfb3b3497745..fa3c7a4c4769 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java @@ -84,6 +84,11 @@ public class LockSettingsStorageTestable extends LockSettingsStorage { } @Override + File getRepairModePersistentDataFile() { + return remapToStorageDir(super.getRepairModePersistentDataFile()); + } + + @Override PersistentDataBlockManagerInternal getPersistentDataBlockManager() { return mPersistentDataBlockManager; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java index 39e2792a3a34..02b86db6ab6f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java @@ -457,6 +457,31 @@ public class LockSettingsStorageTests { assertEquals(2, PersistentData.TYPE_SP_WEAVER); } + @Test + public void testRepairMode_emptyPersistentData() { + assertSame(PersistentData.NONE, mStorage.readPersistentDataBlock()); + } + + @Test + public void testRepairMode_writeGatekeeperPersistentData() { + mStorage.writeRepairModePersistentData( + PersistentData.TYPE_SP_GATEKEEPER, SOME_USER_ID, PAYLOAD); + + final PersistentData data = mStorage.readRepairModePersistentData(); + assertEquals(PersistentData.TYPE_SP_GATEKEEPER, data.type); + assertArrayEquals(PAYLOAD, data.payload); + } + + @Test + public void testRepairMode_writeWeaverPersistentData() { + mStorage.writeRepairModePersistentData( + PersistentData.TYPE_SP_WEAVER, SOME_USER_ID, PAYLOAD); + + final PersistentData data = mStorage.readRepairModePersistentData(); + assertEquals(PersistentData.TYPE_SP_WEAVER, data.type); + assertArrayEquals(PAYLOAD, data.payload); + } + private static void assertArrayEquals(byte[] expected, byte[] actual) { if (!Arrays.equals(expected, actual)) { fail("expected:<" + Arrays.toString(expected) + diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java new file mode 100644 index 000000000000..70150c507460 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2023 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.locksettings; + +import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE; +import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import android.app.PropertyInvalidatedCache; +import android.platform.test.annotations.Presubmit; +import android.provider.Settings; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.VerifyCredentialResponse; +import com.android.server.locksettings.LockSettingsStorage.PersistentData; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class LockscreenRepairModeTest extends BaseLockSettingsServiceTests { + + @Before + public void setUp() throws Exception { + PropertyInvalidatedCache.disableForTestMode(); + mService.initializeSyntheticPassword(PRIMARY_USER_ID); + } + + @Test + public void verifyPin_writeRepairModePW() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN, + mService.getCredentialType(USER_REPAIR_MODE)); + } + + @Test + public void verifyPattern_writeRepairModePW() { + mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPattern("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN, + mService.getCredentialType(USER_REPAIR_MODE)); + } + + @Test + public void verifyPassword_writeRepairModePW() { + mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPassword("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + mService.getCredentialType(USER_REPAIR_MODE)); + } + + @Test + public void verifyCredential_writeRepairModePW_repairModeActive() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + + setRepairModeActive(true); + assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + } + + @Test + public void deleteRepairModePersistentData() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN, + mService.getCredentialType(USER_REPAIR_MODE)); + + mService.deleteRepairModePersistentDataIfNeeded(); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + } + + @Test + public void verifyPin_userRepairMode() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + setRepairModeActive(true); + + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN, + mService.getCredentialType(USER_REPAIR_MODE)); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential(newPin("1234"), USER_REPAIR_MODE, 0 /* flags */) + .getResponseCode()); + } + + @Test + public void verifyPattern_userRepairMode() { + mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPattern("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + setRepairModeActive(true); + + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN, + mService.getCredentialType(USER_REPAIR_MODE)); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential(newPattern("4321"), USER_REPAIR_MODE, 0 /* flags */) + .getResponseCode()); + } + + @Test + public void verifyPassword_userRepairMode() { + mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPassword("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + setRepairModeActive(true); + + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + mService.getCredentialType(USER_REPAIR_MODE)); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential(newPassword("4321"), USER_REPAIR_MODE, 0 /* flags */) + .getResponseCode()); + } + + @Test + public void verifyCredential_userRepairMode_repairModeIsNotActive() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN, + mService.getCredentialType(USER_REPAIR_MODE)); + assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, + mService.verifyCredential(newPin("1234"), USER_REPAIR_MODE, 0 /* flags */) + .getResponseCode()); + } + + @Test + public void verifyCredential_userRepairMode_wrongPin() { + mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID); + assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData()); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, + mService.verifyCredential( + newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW) + .getResponseCode()); + setRepairModeActive(true); + + assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN, + mService.getCredentialType(USER_REPAIR_MODE)); + assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, + mService.verifyCredential(newPin("5678"), USER_REPAIR_MODE, 0 /* flags */) + .getResponseCode()); + } + + private void setRepairModeActive(boolean active) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.REPAIR_MODE_ACTIVE, active ? 1 : 0); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index 5654c89196f2..80fb5e3f950d 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -36,6 +36,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -297,13 +298,15 @@ public class KeySyncTaskTest { TestData.getInsecureCertPathForEndpoint1()); addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, appKeyAlias); + setExpectedScryptArgument(password.getBytes()); + mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1); assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()). isEqualTo(UI_FORMAT_PASSWORD); - verify(mMockScrypt).scrypt(eq(password.getBytes()), any(), + verify(mMockScrypt).scrypt(any(), any(), eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); KeyDerivationParams keyDerivationParams = @@ -314,6 +317,44 @@ public class KeySyncTaskTest { } @Test + public void run_zeroizedCredential() throws Exception { + String password = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "123"; + String appKeyAlias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "alias"; + byte[] zeroizedCredential = password.getBytes(); + mKeySyncTask = new KeySyncTask( + mRecoverableKeyStoreDb, + mRecoverySnapshotStorage, + mSnapshotListenersStorage, + TEST_USER_ID, + CREDENTIAL_TYPE_PASSWORD, + /*credential=*/ zeroizedCredential, + /*credentialUpdated=*/ false, + mPlatformKeyManager, + mTestOnlyInsecureCertificateHelper, + mMockScrypt); + mRecoverableKeyStoreDb.setServerParams( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE); + mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID); + mRecoverableKeyStoreDb.setActiveRootOfTrust(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, + TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS); + mRecoverableKeyStoreDb.setRecoveryServiceCertPath( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, + TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS, + TestData.getInsecureCertPathForEndpoint1()); + addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, appKeyAlias); + + // Need to check array value during method call since it is modified later. + setExpectedScryptArgument(password.getBytes()); + + Arrays.fill(zeroizedCredential, (byte) 0); + mKeySyncTask.run(); + + verify(mMockScrypt).scrypt(any(), any(), + eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), + eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); + } + + @Test public void run_useSha256ToHashPatternInProdMode() throws Exception { String pattern = "123456"; mKeySyncTask = new KeySyncTask( @@ -368,13 +409,15 @@ public class KeySyncTaskTest { mRecoverableKeyStoreDb.setRecoveryServiceCertPath( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); + setExpectedScryptArgument(shortPassword.getBytes()); + mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1); assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()). isEqualTo(UI_FORMAT_PASSWORD); - verify(mMockScrypt).scrypt(eq(shortPassword.getBytes()), any(), + verify(mMockScrypt).scrypt(any(), any(), eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); KeyDerivationParams keyDerivationParams = @@ -650,13 +693,15 @@ public class KeySyncTaskTest { when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); + setExpectedScryptArgument(password.getBytes()); + mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1); assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()). isEqualTo(UI_FORMAT_PASSWORD); - verify(mMockScrypt).scrypt(eq(password.getBytes()), any(), + verify(mMockScrypt).scrypt(any(), any(), eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); } @@ -681,6 +726,8 @@ public class KeySyncTaskTest { when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); + setExpectedScryptArgument(pin.getBytes()); + mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); @@ -688,7 +735,7 @@ public class KeySyncTaskTest { // Password with only digits is changed to pin. assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()). isEqualTo(UI_FORMAT_PIN); - verify(mMockScrypt).scrypt(eq(pin.getBytes()), any(), + verify(mMockScrypt).scrypt(any(), any(), eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); } @@ -868,4 +915,14 @@ public class KeySyncTaskTest { new Random().nextBytes(bytes); return bytes; } + + private void setExpectedScryptArgument(byte[] credentials) { + doAnswer(invocation -> { + assertThat((byte[]) invocation.getArguments()[0]).isEqualTo(credentials); + return invocation.callRealMethod(); + }).when(mMockScrypt).scrypt(any(), any(), + eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R), + eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES)); + + } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java index c546a741e76a..c09e09c8404f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; import android.app.KeyguardManager; import android.content.Context; @@ -54,6 +55,7 @@ import org.mockito.MockitoAnnotations; import java.io.File; import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; import java.util.List; @@ -393,6 +395,18 @@ public class PlatformKeyManagerTest { } @Test + public void getEncryptKey_noScreenlock() throws Exception { + when(mKeyguardManager.isDeviceSecure(USER_ID_FIXTURE)).thenReturn(false); + doThrow(new KeyStoreException()).when(mKeyStoreProxy).setEntry( + anyString(), + any(), + any()); + + assertThrows(InsecureUserException.class, + () -> mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE)); + } + + @Test public void getDecryptKey_generatesNewKeyIfOldOneIsInvalid() throws Exception { doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey( eq(DECRYPTION_KEY_ALIAS_1), diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java index 29152f19d17d..7b6a201796a6 100644 --- a/telephony/java/android/telephony/BarringInfo.java +++ b/telephony/java/android/telephony/BarringInfo.java @@ -202,6 +202,24 @@ public final class BarringInfo implements Parcelable { && mConditionalBarringTimeSeconds == other.mConditionalBarringTimeSeconds; } + private static String barringTypeToString(@BarringType int barringType) { + return switch (barringType) { + case BARRING_TYPE_NONE -> "NONE"; + case BARRING_TYPE_CONDITIONAL -> "CONDITIONAL"; + case BARRING_TYPE_UNCONDITIONAL -> "UNCONDITIONAL"; + case BARRING_TYPE_UNKNOWN -> "UNKNOWN"; + default -> "UNKNOWN(" + barringType + ")"; + }; + } + + @Override + public String toString() { + return "BarringServiceInfo {mBarringType=" + barringTypeToString(mBarringType) + + ", mIsConditionallyBarred=" + mIsConditionallyBarred + + ", mConditionalBarringFactor=" + mConditionalBarringFactor + + ", mConditionalBarringTimeSeconds=" + mConditionalBarringTimeSeconds + "}"; + } + /** @hide */ public BarringServiceInfo(Parcel p) { mBarringType = p.readInt(); diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt index 241e69106718..f61cce666cca 100644 --- a/test-mock/api/current.txt +++ b/test-mock/api/current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.test.mock { @Deprecated public class MockAccountManager { @@ -202,7 +200,7 @@ package android.test.mock { method @Deprecated public int checkPermission(String, String); method @Deprecated public int checkSignatures(String, String); method @Deprecated public int checkSignatures(int, int); - method public void clearInstantAppCookie(); + method @Deprecated public void clearInstantAppCookie(); method @Deprecated public void clearPackagePreferredActivities(String); method @Deprecated public String[] currentToCanonicalPackageNames(String[]); method @Deprecated public void extendVerificationTimeout(int, int, long); @@ -224,15 +222,15 @@ package android.test.mock { method @Deprecated public CharSequence getApplicationLabel(android.content.pm.ApplicationInfo); method @Deprecated public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo); method @Deprecated public android.graphics.drawable.Drawable getApplicationLogo(String) throws android.content.pm.PackageManager.NameNotFoundException; - method public android.content.pm.ChangedPackages getChangedPackages(int); + method @Deprecated public android.content.pm.ChangedPackages getChangedPackages(int); method @Deprecated public int getComponentEnabledSetting(android.content.ComponentName); method @Deprecated public android.graphics.drawable.Drawable getDefaultActivityIcon(); method @Deprecated public android.graphics.drawable.Drawable getDrawable(String, int, android.content.pm.ApplicationInfo); method @Deprecated public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int); method @Deprecated public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int); method @Deprecated public String getInstallerPackageName(String); - method public byte[] getInstantAppCookie(); - method public int getInstantAppCookieMaxBytes(); + method @Deprecated public byte[] getInstantAppCookie(); + method @Deprecated public int getInstantAppCookieMaxBytes(); method @Deprecated public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method @Deprecated public android.content.Intent getLaunchIntentForPackage(String); method @Deprecated public android.content.Intent getLeanbackLaunchIntentForPackage(String); @@ -241,7 +239,7 @@ package android.test.mock { method @Deprecated public int[] getPackageGids(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @Deprecated public android.content.pm.PackageInfo getPackageInfo(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @Deprecated public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException; - method public android.content.pm.PackageInstaller getPackageInstaller(); + method @Deprecated public android.content.pm.PackageInstaller getPackageInstaller(); method @Deprecated public int getPackageUid(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @Deprecated public String[] getPackagesForUid(int); method @Deprecated public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(String[], int); @@ -265,8 +263,8 @@ package android.test.mock { method @Deprecated public android.content.res.XmlResourceParser getXml(String, int, android.content.pm.ApplicationInfo); method @Deprecated public boolean hasSystemFeature(String); method @Deprecated public boolean hasSystemFeature(String, int); - method public boolean isInstantApp(); - method public boolean isInstantApp(String); + method @Deprecated public boolean isInstantApp(); + method @Deprecated public boolean isInstantApp(String); method @Deprecated public boolean isPermissionRevokedByPolicy(String, String); method @Deprecated public boolean isSafeMode(); method @Deprecated public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int); @@ -283,11 +281,12 @@ package android.test.mock { method @Deprecated public android.content.pm.ProviderInfo resolveContentProvider(String, int); method @Deprecated public android.content.pm.ResolveInfo resolveService(android.content.Intent, int); method @Deprecated public android.content.pm.ResolveInfo resolveServiceAsUser(android.content.Intent, int, int); - method public void setApplicationCategoryHint(String, int); + method @Deprecated public void setApplicationCategoryHint(String, int); method @Deprecated public void setApplicationEnabledSetting(String, int, int); method @Deprecated public void setComponentEnabledSetting(android.content.ComponentName, int, int); method @Deprecated public void setInstallerPackageName(String, String); - method public void updateInstantAppCookie(@NonNull byte[]); + method @Deprecated public boolean setInstantAppCookie(@NonNull byte[]); + method @Deprecated public void updateInstantAppCookie(@NonNull byte[]); method @Deprecated public void verifyPendingInstall(int, int); } diff --git a/test-mock/api/removed.txt b/test-mock/api/removed.txt index fa2fbd276e9a..0c800b6f82b5 100644 --- a/test-mock/api/removed.txt +++ b/test-mock/api/removed.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { @@ -11,7 +9,7 @@ package android.test.mock { @Deprecated public class MockPackageManager extends android.content.pm.PackageManager { method @Deprecated public String getDefaultBrowserPackageName(int); method @Deprecated public boolean setDefaultBrowserPackageName(String, int); - method public boolean setInstantAppCookie(@NonNull byte[]); + method @Deprecated public boolean setInstantAppCookie(@NonNull byte[]); } } diff --git a/test-mock/api/system-current.txt b/test-mock/api/system-current.txt index 2b5132ecd14f..f35095743738 100644 --- a/test-mock/api/system-current.txt +++ b/test-mock/api/system-current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { @@ -11,30 +9,30 @@ package android.test.mock { } @Deprecated public class MockPackageManager extends android.content.pm.PackageManager { - method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener); - method public boolean arePermissionsIndividuallyControlled(); + method @Deprecated public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener); + method @Deprecated public boolean arePermissionsIndividuallyControlled(); method @Deprecated public java.util.List<android.content.IntentFilter> getAllIntentFilters(String); - method public String getDefaultBrowserPackageNameAsUser(int); - method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int); - method public android.graphics.drawable.Drawable getInstantAppIcon(String); - method public android.content.ComponentName getInstantAppInstallerComponent(); - method public android.content.ComponentName getInstantAppResolverSettingsComponent(); - method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); - method public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(String); - method public int getIntentVerificationStatusAsUser(String, int); - method public int getPermissionFlags(String, String, android.os.UserHandle); - method public void grantRuntimePermission(String, String, android.os.UserHandle); - method public int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException; - method public int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException; - method public void registerDexModule(String, @Nullable android.content.pm.PackageManager.DexModuleRegisterCallback); - method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener); - method public void revokeRuntimePermission(String, String, android.os.UserHandle); - method public boolean setDefaultBrowserPackageNameAsUser(String, int); + method @Deprecated public String getDefaultBrowserPackageNameAsUser(int); + method @Deprecated public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int); + method @Deprecated public android.graphics.drawable.Drawable getInstantAppIcon(String); + method @Deprecated public android.content.ComponentName getInstantAppInstallerComponent(); + method @Deprecated public android.content.ComponentName getInstantAppResolverSettingsComponent(); + method @Deprecated public java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); + method @Deprecated public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(String); + method @Deprecated public int getIntentVerificationStatusAsUser(String, int); + method @Deprecated public int getPermissionFlags(String, String, android.os.UserHandle); + method @Deprecated public void grantRuntimePermission(String, String, android.os.UserHandle); + method @Deprecated public int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException; + method @Deprecated public int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException; + method @Deprecated public void registerDexModule(String, @Nullable android.content.pm.PackageManager.DexModuleRegisterCallback); + method @Deprecated public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener); + method @Deprecated public void revokeRuntimePermission(String, String, android.os.UserHandle); + method @Deprecated public boolean setDefaultBrowserPackageNameAsUser(String, int); method public String[] setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, String); - method public void setUpdateAvailable(String, boolean); - method public boolean updateIntentVerificationStatusAsUser(String, int, int); - method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle); - method public void verifyIntentFilter(int, int, java.util.List<java.lang.String>); + method @Deprecated public void setUpdateAvailable(String, boolean); + method @Deprecated public boolean updateIntentVerificationStatusAsUser(String, int, int); + method @Deprecated public void updatePermissionFlags(String, String, int, int, android.os.UserHandle); + method @Deprecated public void verifyIntentFilter(int, int, java.util.List<java.lang.String>); } } diff --git a/test-mock/api/system-removed.txt b/test-mock/api/system-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/test-mock/api/system-removed.txt +++ b/test-mock/api/system-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt index 1752edcd469e..9ed010881067 100644 --- a/test-mock/api/test-current.txt +++ b/test-mock/api/test-current.txt @@ -1,6 +1,4 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { @@ -8,13 +6,13 @@ package android.test.mock { } @Deprecated public class MockPackageManager extends android.content.pm.PackageManager { - method public void addCrossProfileIntentFilter(android.content.IntentFilter, int, int, int); - method public void clearCrossProfileIntentFilters(int); - method public int getInstallReason(String, android.os.UserHandle); - method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int); - method public String[] getNamesForUids(int[]); - method @NonNull public String getServicesSystemSharedLibraryPackageName(); - method @NonNull public String getSharedSystemSharedLibraryPackageName(); + method @Deprecated public void addCrossProfileIntentFilter(android.content.IntentFilter, int, int, int); + method @Deprecated public void clearCrossProfileIntentFilters(int); + method @Deprecated public int getInstallReason(String, android.os.UserHandle); + method @Deprecated public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int); + method @Deprecated public String[] getNamesForUids(int[]); + method @Deprecated @NonNull public String getServicesSystemSharedLibraryPackageName(); + method @Deprecated @NonNull public String getSharedSystemSharedLibraryPackageName(); } } diff --git a/test-mock/api/test-removed.txt b/test-mock/api/test-removed.txt index 14191ebcb080..d802177e249b 100644 --- a/test-mock/api/test-removed.txt +++ b/test-mock/api/test-removed.txt @@ -1,3 +1 @@ // Signature format: 2.0 -// - add-additional-overrides=no -// - migrating=Migration in progress see b/299366704 |