diff options
123 files changed, 2830 insertions, 1507 deletions
diff --git a/.prebuilt_info/OWNERS b/.prebuilt_info/OWNERS new file mode 100644 index 000000000000..eb8b89b10e83 --- /dev/null +++ b/.prebuilt_info/OWNERS @@ -0,0 +1 @@ +per-file prebuilt_info_packages_CtsShim_*.asciipb = file:/packages/CtsShim/OWNERS diff --git a/Android.bp b/Android.bp index d5e7cd870e5a..d40f11598553 100644 --- a/Android.bp +++ b/Android.bp @@ -525,7 +525,7 @@ java_library { "android.hardware.vibrator-V1.3-java", "android.security.apc-java", "android.security.authorization-java", - "android.security.usermanager-java", + "android.security.maintenance-java", "android.security.vpnprofilestore-java", "android.system.keystore2-V1-java", "android.system.suspend.control.internal-java", diff --git a/TEST_MAPPING b/TEST_MAPPING index 2b12da291acb..4b449ef0bacf 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -57,5 +57,65 @@ { "name": "ManagedProfileLifecycleStressTest" } - ] + ], + "auto-postsubmit": [ + // Test tag for automotive targets. These are only running in postsubmit so as to harden the + // automotive targets to avoid introducing additional test flake and build time. The plan for + // presubmit testing for auto is to augment the existing tests to cover auto use cases as well. + // Additionally, this tag is used in targeted test suites to limit resource usage on the test + // infra during the hardening phase. + // TODO: this tag to be removed once the above is no longer an issue. + { + "name": "FrameworksUiServicesTests", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] + }, + { + "name": "ExtServicesUnitTests", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] + }, + { + "name": "TestablesTests", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] + }, + { + "name": "FrameworksCoreTests", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + } + ] + }, + { + "name": "FrameworksServicesTests", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + } + ] + } + ] } diff --git a/config/preloaded-classes b/config/preloaded-classes index 5e88d97db91f..56c35bc41d05 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -1838,11 +1838,9 @@ android.database.sqlite.SqliteWrapper android.ddm.DdmHandleAppName$Names android.ddm.DdmHandleAppName android.ddm.DdmHandleExit -android.ddm.DdmHandleHeap android.ddm.DdmHandleHello android.ddm.DdmHandleNativeHeap android.ddm.DdmHandleProfiling -android.ddm.DdmHandleThread android.ddm.DdmHandleViewDebug android.ddm.DdmRegister android.debug.AdbManager diff --git a/core/api/current.txt b/core/api/current.txt index 116ac091b964..0e7ecefbdbdc 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -25018,10 +25018,6 @@ package android.net { ctor public NetworkSpecifier(); } - public class ParseException extends java.lang.RuntimeException { - field public String response; - } - public abstract class PlatformVpnProfile { method public final int getType(); method @NonNull public final String getTypeString(); @@ -25433,236 +25429,236 @@ package android.net.nsd { package android.net.rtp { - public class AudioCodec { - method public static android.net.rtp.AudioCodec getCodec(int, String, String); - method public static android.net.rtp.AudioCodec[] getCodecs(); - field public static final android.net.rtp.AudioCodec AMR; - field public static final android.net.rtp.AudioCodec GSM; - field public static final android.net.rtp.AudioCodec GSM_EFR; - field public static final android.net.rtp.AudioCodec PCMA; - field public static final android.net.rtp.AudioCodec PCMU; - field public final String fmtp; - field public final String rtpmap; - field public final int type; + @Deprecated public class AudioCodec { + method @Deprecated public static android.net.rtp.AudioCodec getCodec(int, String, String); + method @Deprecated public static android.net.rtp.AudioCodec[] getCodecs(); + field @Deprecated public static final android.net.rtp.AudioCodec AMR; + field @Deprecated public static final android.net.rtp.AudioCodec GSM; + field @Deprecated public static final android.net.rtp.AudioCodec GSM_EFR; + field @Deprecated public static final android.net.rtp.AudioCodec PCMA; + field @Deprecated public static final android.net.rtp.AudioCodec PCMU; + field @Deprecated public final String fmtp; + field @Deprecated public final String rtpmap; + field @Deprecated public final int type; } - public class AudioGroup { + @Deprecated public class AudioGroup { ctor @Deprecated public AudioGroup(); - ctor public AudioGroup(@NonNull android.content.Context); - method public void clear(); - method public int getMode(); - method public android.net.rtp.AudioStream[] getStreams(); - method public void sendDtmf(int); - method public void setMode(int); - field public static final int MODE_ECHO_SUPPRESSION = 3; // 0x3 - field public static final int MODE_MUTED = 1; // 0x1 - field public static final int MODE_NORMAL = 2; // 0x2 - field public static final int MODE_ON_HOLD = 0; // 0x0 - } - - public class AudioStream extends android.net.rtp.RtpStream { - ctor public AudioStream(java.net.InetAddress) throws java.net.SocketException; - method public android.net.rtp.AudioCodec getCodec(); - method public int getDtmfType(); - method public android.net.rtp.AudioGroup getGroup(); - method public final boolean isBusy(); - method public void join(android.net.rtp.AudioGroup); - method public void setCodec(android.net.rtp.AudioCodec); - method public void setDtmfType(int); - } - - public class RtpStream { - method public void associate(java.net.InetAddress, int); - method public java.net.InetAddress getLocalAddress(); - method public int getLocalPort(); - method public int getMode(); - method public java.net.InetAddress getRemoteAddress(); - method public int getRemotePort(); - method public boolean isBusy(); - method public void release(); - method public void setMode(int); - field public static final int MODE_NORMAL = 0; // 0x0 - field public static final int MODE_RECEIVE_ONLY = 2; // 0x2 - field public static final int MODE_SEND_ONLY = 1; // 0x1 + ctor @Deprecated public AudioGroup(@NonNull android.content.Context); + method @Deprecated public void clear(); + method @Deprecated public int getMode(); + method @Deprecated public android.net.rtp.AudioStream[] getStreams(); + method @Deprecated public void sendDtmf(int); + method @Deprecated public void setMode(int); + field @Deprecated public static final int MODE_ECHO_SUPPRESSION = 3; // 0x3 + field @Deprecated public static final int MODE_MUTED = 1; // 0x1 + field @Deprecated public static final int MODE_NORMAL = 2; // 0x2 + field @Deprecated public static final int MODE_ON_HOLD = 0; // 0x0 + } + + @Deprecated public class AudioStream extends android.net.rtp.RtpStream { + ctor @Deprecated public AudioStream(java.net.InetAddress) throws java.net.SocketException; + method @Deprecated public android.net.rtp.AudioCodec getCodec(); + method @Deprecated public int getDtmfType(); + method @Deprecated public android.net.rtp.AudioGroup getGroup(); + method @Deprecated public final boolean isBusy(); + method @Deprecated public void join(android.net.rtp.AudioGroup); + method @Deprecated public void setCodec(android.net.rtp.AudioCodec); + method @Deprecated public void setDtmfType(int); + } + + @Deprecated public class RtpStream { + method @Deprecated public void associate(java.net.InetAddress, int); + method @Deprecated public java.net.InetAddress getLocalAddress(); + method @Deprecated public int getLocalPort(); + method @Deprecated public int getMode(); + method @Deprecated public java.net.InetAddress getRemoteAddress(); + method @Deprecated public int getRemotePort(); + method @Deprecated public boolean isBusy(); + method @Deprecated public void release(); + method @Deprecated public void setMode(int); + field @Deprecated public static final int MODE_NORMAL = 0; // 0x0 + field @Deprecated public static final int MODE_RECEIVE_ONLY = 2; // 0x2 + field @Deprecated public static final int MODE_SEND_ONLY = 1; // 0x1 } } package android.net.sip { - public class SipAudioCall { - ctor public SipAudioCall(android.content.Context, android.net.sip.SipProfile); - method public void answerCall(int) throws android.net.sip.SipException; - method public void attachCall(android.net.sip.SipSession, String) throws android.net.sip.SipException; - method public void close(); - method public void continueCall(int) throws android.net.sip.SipException; - method public void endCall() throws android.net.sip.SipException; - method public android.net.sip.SipProfile getLocalProfile(); - method public android.net.sip.SipProfile getPeerProfile(); - method public int getState(); - method public void holdCall(int) throws android.net.sip.SipException; - method public boolean isInCall(); - method public boolean isMuted(); - method public boolean isOnHold(); - method public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException; - method public void sendDtmf(int); - method public void sendDtmf(int, android.os.Message); - method public void setListener(android.net.sip.SipAudioCall.Listener); - method public void setListener(android.net.sip.SipAudioCall.Listener, boolean); - method public void setSpeakerMode(boolean); - method public void startAudio(); - method public void toggleMute(); - } - - public static class SipAudioCall.Listener { - ctor public SipAudioCall.Listener(); - method public void onCallBusy(android.net.sip.SipAudioCall); - method public void onCallEnded(android.net.sip.SipAudioCall); - method public void onCallEstablished(android.net.sip.SipAudioCall); - method public void onCallHeld(android.net.sip.SipAudioCall); - method public void onCalling(android.net.sip.SipAudioCall); - method public void onChanged(android.net.sip.SipAudioCall); - method public void onError(android.net.sip.SipAudioCall, int, String); - method public void onReadyToCall(android.net.sip.SipAudioCall); - method public void onRinging(android.net.sip.SipAudioCall, android.net.sip.SipProfile); - method public void onRingingBack(android.net.sip.SipAudioCall); - } - - public class SipErrorCode { - method public static String toString(int); - field public static final int CLIENT_ERROR = -4; // 0xfffffffc - field public static final int CROSS_DOMAIN_AUTHENTICATION = -11; // 0xfffffff5 - field public static final int DATA_CONNECTION_LOST = -10; // 0xfffffff6 - field public static final int INVALID_CREDENTIALS = -8; // 0xfffffff8 - field public static final int INVALID_REMOTE_URI = -6; // 0xfffffffa - field public static final int IN_PROGRESS = -9; // 0xfffffff7 - field public static final int NO_ERROR = 0; // 0x0 - field public static final int PEER_NOT_REACHABLE = -7; // 0xfffffff9 - field public static final int SERVER_ERROR = -2; // 0xfffffffe - field public static final int SERVER_UNREACHABLE = -12; // 0xfffffff4 - field public static final int SOCKET_ERROR = -1; // 0xffffffff - field public static final int TIME_OUT = -5; // 0xfffffffb - field public static final int TRANSACTION_TERMINTED = -3; // 0xfffffffd - } - - public class SipException extends java.lang.Exception { - ctor public SipException(); - ctor public SipException(String); - ctor public SipException(String, Throwable); - } - - public class SipManager { - method public void close(String) throws android.net.sip.SipException; - method public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException; - method public static String getCallId(android.content.Intent); - method public static String getOfferSessionDescription(android.content.Intent); - method public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException; - method public static boolean isApiSupported(android.content.Context); - method public static boolean isIncomingCallIntent(android.content.Intent); - method public boolean isOpened(String) throws android.net.sip.SipException; - method public boolean isRegistered(String) throws android.net.sip.SipException; - method public static boolean isSipWifiOnly(android.content.Context); - method public static boolean isVoipSupported(android.content.Context); - method public android.net.sip.SipAudioCall makeAudioCall(android.net.sip.SipProfile, android.net.sip.SipProfile, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException; - method public android.net.sip.SipAudioCall makeAudioCall(String, String, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException; - method public static android.net.sip.SipManager newInstance(android.content.Context); - method public void open(android.net.sip.SipProfile) throws android.net.sip.SipException; - method public void open(android.net.sip.SipProfile, android.app.PendingIntent, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; - method public void register(android.net.sip.SipProfile, int, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; - method public void setRegistrationListener(String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; - method public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException; - method public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; - field public static final String EXTRA_CALL_ID = "android:sipCallID"; - field public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; - field public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65 - } - - public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable { - method public int describeContents(); - method public String getAuthUserName(); - method public boolean getAutoRegistration(); - method public String getDisplayName(); - method public String getPassword(); - method public int getPort(); - method public String getProfileName(); - method public String getProtocol(); - method public String getProxyAddress(); - method public boolean getSendKeepAlive(); - method public String getSipDomain(); - method public String getUriString(); - method public String getUserName(); - method public void setCallingUid(int); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.net.sip.SipProfile> CREATOR; - } - - public static class SipProfile.Builder { - ctor public SipProfile.Builder(android.net.sip.SipProfile); - ctor public SipProfile.Builder(String) throws java.text.ParseException; - ctor public SipProfile.Builder(String, String) throws java.text.ParseException; - method public android.net.sip.SipProfile build(); - method public android.net.sip.SipProfile.Builder setAuthUserName(String); - method public android.net.sip.SipProfile.Builder setAutoRegistration(boolean); - method public android.net.sip.SipProfile.Builder setDisplayName(String); - method public android.net.sip.SipProfile.Builder setOutboundProxy(String); - method public android.net.sip.SipProfile.Builder setPassword(String); - method public android.net.sip.SipProfile.Builder setPort(int) throws java.lang.IllegalArgumentException; - method public android.net.sip.SipProfile.Builder setProfileName(String); - method public android.net.sip.SipProfile.Builder setProtocol(String) throws java.lang.IllegalArgumentException; - method public android.net.sip.SipProfile.Builder setSendKeepAlive(boolean); - } - - public interface SipRegistrationListener { - method public void onRegistering(String); - method public void onRegistrationDone(String, long); - method public void onRegistrationFailed(String, int, String); - } - - public final class SipSession { - method public void answerCall(String, int); - method public void changeCall(String, int); - method public void endCall(); - method public String getCallId(); - method public String getLocalIp(); - method public android.net.sip.SipProfile getLocalProfile(); - method public android.net.sip.SipProfile getPeerProfile(); - method public int getState(); - method public boolean isInCall(); - method public void makeCall(android.net.sip.SipProfile, String, int); - method public void register(int); - method public void setListener(android.net.sip.SipSession.Listener); - method public void unregister(); - } - - public static class SipSession.Listener { - ctor public SipSession.Listener(); - method public void onCallBusy(android.net.sip.SipSession); - method public void onCallChangeFailed(android.net.sip.SipSession, int, String); - method public void onCallEnded(android.net.sip.SipSession); - method public void onCallEstablished(android.net.sip.SipSession, String); - method public void onCalling(android.net.sip.SipSession); - method public void onError(android.net.sip.SipSession, int, String); - method public void onRegistering(android.net.sip.SipSession); - method public void onRegistrationDone(android.net.sip.SipSession, int); - method public void onRegistrationFailed(android.net.sip.SipSession, int, String); - method public void onRegistrationTimeout(android.net.sip.SipSession); - method public void onRinging(android.net.sip.SipSession, android.net.sip.SipProfile, String); - method public void onRingingBack(android.net.sip.SipSession); - } - - public static class SipSession.State { - method public static String toString(int); - field public static final int DEREGISTERING = 2; // 0x2 - field public static final int INCOMING_CALL = 3; // 0x3 - field public static final int INCOMING_CALL_ANSWERING = 4; // 0x4 - field public static final int IN_CALL = 8; // 0x8 - field public static final int NOT_DEFINED = 101; // 0x65 - field public static final int OUTGOING_CALL = 5; // 0x5 - field public static final int OUTGOING_CALL_CANCELING = 7; // 0x7 - field public static final int OUTGOING_CALL_RING_BACK = 6; // 0x6 - field public static final int PINGING = 9; // 0x9 - field public static final int READY_TO_CALL = 0; // 0x0 - field public static final int REGISTERING = 1; // 0x1 + @Deprecated public class SipAudioCall { + ctor @Deprecated public SipAudioCall(android.content.Context, android.net.sip.SipProfile); + method @Deprecated public void answerCall(int) throws android.net.sip.SipException; + method @Deprecated public void attachCall(android.net.sip.SipSession, String) throws android.net.sip.SipException; + method @Deprecated public void close(); + method @Deprecated public void continueCall(int) throws android.net.sip.SipException; + method @Deprecated public void endCall() throws android.net.sip.SipException; + method @Deprecated public android.net.sip.SipProfile getLocalProfile(); + method @Deprecated public android.net.sip.SipProfile getPeerProfile(); + method @Deprecated public int getState(); + method @Deprecated public void holdCall(int) throws android.net.sip.SipException; + method @Deprecated public boolean isInCall(); + method @Deprecated public boolean isMuted(); + method @Deprecated public boolean isOnHold(); + method @Deprecated public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException; + method @Deprecated public void sendDtmf(int); + method @Deprecated public void sendDtmf(int, android.os.Message); + method @Deprecated public void setListener(android.net.sip.SipAudioCall.Listener); + method @Deprecated public void setListener(android.net.sip.SipAudioCall.Listener, boolean); + method @Deprecated public void setSpeakerMode(boolean); + method @Deprecated public void startAudio(); + method @Deprecated public void toggleMute(); + } + + @Deprecated public static class SipAudioCall.Listener { + ctor @Deprecated public SipAudioCall.Listener(); + method @Deprecated public void onCallBusy(android.net.sip.SipAudioCall); + method @Deprecated public void onCallEnded(android.net.sip.SipAudioCall); + method @Deprecated public void onCallEstablished(android.net.sip.SipAudioCall); + method @Deprecated public void onCallHeld(android.net.sip.SipAudioCall); + method @Deprecated public void onCalling(android.net.sip.SipAudioCall); + method @Deprecated public void onChanged(android.net.sip.SipAudioCall); + method @Deprecated public void onError(android.net.sip.SipAudioCall, int, String); + method @Deprecated public void onReadyToCall(android.net.sip.SipAudioCall); + method @Deprecated public void onRinging(android.net.sip.SipAudioCall, android.net.sip.SipProfile); + method @Deprecated public void onRingingBack(android.net.sip.SipAudioCall); + } + + @Deprecated public class SipErrorCode { + method @Deprecated public static String toString(int); + field @Deprecated public static final int CLIENT_ERROR = -4; // 0xfffffffc + field @Deprecated public static final int CROSS_DOMAIN_AUTHENTICATION = -11; // 0xfffffff5 + field @Deprecated public static final int DATA_CONNECTION_LOST = -10; // 0xfffffff6 + field @Deprecated public static final int INVALID_CREDENTIALS = -8; // 0xfffffff8 + field @Deprecated public static final int INVALID_REMOTE_URI = -6; // 0xfffffffa + field @Deprecated public static final int IN_PROGRESS = -9; // 0xfffffff7 + field @Deprecated public static final int NO_ERROR = 0; // 0x0 + field @Deprecated public static final int PEER_NOT_REACHABLE = -7; // 0xfffffff9 + field @Deprecated public static final int SERVER_ERROR = -2; // 0xfffffffe + field @Deprecated public static final int SERVER_UNREACHABLE = -12; // 0xfffffff4 + field @Deprecated public static final int SOCKET_ERROR = -1; // 0xffffffff + field @Deprecated public static final int TIME_OUT = -5; // 0xfffffffb + field @Deprecated public static final int TRANSACTION_TERMINTED = -3; // 0xfffffffd + } + + @Deprecated public class SipException extends java.lang.Exception { + ctor @Deprecated public SipException(); + ctor @Deprecated public SipException(String); + ctor @Deprecated public SipException(String, Throwable); + } + + @Deprecated public class SipManager { + method @Deprecated public void close(String) throws android.net.sip.SipException; + method @Deprecated public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException; + method @Deprecated public static String getCallId(android.content.Intent); + method @Deprecated public static String getOfferSessionDescription(android.content.Intent); + method @Deprecated public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException; + method @Deprecated public static boolean isApiSupported(android.content.Context); + method @Deprecated public static boolean isIncomingCallIntent(android.content.Intent); + method @Deprecated public boolean isOpened(String) throws android.net.sip.SipException; + method @Deprecated public boolean isRegistered(String) throws android.net.sip.SipException; + method @Deprecated public static boolean isSipWifiOnly(android.content.Context); + method @Deprecated public static boolean isVoipSupported(android.content.Context); + method @Deprecated public android.net.sip.SipAudioCall makeAudioCall(android.net.sip.SipProfile, android.net.sip.SipProfile, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException; + method @Deprecated public android.net.sip.SipAudioCall makeAudioCall(String, String, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException; + method @Deprecated public static android.net.sip.SipManager newInstance(android.content.Context); + method @Deprecated public void open(android.net.sip.SipProfile) throws android.net.sip.SipException; + method @Deprecated public void open(android.net.sip.SipProfile, android.app.PendingIntent, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; + method @Deprecated public void register(android.net.sip.SipProfile, int, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; + method @Deprecated public void setRegistrationListener(String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; + method @Deprecated public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException; + method @Deprecated public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; + field @Deprecated public static final String EXTRA_CALL_ID = "android:sipCallID"; + field @Deprecated public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; + field @Deprecated public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65 + } + + @Deprecated public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable { + method @Deprecated public int describeContents(); + method @Deprecated public String getAuthUserName(); + method @Deprecated public boolean getAutoRegistration(); + method @Deprecated public String getDisplayName(); + method @Deprecated public String getPassword(); + method @Deprecated public int getPort(); + method @Deprecated public String getProfileName(); + method @Deprecated public String getProtocol(); + method @Deprecated public String getProxyAddress(); + method @Deprecated public boolean getSendKeepAlive(); + method @Deprecated public String getSipDomain(); + method @Deprecated public String getUriString(); + method @Deprecated public String getUserName(); + method @Deprecated public void setCallingUid(int); + method @Deprecated public void writeToParcel(android.os.Parcel, int); + field @Deprecated public static final android.os.Parcelable.Creator<android.net.sip.SipProfile> CREATOR; + } + + @Deprecated public static class SipProfile.Builder { + ctor @Deprecated public SipProfile.Builder(android.net.sip.SipProfile); + ctor @Deprecated public SipProfile.Builder(String) throws java.text.ParseException; + ctor @Deprecated public SipProfile.Builder(String, String) throws java.text.ParseException; + method @Deprecated public android.net.sip.SipProfile build(); + method @Deprecated public android.net.sip.SipProfile.Builder setAuthUserName(String); + method @Deprecated public android.net.sip.SipProfile.Builder setAutoRegistration(boolean); + method @Deprecated public android.net.sip.SipProfile.Builder setDisplayName(String); + method @Deprecated public android.net.sip.SipProfile.Builder setOutboundProxy(String); + method @Deprecated public android.net.sip.SipProfile.Builder setPassword(String); + method @Deprecated public android.net.sip.SipProfile.Builder setPort(int) throws java.lang.IllegalArgumentException; + method @Deprecated public android.net.sip.SipProfile.Builder setProfileName(String); + method @Deprecated public android.net.sip.SipProfile.Builder setProtocol(String) throws java.lang.IllegalArgumentException; + method @Deprecated public android.net.sip.SipProfile.Builder setSendKeepAlive(boolean); + } + + @Deprecated public interface SipRegistrationListener { + method @Deprecated public void onRegistering(String); + method @Deprecated public void onRegistrationDone(String, long); + method @Deprecated public void onRegistrationFailed(String, int, String); + } + + @Deprecated public final class SipSession { + method @Deprecated public void answerCall(String, int); + method @Deprecated public void changeCall(String, int); + method @Deprecated public void endCall(); + method @Deprecated public String getCallId(); + method @Deprecated public String getLocalIp(); + method @Deprecated public android.net.sip.SipProfile getLocalProfile(); + method @Deprecated public android.net.sip.SipProfile getPeerProfile(); + method @Deprecated public int getState(); + method @Deprecated public boolean isInCall(); + method @Deprecated public void makeCall(android.net.sip.SipProfile, String, int); + method @Deprecated public void register(int); + method @Deprecated public void setListener(android.net.sip.SipSession.Listener); + method @Deprecated public void unregister(); + } + + @Deprecated public static class SipSession.Listener { + ctor @Deprecated public SipSession.Listener(); + method @Deprecated public void onCallBusy(android.net.sip.SipSession); + method @Deprecated public void onCallChangeFailed(android.net.sip.SipSession, int, String); + method @Deprecated public void onCallEnded(android.net.sip.SipSession); + method @Deprecated public void onCallEstablished(android.net.sip.SipSession, String); + method @Deprecated public void onCalling(android.net.sip.SipSession); + method @Deprecated public void onError(android.net.sip.SipSession, int, String); + method @Deprecated public void onRegistering(android.net.sip.SipSession); + method @Deprecated public void onRegistrationDone(android.net.sip.SipSession, int); + method @Deprecated public void onRegistrationFailed(android.net.sip.SipSession, int, String); + method @Deprecated public void onRegistrationTimeout(android.net.sip.SipSession); + method @Deprecated public void onRinging(android.net.sip.SipSession, android.net.sip.SipProfile, String); + method @Deprecated public void onRingingBack(android.net.sip.SipSession); + } + + @Deprecated public static class SipSession.State { + method @Deprecated public static String toString(int); + field @Deprecated public static final int DEREGISTERING = 2; // 0x2 + field @Deprecated public static final int INCOMING_CALL = 3; // 0x3 + field @Deprecated public static final int INCOMING_CALL_ANSWERING = 4; // 0x4 + field @Deprecated public static final int IN_CALL = 8; // 0x8 + field @Deprecated public static final int NOT_DEFINED = 101; // 0x65 + field @Deprecated public static final int OUTGOING_CALL = 5; // 0x5 + field @Deprecated public static final int OUTGOING_CALL_CANCELING = 7; // 0x7 + field @Deprecated public static final int OUTGOING_CALL_RING_BACK = 6; // 0x6 + field @Deprecated public static final int PINGING = 9; // 0x9 + field @Deprecated public static final int READY_TO_CALL = 0; // 0x0 + field @Deprecated public static final int REGISTERING = 1; // 0x1 } } @@ -38399,22 +38395,22 @@ package android.telecom { method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection); method public final void connectionServiceFocusReleased(); method @Nullable public final android.telecom.RemoteConference createRemoteIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); - method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method @Nullable public final android.telecom.RemoteConnection createRemoteIncomingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); method @Nullable public final android.telecom.RemoteConference createRemoteOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); - method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method @Nullable public final android.telecom.RemoteConnection createRemoteOutgoingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); method public final java.util.Collection<android.telecom.Conference> getAllConferences(); method public final java.util.Collection<android.telecom.Connection> getAllConnections(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConference(android.telecom.Connection, android.telecom.Connection); method public void onConnectionServiceFocusGained(); method public void onConnectionServiceFocusLost(); - method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method @Nullable public android.telecom.Conference onCreateIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); - method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method @Nullable public android.telecom.Conference onCreateOutgoingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); + method public void onCreateOutgoingConferenceFailed(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 4d9b4aafcae1..7c6ff8ede3cc 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -20,8 +20,24 @@ package android.app.usage { } +package android.content { + + public class Intent implements java.lang.Cloneable android.os.Parcelable { + field public static final String ACTION_CLEAR_DNS_CACHE = "android.intent.action.CLEAR_DNS_CACHE"; + } + +} + package android.net { + public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + ctor public EthernetNetworkSpecifier(@NonNull String); + method public int describeContents(); + method @Nullable public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR; + } + public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable { method public int getResourceId(); } @@ -56,6 +72,13 @@ package android.net { field @NonNull public final java.util.List<java.lang.String> underlyingIfaces; } + public class VpnManager { + field @Deprecated public static final int TYPE_VPN_LEGACY = 3; // 0x3 + field public static final int TYPE_VPN_NONE = -1; // 0xffffffff + field public static final int TYPE_VPN_PLATFORM = 2; // 0x2 + field public static final int TYPE_VPN_SERVICE = 1; // 0x1 + } + } package android.os { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index dc2e7a7e1a42..acce0a8822c2 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -6373,22 +6373,22 @@ package android.net.netstats.provider { package android.net.sip { - public class SipAudioCall { - method @Nullable public android.net.rtp.AudioGroup getAudioGroup(); - method public void setAudioGroup(@NonNull android.net.rtp.AudioGroup); + @Deprecated public class SipAudioCall { + method @Deprecated @Nullable public android.net.rtp.AudioGroup getAudioGroup(); + method @Deprecated public void setAudioGroup(@NonNull android.net.rtp.AudioGroup); } - public class SipManager { - method @NonNull public java.util.List<android.net.sip.SipProfile> getProfiles() throws android.net.sip.SipException; - field public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED"; - field public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL"; - field public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE"; - field public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP"; - field public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP"; + @Deprecated public class SipManager { + method @Deprecated @NonNull public java.util.List<android.net.sip.SipProfile> getProfiles() throws android.net.sip.SipException; + field @Deprecated public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED"; + field @Deprecated public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL"; + field @Deprecated public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE"; + field @Deprecated public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP"; + field @Deprecated public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP"; } - public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable { - method public int getCallingUid(); + @Deprecated public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable { + method @Deprecated public int getCallingUid(); } } @@ -6409,12 +6409,12 @@ package android.net.util { package android.net.vcn { public class VcnManager { - method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener); + method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.vcn.VcnNetworkPolicyResult applyVcnNetworkPolicy(@NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties); - method public void removeVcnNetworkPolicyListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener); + method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void removeVcnNetworkPolicyChangeListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener); } - public static interface VcnManager.VcnNetworkPolicyListener { + public static interface VcnManager.VcnNetworkPolicyChangeListener { method public void onPolicyChanged(); } @@ -9356,6 +9356,10 @@ package android.telephony { field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool"; } + public static final class CarrierConfigManager.Ims { + field public static final String KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY = "ims.publish_service_desc_feature_tag_map_override_string_array"; + } + public static final class CarrierConfigManager.Wifi { field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count"; field public static final String KEY_PREFIX = "wifi."; @@ -10179,7 +10183,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult setIccLockEnabled(boolean, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); - method public int setNrDualConnectivityState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setNrDualConnectivityState(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); @@ -10565,7 +10569,6 @@ package android.telephony.data { } public final class EpsBearerQosSessionAttributes implements android.os.Parcelable android.net.QosSessionAttributes { - method @NonNull public static android.telephony.data.EpsBearerQosSessionAttributes create(@NonNull android.os.Parcel); method public int describeContents(); method public long getGuaranteedDownlinkBitRate(); method public long getGuaranteedUplinkBitRate(); @@ -11543,6 +11546,7 @@ package android.telephony.ims { method public void onAutoConfigurationErrorReceived(int, @NonNull String); method public void onConfigurationChanged(@NonNull byte[]); method public void onConfigurationReset(); + method public void onPreProvisioningReceived(@NonNull byte[]); method public void onRemoved(); } @@ -11567,7 +11571,7 @@ package android.telephony.ims { method @NonNull public String getServiceId(); method @NonNull public String getServiceVersion(); method @NonNull public String getStatus(); - method @Nullable public String getTimestamp(); + method @Nullable public java.time.Instant getTime(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactPresenceTuple> CREATOR; field public static final String SERVICE_ID_CALL_COMPOSER = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callcomposer"; @@ -11594,7 +11598,7 @@ package android.telephony.ims { method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setContactUri(@NonNull android.net.Uri); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceCapabilities(@NonNull android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceDescription(@NonNull String); - method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setTimestamp(@NonNull String); + method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setTime(@NonNull java.time.Instant); } public static final class RcsContactPresenceTuple.ServiceCapabilities implements android.os.Parcelable { @@ -11650,7 +11654,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getUcePublishState() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeOnPublishStateChangedListener(@NonNull android.telephony.ims.RcsUceAdapter.OnPublishStateChangedListener) throws android.telephony.ims.ImsException; method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestAvailability(@NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; // 0x1 @@ -12012,6 +12016,7 @@ package android.telephony.ims.stub { method public int getConfigInt(int); method public String getConfigString(int); method public final void notifyAutoConfigurationErrorReceived(int, @NonNull String); + method public final void notifyPreProvisioningReceived(@NonNull byte[]); method public final void notifyProvisionedValueChanged(int, int); method public final void notifyProvisionedValueChanged(int, String); method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); @@ -12127,7 +12132,7 @@ package android.telephony.ims.stub { ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor); method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback); method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback); - method public void subscribeForCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback); + method public void subscribeForCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback); field public static final int COMMAND_CODE_FETCH_ERROR = 3; // 0x3 field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1 field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; // 0x5 @@ -12295,6 +12300,7 @@ package android.util { package android.uwb { public final class AngleMeasurement implements android.os.Parcelable { + ctor public AngleMeasurement(double, double, double); method public int describeContents(); method @FloatRange(from=0.0, to=1.0) public double getConfidenceLevel(); method @FloatRange(from=0.0, to=3.141592653589793) public double getErrorRadians(); @@ -12303,14 +12309,6 @@ package android.uwb { field @NonNull public static final android.os.Parcelable.Creator<android.uwb.AngleMeasurement> CREATOR; } - public static final class AngleMeasurement.Builder { - ctor public AngleMeasurement.Builder(); - method @NonNull public android.uwb.AngleMeasurement build(); - method @NonNull public android.uwb.AngleMeasurement.Builder setConfidenceLevel(double); - method @NonNull public android.uwb.AngleMeasurement.Builder setErrorRadians(double); - method @NonNull public android.uwb.AngleMeasurement.Builder setRadians(double); - } - public final class AngleOfArrivalMeasurement implements android.os.Parcelable { method public int describeContents(); method @Nullable public android.uwb.AngleMeasurement getAltitude(); @@ -12320,10 +12318,9 @@ package android.uwb { } public static final class AngleOfArrivalMeasurement.Builder { - ctor public AngleOfArrivalMeasurement.Builder(); + ctor public AngleOfArrivalMeasurement.Builder(@NonNull android.uwb.AngleMeasurement); method @NonNull public android.uwb.AngleOfArrivalMeasurement build(); method @NonNull public android.uwb.AngleOfArrivalMeasurement.Builder setAltitude(@NonNull android.uwb.AngleMeasurement); - method @NonNull public android.uwb.AngleOfArrivalMeasurement.Builder setAzimuth(@NonNull android.uwb.AngleMeasurement); } public final class DistanceMeasurement implements android.os.Parcelable { @@ -12423,7 +12420,7 @@ package android.uwb { public final class UwbManager { method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos(); method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo(); - method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public AutoCloseable openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback); + method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.CancellationSignal openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback); method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback); method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback); } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index b0b45564d44d..a0ff97e1f338 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1604,6 +1604,10 @@ package android.telecom { method @NonNull public android.telecom.ConnectionRequest.Builder setVideoState(int); } + public abstract class ConnectionService extends android.app.Service { + method public void onBindClient(@Nullable android.content.Intent); + } + } package android.telephony { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b99d5cd13a77..65f2c02faa85 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2770,7 +2770,7 @@ public final class ActivityThread extends ClientTransactionHandler { memInfo.getTotalPrivateDirty(), memInfo.getTotalPrivateClean(), memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() : - memInfo.getTotalSwappedOut(), memInfo.getTotalPss(), + memInfo.getTotalSwappedOut(), memInfo.getTotalRss(), nativeMax+dalvikMax, nativeAllocated+dalvikAllocated, nativeFree+dalvikFree); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 6bfc12d8d19e..4d68e90437be 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2329,6 +2329,7 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final String ACTION_CLEAR_DNS_CACHE = "android.intent.action.CLEAR_DNS_CACHE"; /** * Alarm Changed Action: This is broadcast when the AlarmClock diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java index e24aeb2af3a1..8fa235294451 100644 --- a/core/java/android/ddm/DdmHandleHeap.java +++ b/core/java/android/ddm/DdmHandleHeap.java @@ -30,15 +30,7 @@ import java.nio.ByteBuffer; */ public class DdmHandleHeap extends ChunkHandler { - public static final int CHUNK_HPIF = type("HPIF"); - public static final int CHUNK_HPSG = type("HPSG"); - public static final int CHUNK_HPDU = type("HPDU"); - public static final int CHUNK_HPDS = type("HPDS"); - public static final int CHUNK_NHSG = type("NHSG"); public static final int CHUNK_HPGC = type("HPGC"); - public static final int CHUNK_REAE = type("REAE"); - public static final int CHUNK_REAQ = type("REAQ"); - public static final int CHUNK_REAL = type("REAL"); private static DdmHandleHeap mInstance = new DdmHandleHeap(); @@ -50,15 +42,7 @@ public class DdmHandleHeap extends ChunkHandler { * Register for the messages we're interested in. */ public static void register() { - DdmServer.registerHandler(CHUNK_HPIF, mInstance); - DdmServer.registerHandler(CHUNK_HPSG, mInstance); - DdmServer.registerHandler(CHUNK_HPDU, mInstance); - DdmServer.registerHandler(CHUNK_HPDS, mInstance); - DdmServer.registerHandler(CHUNK_NHSG, mInstance); DdmServer.registerHandler(CHUNK_HPGC, mInstance); - DdmServer.registerHandler(CHUNK_REAE, mInstance); - DdmServer.registerHandler(CHUNK_REAQ, mInstance); - DdmServer.registerHandler(CHUNK_REAL, mInstance); } /** @@ -81,24 +65,8 @@ public class DdmHandleHeap extends ChunkHandler { Log.v("ddm-heap", "Handling " + name(request.type) + " chunk"); int type = request.type; - if (type == CHUNK_HPIF) { - return handleHPIF(request); - } else if (type == CHUNK_HPSG) { - return handleHPSGNHSG(request, false); - } else if (type == CHUNK_HPDU) { - return handleHPDU(request); - } else if (type == CHUNK_HPDS) { - return handleHPDS(request); - } else if (type == CHUNK_NHSG) { - return handleHPSGNHSG(request, true); - } else if (type == CHUNK_HPGC) { + if (type == CHUNK_HPGC) { return handleHPGC(request); - } else if (type == CHUNK_REAE) { - return handleREAE(request); - } else if (type == CHUNK_REAQ) { - return handleREAQ(request); - } else if (type == CHUNK_REAL) { - return handleREAL(request); } else { throw new RuntimeException("Unknown packet " + ChunkHandler.name(type)); @@ -106,112 +74,6 @@ public class DdmHandleHeap extends ChunkHandler { } /* - * Handle a "HeaP InFo" request. - */ - private Chunk handleHPIF(Chunk request) { - ByteBuffer in = wrapChunk(request); - - int when = in.get(); - if (false) - Log.v("ddm-heap", "Heap segment enable: when=" + when); - - boolean ok = DdmVmInternal.heapInfoNotify(when); - if (!ok) { - return createFailChunk(1, "Unsupported HPIF what"); - } else { - return null; // empty response - } - } - - /* - * Handle a "HeaP SeGment" or "Native Heap SeGment" request. - */ - private Chunk handleHPSGNHSG(Chunk request, boolean isNative) { - ByteBuffer in = wrapChunk(request); - - int when = in.get(); - int what = in.get(); - if (false) - Log.v("ddm-heap", "Heap segment enable: when=" + when - + ", what=" + what + ", isNative=" + isNative); - - boolean ok = DdmVmInternal.heapSegmentNotify(when, what, isNative); - if (!ok) { - return createFailChunk(1, "Unsupported HPSG what/when"); - } else { - // TODO: if "when" is non-zero and we want to see a dump - // right away, initiate a GC. - return null; // empty response - } - } - - /* - * Handle a "HeaP DUmp" request. - * - * This currently just returns a result code. We could pull up - * the entire contents of the file and return them, but hprof dump - * files can be a few megabytes. - */ - private Chunk handleHPDU(Chunk request) { - ByteBuffer in = wrapChunk(request); - byte result; - - /* get the filename for the output file */ - int len = in.getInt(); - String fileName = getString(in, len); - if (false) - Log.d("ddm-heap", "Heap dump: file='" + fileName + "'"); - - try { - Debug.dumpHprofData(fileName); - result = 0; - } catch (UnsupportedOperationException uoe) { - Log.w("ddm-heap", "hprof dumps not supported in this VM"); - result = -1; - } catch (IOException ioe) { - result = -1; - } catch (RuntimeException re) { - result = -1; - } - - /* create a non-empty reply so the handler fires on completion */ - byte[] reply = { result }; - return new Chunk(CHUNK_HPDU, reply, 0, reply.length); - } - - /* - * Handle a "HeaP Dump Streaming" request. - * - * This tells the VM to create a heap dump and send it directly to - * DDMS. The dumps are large enough that we don't want to copy the - * data into a byte[] and send it from here. - */ - private Chunk handleHPDS(Chunk request) { - ByteBuffer in = wrapChunk(request); - byte result; - - /* get the filename for the output file */ - if (false) - Log.d("ddm-heap", "Heap dump: [DDMS]"); - - String failMsg = null; - try { - Debug.dumpHprofDataDdms(); - } catch (UnsupportedOperationException uoe) { - failMsg = "hprof dumps not supported in this VM"; - } catch (RuntimeException re) { - failMsg = "Exception: " + re.getMessage(); - } - - if (failMsg != null) { - Log.w("ddm-heap", failMsg); - return createFailChunk(1, failMsg); - } else { - return null; - } - } - - /* * Handle a "HeaP Garbage Collection" request. */ private Chunk handleHPGC(Chunk request) { @@ -223,47 +85,4 @@ public class DdmHandleHeap extends ChunkHandler { return null; // empty response } - - /* - * Handle a "REcent Allocation Enable" request. - */ - private Chunk handleREAE(Chunk request) { - ByteBuffer in = wrapChunk(request); - boolean enable; - - enable = (in.get() != 0); - - if (false) - Log.d("ddm-heap", "Recent allocation enable request: " + enable); - - DdmVmInternal.enableRecentAllocations(enable); - - return null; // empty response - } - - /* - * Handle a "REcent Allocation Query" request. - */ - private Chunk handleREAQ(Chunk request) { - //ByteBuffer in = wrapChunk(request); - - byte[] reply = new byte[1]; - reply[0] = DdmVmInternal.getRecentAllocationStatus() ? (byte)1 :(byte)0; - return new Chunk(CHUNK_REAQ, reply, 0, reply.length); - } - - /* - * Handle a "REcent ALlocations" request. - */ - private Chunk handleREAL(Chunk request) { - //ByteBuffer in = wrapChunk(request); - - if (false) - Log.d("ddm-heap", "Recent allocations request"); - - /* generate the reply in a ready-to-go format */ - byte[] reply = DdmVmInternal.getRecentAllocations(); - return new Chunk(CHUNK_REAL, reply, 0, reply.length); - } } - diff --git a/core/java/android/ddm/DdmHandleThread.java b/core/java/android/ddm/DdmHandleThread.java deleted file mode 100644 index 613ab75f9c1b..000000000000 --- a/core/java/android/ddm/DdmHandleThread.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.ddm; - -import org.apache.harmony.dalvik.ddmc.Chunk; -import org.apache.harmony.dalvik.ddmc.ChunkHandler; -import org.apache.harmony.dalvik.ddmc.DdmServer; -import org.apache.harmony.dalvik.ddmc.DdmVmInternal; -import android.util.Log; -import java.nio.ByteBuffer; - -/** - * Handle thread-related traffic. - */ -public class DdmHandleThread extends ChunkHandler { - - public static final int CHUNK_THEN = type("THEN"); - public static final int CHUNK_THCR = type("THCR"); - public static final int CHUNK_THDE = type("THDE"); - public static final int CHUNK_THST = type("THST"); - public static final int CHUNK_STKL = type("STKL"); - - private static DdmHandleThread mInstance = new DdmHandleThread(); - - - /* singleton, do not instantiate */ - private DdmHandleThread() {} - - /** - * Register for the messages we're interested in. - */ - public static void register() { - DdmServer.registerHandler(CHUNK_THEN, mInstance); - DdmServer.registerHandler(CHUNK_THST, mInstance); - DdmServer.registerHandler(CHUNK_STKL, mInstance); - } - - /** - * Called when the DDM server connects. The handler is allowed to - * send messages to the server. - */ - public void connected() {} - - /** - * Called when the DDM server disconnects. Can be used to disable - * periodic transmissions or clean up saved state. - */ - public void disconnected() {} - - /** - * Handle a chunk of data. - */ - public Chunk handleChunk(Chunk request) { - if (false) - Log.v("ddm-thread", "Handling " + name(request.type) + " chunk"); - int type = request.type; - - if (type == CHUNK_THEN) { - return handleTHEN(request); - } else if (type == CHUNK_THST) { - return handleTHST(request); - } else if (type == CHUNK_STKL) { - return handleSTKL(request); - } else { - throw new RuntimeException("Unknown packet " - + ChunkHandler.name(type)); - } - } - - /* - * Handle a "THread notification ENable" request. - */ - private Chunk handleTHEN(Chunk request) { - ByteBuffer in = wrapChunk(request); - - boolean enable = (in.get() != 0); - //Log.i("ddm-thread", "Thread notify enable: " + enable); - - DdmVmInternal.threadNotify(enable); - return null; // empty response - } - - /* - * Handle a "THread STatus" request. This is constructed by the VM. - */ - private Chunk handleTHST(Chunk request) { - ByteBuffer in = wrapChunk(request); - // currently nothing to read from "in" - - //Log.d("ddm-thread", "Thread status request"); - - byte[] status = DdmVmInternal.getThreadStats(); - if (status != null) - return new Chunk(CHUNK_THST, status, 0, status.length); - else - return createFailChunk(1, "Can't build THST chunk"); - } - - /* - * Handle a STacK List request. - * - * This is done by threadId, which isn't great since those are - * recycled. We need a thread serial ID. The Linux tid is an okay - * answer as it's unlikely to recycle at the exact wrong moment. - * However, we're using the short threadId in THST messages, so we - * use them here for consistency. (One thought is to keep the current - * thread ID in the low 16 bits and somehow serialize the top 16 bits.) - */ - private Chunk handleSTKL(Chunk request) { - ByteBuffer in = wrapChunk(request); - int threadId; - - threadId = in.getInt(); - - //Log.d("ddm-thread", "Stack list request " + threadId); - - StackTraceElement[] trace = DdmVmInternal.getStackTraceById(threadId); - if (trace == null) { - return createFailChunk(1, "Stack trace unavailable"); - } else { - return createStackChunk(trace, threadId); - } - } - - /* - * Serialize a StackTraceElement[] into an STKL chunk. - * - * We include the threadId in the response so the other side doesn't have - * to match up requests and responses as carefully. - */ - private Chunk createStackChunk(StackTraceElement[] trace, int threadId) { - int bufferSize = 0; - - bufferSize += 4; // version, flags, whatever - bufferSize += 4; // thread ID - bufferSize += 4; // frame count - for (StackTraceElement elem : trace) { - bufferSize += 4 + elem.getClassName().length() * 2; - bufferSize += 4 + elem.getMethodName().length() * 2; - bufferSize += 4; - if (elem.getFileName() != null) - bufferSize += elem.getFileName().length() * 2; - bufferSize += 4; // line number - } - - ByteBuffer out = ByteBuffer.allocate(bufferSize); - out.putInt(0); - out.putInt(threadId); - out.putInt(trace.length); - for (StackTraceElement elem : trace) { - out.putInt(elem.getClassName().length()); - putString(out, elem.getClassName()); - out.putInt(elem.getMethodName().length()); - putString(out, elem.getMethodName()); - if (elem.getFileName() != null) { - out.putInt(elem.getFileName().length()); - putString(out, elem.getFileName()); - } else { - out.putInt(0); - } - out.putInt(elem.getLineNumber()); - } - - return new Chunk(CHUNK_STKL, out); - } -} - diff --git a/core/java/android/ddm/DdmRegister.java b/core/java/android/ddm/DdmRegister.java index e0faa51a938e..ca1031287e3e 100644 --- a/core/java/android/ddm/DdmRegister.java +++ b/core/java/android/ddm/DdmRegister.java @@ -16,9 +16,10 @@ package android.ddm; -import org.apache.harmony.dalvik.ddmc.DdmServer; import android.util.Log; +import org.apache.harmony.dalvik.ddmc.DdmServer; + /** * Just a place to stick handler registrations, instead of scattering * them around. @@ -46,7 +47,6 @@ public class DdmRegister { if (false) Log.v("ddm", "Registering DDM message handlers"); DdmHandleHello.register(); - DdmHandleThread.register(); DdmHandleHeap.register(); DdmHandleNativeHeap.register(); DdmHandleProfiling.register(); diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/core/java/android/net/EthernetNetworkSpecifier.java new file mode 100644 index 000000000000..e1685887e806 --- /dev/null +++ b/core/java/android/net/EthernetNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify ethernet interfaces. + * + * @see EthernetManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public EthernetNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(@Nullable Object o) { + if (!(o instanceof EthernetNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((EthernetNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "EthernetNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Parcelable.Creator<EthernetNetworkSpecifier> CREATOR = + new Parcelable.Creator<EthernetNetworkSpecifier>() { + public EthernetNetworkSpecifier createFromParcel(Parcel in) { + return new EthernetNetworkSpecifier(in.readString()); + } + public EthernetNetworkSpecifier[] newArray(int size) { + return new EthernetNetworkSpecifier[size]; + } + }; +} diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index f472ed4381d1..77754d1256a7 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -16,12 +16,15 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; @@ -56,18 +59,21 @@ import java.util.List; */ public class VpnManager { /** Type representing a lack of VPN @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_NONE = -1; /** * A VPN created by an app using the {@link VpnService} API. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_SERVICE = 1; /** * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_PLATFORM = 2; /** @@ -76,6 +82,7 @@ public class VpnManager { * @hide */ @Deprecated + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_LEGACY = 3; /** diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 8ebf757760c3..062438c6e5db 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -73,7 +73,8 @@ import java.util.concurrent.Executor; public class VcnManager { @NonNull private static final String TAG = VcnManager.class.getSimpleName(); - private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder> + private static final Map< + VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder> REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>(); @NonNull private final Context mContext; @@ -93,13 +94,13 @@ public class VcnManager { } /** - * Get all currently registered VcnNetworkPolicyListeners for testing purposes. + * Get all currently registered VcnNetworkPolicyChangeListeners for testing purposes. * * @hide */ @VisibleForTesting(visibility = Visibility.PRIVATE) @NonNull - public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder> + public static Map<VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder> getAllPolicyListeners() { return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS); } @@ -162,14 +163,14 @@ public class VcnManager { } // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using - // the new VcnNetworkPolicyListener API + // the new VcnNetworkPolicyChangeListener API /** * VcnUnderlyingNetworkPolicyListener is the interface through which internal system components * can register to receive updates for VCN-underlying Network policies from the System Server. * * @hide */ - public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {} + public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyChangeListener {} /** * Add a listener for VCN-underlying network policy updates. @@ -185,7 +186,7 @@ public class VcnManager { @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnUnderlyingNetworkPolicyListener( @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) { - addVcnNetworkPolicyListener(executor, listener); + addVcnNetworkPolicyChangeListener(executor, listener); } /** @@ -198,7 +199,7 @@ public class VcnManager { */ public void removeVcnUnderlyingNetworkPolicyListener( @NonNull VcnUnderlyingNetworkPolicyListener listener) { - removeVcnNetworkPolicyListener(listener); + removeVcnNetworkPolicyChangeListener(listener); } /** @@ -233,20 +234,20 @@ public class VcnManager { } /** - * VcnNetworkPolicyListener is the interface through which internal system components (e.g. - * Network Factories) can register to receive updates for VCN-underlying Network policies from - * the System Server. + * VcnNetworkPolicyChangeListener is the interface through which internal system components + * (e.g. Network Factories) can register to receive updates for VCN-underlying Network policies + * from the System Server. * * <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks - * should register a VcnNetworkPolicyListener. VcnManager will then use this listener to notify - * the registrant when VCN Network policies change. Upon receiving this signal, the listener - * must check {@link VcnManager} for the current Network policy result for each of its Networks - * via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}. + * should register a VcnNetworkPolicyChangeListener. VcnManager will then use this listener to + * notify the registrant when VCN Network policies change. Upon receiving this signal, the + * listener must check {@link VcnManager} for the current Network policy result for each of its + * Networks via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}. * * @hide */ @SystemApi - public interface VcnNetworkPolicyListener { + public interface VcnNetworkPolicyChangeListener { /** * Notifies the implementation that the VCN's underlying Network policy has changed. * @@ -260,20 +261,21 @@ public class VcnManager { /** * Add a listener for VCN-underlying Network policy updates. * - * <p>A {@link VcnNetworkPolicyListener} is eligible to begin receiving callbacks once it is - * registered. No callbacks are guaranteed upon registration. + * <p>A {@link VcnNetworkPolicyChangeListener} is eligible to begin receiving callbacks once it + * is registered. No callbacks are guaranteed upon registration. * * @param executor the Executor that will be used for invoking all calls to the specified * Listener - * @param listener the VcnNetworkPolicyListener to be added + * @param listener the VcnNetworkPolicyChangeListener to be added * @throws SecurityException if the caller does not have permission NETWORK_FACTORY - * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered + * @throws IllegalStateException if the specified VcnNetworkPolicyChangeListener is already + * registered * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public void addVcnNetworkPolicyListener( - @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) { + public void addVcnNetworkPolicyChangeListener( + @NonNull Executor executor, @NonNull VcnNetworkPolicyChangeListener listener) { requireNonNull(executor, "executor must not be null"); requireNonNull(listener, "listener must not be null"); @@ -292,15 +294,18 @@ public class VcnManager { } /** - * Remove the specified VcnNetworkPolicyListener from VcnManager. + * Remove the specified VcnNetworkPolicyChangeListener from VcnManager. * * <p>If the specified listener is not currently registered, this is a no-op. * - * @param listener the VcnNetworkPolicyListener that will be removed + * @param listener the VcnNetworkPolicyChangeListener that will be removed + * @throws SecurityException if the caller does not have permission NETWORK_FACTORY * @hide */ @SystemApi - public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) { + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public void removeVcnNetworkPolicyChangeListener( + @NonNull VcnNetworkPolicyChangeListener listener) { requireNonNull(listener, "listener must not be null"); VcnUnderlyingNetworkPolicyListenerBinder binder = @@ -320,8 +325,9 @@ public class VcnManager { * Applies the network policy for a {@link android.net.Network} with the given parameters. * * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy - * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider - * MUST poll for the updated Network policy based on that Network's capabilities and properties. + * may have changed via {@link VcnNetworkPolicyChangeListener#onPolicyChanged()}, a Network + * Provider MUST poll for the updated Network policy based on that Network's capabilities and + * properties. * * @param networkCapabilities the NetworkCapabilities to be used in determining the Network * policy result for this Network. @@ -532,17 +538,18 @@ public class VcnManager { } /** - * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server. + * Binder wrapper for added VcnNetworkPolicyChangeListeners to receive signals from System + * Server. * * @hide */ private static class VcnUnderlyingNetworkPolicyListenerBinder extends IVcnUnderlyingNetworkPolicyListener.Stub { @NonNull private final Executor mExecutor; - @NonNull private final VcnNetworkPolicyListener mListener; + @NonNull private final VcnNetworkPolicyChangeListener mListener; private VcnUnderlyingNetworkPolicyListenerBinder( - Executor executor, VcnNetworkPolicyListener listener) { + Executor executor, VcnNetworkPolicyChangeListener listener) { mExecutor = executor; mListener = listener; } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index a4d6c3845fbf..0264d2335c4b 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1235,9 +1235,9 @@ public final class FileUtils { } /** - * Creates a directory with name {@code name} under an existing directory {@code baseDir}. - * Returns a {@code File} object representing the directory on success, {@code null} on - * failure. + * Creates a directory with name {@code name} under an existing directory {@code baseDir} if it + * doesn't exist already. Returns a {@code File} object representing the directory if it exists + * and {@code null} if not. * * @hide */ @@ -1247,13 +1247,23 @@ public final class FileUtils { return createDir(dir) ? dir : null; } - /** @hide */ + /** + * Ensure the given directory exists, creating it if needed. This method is threadsafe. + * + * @return false if the directory doesn't exist and couldn't be created + * + * @hide + */ public static boolean createDir(File dir) { + if (dir.mkdir()) { + return true; + } + if (dir.exists()) { return dir.isDirectory(); } - return dir.mkdir(); + return false; } /** diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java index 9df213b2092f..8c771baaea37 100644 --- a/core/java/android/uwb/AngleMeasurement.java +++ b/core/java/android/uwb/AngleMeasurement.java @@ -38,9 +38,30 @@ public final class AngleMeasurement implements Parcelable { private final double mErrorRadians; private final double mConfidenceLevel; - private AngleMeasurement(double radians, double errorRadians, double confidenceLevel) { + /** + * Constructs a new {@link AngleMeasurement} object + * + * @param radians the angle in radians + * @param errorRadians the error of the angle measurement in radians + * @param confidenceLevel confidence level of the angle measurement + * + * @throws IllegalArgumentException if the radians, errorRadians, or confidenceLevel is out of + * allowed range + */ + public AngleMeasurement(double radians, double errorRadians, double confidenceLevel) { + if (radians < -Math.PI || radians > Math.PI) { + throw new IllegalArgumentException("Invalid radians: " + radians); + } mRadians = radians; + + if (errorRadians < 0.0 || errorRadians > Math.PI) { + throw new IllegalArgumentException("Invalid error radians: " + errorRadians); + } mErrorRadians = errorRadians; + + if (confidenceLevel < 0.0 || confidenceLevel > 1.0) { + throw new IllegalArgumentException("Invalid confidence level: " + confidenceLevel); + } mConfidenceLevel = confidenceLevel; } @@ -122,11 +143,7 @@ public final class AngleMeasurement implements Parcelable { new Creator<AngleMeasurement>() { @Override public AngleMeasurement createFromParcel(Parcel in) { - Builder builder = new Builder(); - builder.setRadians(in.readDouble()); - builder.setErrorRadians(in.readDouble()); - builder.setConfidenceLevel(in.readDouble()); - return builder.build(); + return new AngleMeasurement(in.readDouble(), in.readDouble(), in.readDouble()); } @Override @@ -134,82 +151,4 @@ public final class AngleMeasurement implements Parcelable { return new AngleMeasurement[size]; } }; - - /** - * Builder class for {@link AngleMeasurement}. - */ - public static final class Builder { - private double mRadians = Double.NaN; - private double mErrorRadians = Double.NaN; - private double mConfidenceLevel = Double.NaN; - - /** - * Set the angle in radians - * - * @param radians angle in radians - * @throws IllegalArgumentException if angle exceeds allowed limits of [-Math.PI, +Math.PI] - */ - @NonNull - public Builder setRadians(double radians) { - if (radians < -Math.PI || radians > Math.PI) { - throw new IllegalArgumentException("Invalid radians: " + radians); - } - mRadians = radians; - return this; - } - - /** - * Set the angle error in radians - * - * @param errorRadians error of the angle in radians - * @throws IllegalArgumentException if the error exceeds the allowed limits of [0, +Math.PI] - */ - @NonNull - public Builder setErrorRadians(double errorRadians) { - if (errorRadians < 0.0 || errorRadians > Math.PI) { - throw new IllegalArgumentException( - "Invalid error radians: " + errorRadians); - } - mErrorRadians = errorRadians; - return this; - } - - /** - * Set the angle confidence level - * - * @param confidenceLevel level of confidence of the angle measurement - * @throws IllegalArgumentException if the error exceeds the allowed limits of [0.0, 1.0] - */ - @NonNull - public Builder setConfidenceLevel(double confidenceLevel) { - if (confidenceLevel < 0.0 || confidenceLevel > 1.0) { - throw new IllegalArgumentException( - "Invalid confidence level: " + confidenceLevel); - } - mConfidenceLevel = confidenceLevel; - return this; - } - - /** - * Build the {@link AngleMeasurement} object - * - * @throws IllegalStateException if angle, error, or confidence values are missing - */ - @NonNull - public AngleMeasurement build() { - if (Double.isNaN(mRadians)) { - throw new IllegalStateException("Angle is not set"); - } - - if (Double.isNaN(mErrorRadians)) { - throw new IllegalStateException("Angle error is not set"); - } - - if (Double.isNaN(mConfidenceLevel)) { - throw new IllegalStateException("Angle confidence level is not set"); - } - - return new AngleMeasurement(mRadians, mErrorRadians, mConfidenceLevel); - } - } } diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java index 3d8626b98bed..db04ad16c191 100644 --- a/core/java/android/uwb/AngleOfArrivalMeasurement.java +++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java @@ -116,9 +116,8 @@ public final class AngleOfArrivalMeasurement implements Parcelable { new Creator<AngleOfArrivalMeasurement>() { @Override public AngleOfArrivalMeasurement createFromParcel(Parcel in) { - Builder builder = new Builder(); - - builder.setAzimuth(in.readParcelable(AngleMeasurement.class.getClassLoader())); + Builder builder = + new Builder(in.readParcelable(AngleMeasurement.class.getClassLoader())); builder.setAltitude(in.readParcelable(AngleMeasurement.class.getClassLoader())); @@ -135,18 +134,16 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * Builder class for {@link AngleOfArrivalMeasurement}. */ public static final class Builder { - private AngleMeasurement mAzimuthAngleMeasurement = null; + private final AngleMeasurement mAzimuthAngleMeasurement; private AngleMeasurement mAltitudeAngleMeasurement = null; /** - * Set the azimuth angle + * Constructs an {@link AngleOfArrivalMeasurement} object * - * @param azimuthAngle azimuth angle + * @param azimuthAngle the azimuth angle of the measurement */ - @NonNull - public Builder setAzimuth(@NonNull AngleMeasurement azimuthAngle) { + public Builder(@NonNull AngleMeasurement azimuthAngle) { mAzimuthAngleMeasurement = azimuthAngle; - return this; } /** @@ -162,15 +159,9 @@ public final class AngleOfArrivalMeasurement implements Parcelable { /** * Build the {@link AngleOfArrivalMeasurement} object - * - * @throws IllegalStateException if the required azimuth angle is not provided */ @NonNull public AngleOfArrivalMeasurement build() { - if (mAzimuthAngleMeasurement == null) { - throw new IllegalStateException("Azimuth angle measurement is not set"); - } - return new AngleOfArrivalMeasurement(mAzimuthAngleMeasurement, mAltitudeAngleMeasurement); } diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl index 468a69c7bddb..4036892fb9e7 100644 --- a/core/java/android/uwb/IUwbAdapter.aidl +++ b/core/java/android/uwb/IUwbAdapter.aidl @@ -62,9 +62,6 @@ interface IUwbAdapter { /** * Request to open a new ranging session * - * This function must return before calling any functions in - * IUwbAdapterCallbacks. - * * This function does not start the ranging session, but all necessary * components must be initialized and ready to start a new ranging * session prior to calling IUwbAdapterCallback#onRangingOpened. @@ -77,12 +74,16 @@ interface IUwbAdapter { * RANGING_SESSION_OPEN_THRESHOLD_MS milliseconds of #openRanging being called * if the ranging session fails to be opened. * + * If the provided sessionHandle is already open for the calling client, then + * #onRangingOpenFailed must be called and the new session must not be opened. + * + * @param sessionHandle the session handle to open ranging for * @param rangingCallbacks the callbacks used to deliver ranging information * @param parameters the configuration to use for ranging - * @return a SessionHandle used to identify this ranging request */ - SessionHandle openRanging(in IUwbRangingCallbacks rangingCallbacks, - in PersistableBundle parameters); + void openRanging(in SessionHandle sessionHandle, + in IUwbRangingCallbacks rangingCallbacks, + in PersistableBundle parameters); /** * Request to start ranging diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java index c0d818774ba0..85f2c1ccc180 100644 --- a/core/java/android/uwb/RangingManager.java +++ b/core/java/android/uwb/RangingManager.java @@ -17,6 +17,7 @@ package android.uwb; import android.annotation.NonNull; +import android.os.CancellationSignal; import android.os.PersistableBundle; import android.os.RemoteException; import android.util.Log; @@ -32,6 +33,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub { private final IUwbAdapter mAdapter; private final Hashtable<SessionHandle, RangingSession> mRangingSessionTable = new Hashtable<>(); + private int mNextSessionId = 1; public RangingManager(IUwbAdapter adapter) { mAdapter = adapter; @@ -44,29 +46,26 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub { * @param executor {@link Executor} to run callbacks * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession} * that is being opened. - * @return a new {@link RangingSession} + * @return a {@link CancellationSignal} that may be used to cancel the opening of the + * {@link RangingSession}. */ - public RangingSession openSession(@NonNull PersistableBundle params, @NonNull Executor executor, + public CancellationSignal openSession(@NonNull PersistableBundle params, + @NonNull Executor executor, @NonNull RangingSession.Callback callbacks) { - SessionHandle sessionHandle; - try { - sessionHandle = mAdapter.openRanging(this, params); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - synchronized (this) { - if (hasSession(sessionHandle)) { - Log.w(TAG, "Newly created session unexpectedly reuses an active SessionHandle"); - executor.execute(() -> callbacks.onClosed( - RangingSession.Callback.REASON_GENERIC_ERROR, - new PersistableBundle())); - } - + SessionHandle sessionHandle = new SessionHandle(mNextSessionId++); RangingSession session = new RangingSession(executor, callbacks, mAdapter, sessionHandle); mRangingSessionTable.put(sessionHandle, session); - return session; + try { + mAdapter.openRanging(sessionHandle, this, params); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + CancellationSignal cancellationSignal = new CancellationSignal(); + cancellationSignal.setOnCancelListener(() -> session.close()); + return cancellationSignal; } } diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java index 63a6d058f358..844bbbe7970b 100644 --- a/core/java/android/uwb/UwbManager.java +++ b/core/java/android/uwb/UwbManager.java @@ -25,6 +25,7 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; +import android.os.CancellationSignal; import android.os.IBinder; import android.os.PersistableBundle; import android.os.RemoteException; @@ -228,14 +229,14 @@ public final class UwbManager { * @param callbacks {@link RangingSession.Callback} to associate with the * {@link RangingSession} that is being opened. * - * @return an {@link AutoCloseable} that is able to be used to close or cancel the opening of a + * @return an {@link CancellationSignal} that is able to be used to cancel the opening of a * {@link RangingSession} that has been requested through {@link #openRangingSession} * but has not yet been made available by * {@link RangingSession.Callback#onOpened(RangingSession)}. */ @NonNull @RequiresPermission(Manifest.permission.UWB_PRIVILEGED) - public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters, + public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters, @NonNull @CallbackExecutor Executor executor, @NonNull RangingSession.Callback callbacks) { return mRangingManager.openSession(parameters, executor, callbacks); diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS index a86984f44a41..31f6f6afdd53 100644 --- a/core/java/android/view/OWNERS +++ b/core/java/android/view/OWNERS @@ -80,5 +80,6 @@ per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS per-file Window*.aidl = file:/services/core/java/com/android/server/wm/OWNERS # Scroll Capture +per-file *ScrollCapture*.aidl = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS per-file *ScrollCapture*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS per-file *CaptureHelper*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 10f6c610d5d3..96818fa26a73 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -67,7 +67,7 @@ import java.util.function.Consumer; * <p>Content capture provides real-time, continuous capture of application activity, display and * events to an intelligence service that is provided by the Android system. The intelligence * service then uses that info to mediate and speed user journey through different apps. For - * example, when the user receives a restaurant address in a chat app and switchs to a map app + * example, when the user receives a restaurant address in a chat app and switches to a map app * to search for that restaurant, the intelligence service could offer an autofill dialog to * let the user automatically select its address. * diff --git a/core/java/com/android/internal/compat/AndroidBuildClassifier.java b/core/java/com/android/internal/compat/AndroidBuildClassifier.java index 0b937fad7df1..364db06976a0 100644 --- a/core/java/com/android/internal/compat/AndroidBuildClassifier.java +++ b/core/java/com/android/internal/compat/AndroidBuildClassifier.java @@ -31,4 +31,14 @@ public class AndroidBuildClassifier { public boolean isFinalBuild() { return "REL".equals(Build.VERSION.CODENAME); } + + /** + * The current platform SDK version. + */ + public int platformTargetSdk() { + if (isFinalBuild()) { + return Build.VERSION.SDK_INT; + } + return Build.VERSION_CODES.CUR_DEVELOPMENT; + } } diff --git a/core/java/com/android/internal/compat/OverrideAllowedState.java b/core/java/com/android/internal/compat/OverrideAllowedState.java index c0bbe5082131..e408be2ab471 100644 --- a/core/java/com/android/internal/compat/OverrideAllowedState.java +++ b/core/java/com/android/internal/compat/OverrideAllowedState.java @@ -34,7 +34,8 @@ public final class OverrideAllowedState implements Parcelable { DISABLED_NON_TARGET_SDK, DISABLED_TARGET_SDK_TOO_HIGH, DEFERRED_VERIFICATION, - LOGGING_ONLY_CHANGE + LOGGING_ONLY_CHANGE, + PLATFORM_TOO_OLD }) @Retention(RetentionPolicy.SOURCE) public @interface State { @@ -65,6 +66,10 @@ public final class OverrideAllowedState implements Parcelable { * Change is marked as logging only, and cannot be toggled. */ public static final int LOGGING_ONLY_CHANGE = 5; + /** + * Change is gated by a target sdk version newer than the current platform sdk version. + */ + public static final int PLATFORM_TOO_OLD = 6; @State public final int state; @@ -123,6 +128,11 @@ public final class OverrideAllowedState implements Parcelable { throw new SecurityException(String.format( "Cannot override %1$d because it is marked as a logging-only change.", changeId)); + case PLATFORM_TOO_OLD: + throw new SecurityException(String.format( + "Cannot override %1$d for %2$s because the change's targetSdk threshold " + + "(%3$d) is above the platform sdk.", + changeId, packageName, changeIdTargetSdk)); } } @@ -170,6 +180,8 @@ public final class OverrideAllowedState implements Parcelable { return "DEFERRED_VERIFICATION"; case LOGGING_ONLY_CHANGE: return "LOGGING_ONLY_CHANGE"; + case PLATFORM_TOO_OLD: + return "PLATFORM_TOO_OLD"; } return "UNKNOWN"; } diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS index d284d5167843..8e68be0f742a 100644 --- a/core/java/com/android/internal/widget/OWNERS +++ b/core/java/com/android/internal/widget/OWNERS @@ -1,4 +1,6 @@ per-file PointerLocationView.java = michaelwr@google.com, svv@google.com +per-file RecyclerView.java = mount@google.com +per-file ViewPager.java = mount@google.com # LockSettings related per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index c01f741862b1..ed84434adff5 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -630,6 +630,12 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char saveResolvedClassesDelayMsOptsBuf[ sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX]; char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX]; + char madviseWillNeedFileSizeVdex[ + sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX]; + char madviseWillNeedFileSizeOdex[ + sizeof("-XMadviseWillNeedOdexFileSize:")-1 + PROPERTY_VALUE_MAX]; + char madviseWillNeedFileSizeArt[ + sizeof("-XMadviseWillNeedArtFileSize:")-1 + PROPERTY_VALUE_MAX]; char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX]; char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX]; char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX]; @@ -838,6 +844,22 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:"); /* + * Use default platform configuration as limits for madvising, + * when no properties are specified. + */ + parseRuntimeOption("dalvik.vm.madvise.vdexfile.size", + madviseWillNeedFileSizeVdex, + "-XMadviseWillNeedVdexFileSize:"); + + parseRuntimeOption("dalvik.vm.madvise.odexfile.size", + madviseWillNeedFileSizeOdex, + "-XMadviseWillNeedOdexFileSize:"); + + parseRuntimeOption("dalvik.vm.madvise.artfile.size", + madviseWillNeedFileSizeArt, + "-XMadviseWillNeedArtFileSize:"); + + /* * Profile related options. */ parseRuntimeOption("dalvik.vm.hot-startup-method-samples", hotstartupsamplesOptsBuf, diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index f71b42c4793f..249950419441 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -1516,7 +1516,9 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, res = JNI_TRUE; } else { jniThrowException(env, "java/util/NoSuchElementException", - "Death link does not exist"); + base::StringPrintf("Death link does not exist (%s)", + statusToString(err).c_str()) + .c_str()); } } diff --git a/core/proto/android/app/OWNERS b/core/proto/android/app/OWNERS index 296abd18aadc..cc479e61b855 100644 --- a/core/proto/android/app/OWNERS +++ b/core/proto/android/app/OWNERS @@ -1 +1 @@ -per-file location_time_zone_manager.proto = nfuller@google.com, mingaleev@google.com +per-file location_time_zone_manager.proto, time_zone_detector.proto = nfuller@google.com, mingaleev@google.com diff --git a/core/proto/android/app/location_time_zone_manager.proto b/core/proto/android/app/location_time_zone_manager.proto index f44d5495f132..891e9fca36aa 100644 --- a/core/proto/android/app/location_time_zone_manager.proto +++ b/core/proto/android/app/location_time_zone_manager.proto @@ -17,6 +17,7 @@ syntax = "proto2"; package android.app.time; +import "frameworks/base/core/proto/android/app/time_zone_detector.proto"; import "frameworks/base/core/proto/android/privacy.proto"; option java_multiple_files = true; @@ -31,15 +32,6 @@ message LocationTimeZoneManagerServiceStateProto { repeated TimeZoneProviderStateProto secondary_provider_states = 3; } -// Represents a GeolocationTimeZoneSuggestion that can be / has been passed to the time zone -// detector. -message GeolocationTimeZoneSuggestionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - repeated string zone_ids = 1; - repeated string debug_info = 2; -} - // The state tracked for a LocationTimeZoneProvider. message TimeZoneProviderStateProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/app/time_zone_detector.proto b/core/proto/android/app/time_zone_detector.proto new file mode 100644 index 000000000000..b33ca1d4f476 --- /dev/null +++ b/core/proto/android/app/time_zone_detector.proto @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto2"; +package android.app.time; + +import "frameworks/base/core/proto/android/privacy.proto"; + +option java_multiple_files = true; +option java_outer_classname = "TimeZoneDetectorProto"; + +// Represents a GeolocationTimeZoneSuggestion that can be / has been passed to the time zone +// detector. +message GeolocationTimeZoneSuggestionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + repeated string zone_ids = 1; + repeated string debug_info = 2; +} + +/* + * An obfuscated and simplified time zone suggestion for metrics use. + * + * The suggestion's time zone IDs (which relate to location) are obfuscated by + * mapping them to an ordinal. When the ordinal is assigned consistently across + * several objects (i.e. so the same time zone ID is always mapped to the same + * ordinal), this allows comparisons between those objects. For example, we can + * answer "did these two suggestions agree?", "does the suggestion match the + * device's current time zone?", without leaking knowledge of location. Ordinals + * are also significantly more compact than full IANA TZDB IDs, albeit highly + * unstable and of limited use. + */ +message MetricsTimeZoneSuggestion { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + enum Type { + CERTAIN = 1; + UNCERTAIN = 2; + } + optional Type type = 1; + + // The ordinals for time zone(s) in the suggestion. Always empty for + // UNCERTAIN, and can be empty for CERTAIN, for example when the device is in + // a disputed area / on an ocean. + repeated uint32 time_zone_ordinals = 2; +} diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8ac00dceea9e..4a06671d9f27 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3605,6 +3605,8 @@ <string name="ext_media_checking_notification_title">Checking <xliff:g id="name" example="SD card">%s</xliff:g>\u2026</string> <!-- Notification body when external media is being checked [CHAR LIMIT=NONE] --> <string name="ext_media_checking_notification_message">Reviewing current content</string> + <!-- TV specific notification body when external media is being checked [CHAR LIMIT=75] --> + <string name="ext_media_checking_notification_message" product="tv">Analyzing media storage</string> <!-- Notification body when new external media is detected [CHAR LIMIT=30] --> <string name="ext_media_new_notification_title">New <xliff:g id="name" example="SD card">%s</xliff:g></string> @@ -3612,11 +3614,15 @@ <string name="ext_media_new_notification_title" product="automotive"><xliff:g id="name" example="SD card">%s</xliff:g> isn\u2019t working</string> <!-- Notification body when new external media is detected [CHAR LIMIT=NONE] --> <string name="ext_media_new_notification_message">Tap to set up</string> + <!-- TV specific notification body when new external media is detected [CHAR LIMIT=75] --> + <string name="ext_media_new_notification_message" product="tv">Select to set up</string> <!-- Automotive specific notification body when new external media is detected. [CHAR LIMIT=NONE] --> <string name="ext_media_new_notification_message" product="automotive">You may need to reformat the device. Tap to eject.</string> <!-- Notification body when external media is ready for use [CHAR LIMIT=NONE] --> <string name="ext_media_ready_notification_message">For transferring photos and media</string> + <!-- TV specific notification body when external media is ready for use [CHAR LIMIT=75] --> + <string name="ext_media_ready_notification_message" product="tv">Browse media files</string> <!-- Notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] --> <string name="ext_media_unmountable_notification_title">Issue with <xliff:g id="name" example="SD card">%s</xliff:g></string> @@ -3635,8 +3641,8 @@ <string name="ext_media_unsupported_notification_title" product="automotive"><xliff:g id="name" example="SD card">%s</xliff:g> isn\u2019t working</string> <!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] --> <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string> - <!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] --> - <string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string> + <!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=75] --> + <string name="ext_media_unsupported_notification_message" product="tv">Select to set up <xliff:g id="name" example="SD card">%s</xliff:g> in a supported format.</string> <!-- Automotive specific notification body when external media is unsupported [CHAR LIMIT=NONE] --> <string name="ext_media_unsupported_notification_message" product="automotive">You may need to reformat the device</string> diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java index 2c1bbf0d0b83..aa2eb63ae4b8 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -232,7 +232,7 @@ public final class LooperStatsTest { assertThat(entry3.handlerClassName).isEqualTo( "com.android.internal.os.LooperStatsTest$TestHandlerSecond"); assertThat(entry3.messageName).startsWith( - "com.android.internal.os.LooperStatsTest-$$ExternalSyntheticLambda"); + "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4"); assertThat(entry3.messageCount).isEqualTo(1); assertThat(entry3.recordedMessageCount).isEqualTo(1); assertThat(entry3.exceptionCount).isEqualTo(0); diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java index c01bb75c32aa..e41805dd3a59 100644 --- a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java +++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java @@ -22,7 +22,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.os.PersistableBundle; import android.os.RemoteException; @@ -32,6 +31,7 @@ import androidx.test.filters.SmallTest; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import java.util.concurrent.Executor; @@ -42,51 +42,23 @@ import java.util.concurrent.Executor; @RunWith(AndroidJUnit4.class) public class RangingManagerTest { - private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class); private static final Executor EXECUTOR = UwbTestUtils.getExecutor(); private static final PersistableBundle PARAMS = new PersistableBundle(); private static final @RangingChangeReason int REASON = RangingChangeReason.UNKNOWN; @Test public void testOpenSession_OpenRangingInvoked() throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); + IUwbAdapter adapter = mock(IUwbAdapter.class); + RangingManager rangingManager = new RangingManager(adapter); RangingSession.Callback callback = mock(RangingSession.Callback.class); rangingManager.openSession(PARAMS, EXECUTOR, callback); - verify(ADAPTER, times(1)).openRanging(eq(rangingManager), eq(PARAMS)); - } - - @Test - public void testOpenSession_ErrorIfSameSessionHandleReturned() throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - SessionHandle handle = new SessionHandle(1); - when(ADAPTER.openRanging(any(), any())).thenReturn(handle); - - rangingManager.openSession(PARAMS, EXECUTOR, callback); - - // Calling openSession will cause the same session handle to be returned. The onClosed - // callback should be invoked - RangingSession.Callback callback2 = mock(RangingSession.Callback.class); - rangingManager.openSession(PARAMS, EXECUTOR, callback2); - verify(callback, times(0)).onClosed(anyInt(), any()); - verify(callback2, times(1)).onClosed(anyInt(), any()); - } - - @Test - public void testOnRangingOpened_ValidSessionHandle() throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); - RangingSession.Callback callback = mock(RangingSession.Callback.class); - SessionHandle handle = new SessionHandle(1); - when(ADAPTER.openRanging(any(), any())).thenReturn(handle); - - rangingManager.openSession(PARAMS, EXECUTOR, callback); - rangingManager.onRangingOpened(handle); - verify(callback, times(1)).onOpened(any()); + verify(adapter, times(1)).openRanging(any(), eq(rangingManager), eq(PARAMS)); } @Test public void testOnRangingOpened_InvalidSessionHandle() throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); + IUwbAdapter adapter = mock(IUwbAdapter.class); + RangingManager rangingManager = new RangingManager(adapter); RangingSession.Callback callback = mock(RangingSession.Callback.class); rangingManager.onRangingOpened(new SessionHandle(2)); @@ -95,18 +67,20 @@ public class RangingManagerTest { @Test public void testOnRangingOpened_MultipleSessionsRegistered() throws RemoteException { - SessionHandle sessionHandle1 = new SessionHandle(1); - SessionHandle sessionHandle2 = new SessionHandle(2); + IUwbAdapter adapter = mock(IUwbAdapter.class); RangingSession.Callback callback1 = mock(RangingSession.Callback.class); RangingSession.Callback callback2 = mock(RangingSession.Callback.class); + ArgumentCaptor<SessionHandle> sessionHandleCaptor = + ArgumentCaptor.forClass(SessionHandle.class); - when(ADAPTER.openRanging(any(), any())) - .thenReturn(sessionHandle1) - .thenReturn(sessionHandle2); - - RangingManager rangingManager = new RangingManager(ADAPTER); + RangingManager rangingManager = new RangingManager(adapter); rangingManager.openSession(PARAMS, EXECUTOR, callback1); + verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle1 = sessionHandleCaptor.getValue(); + rangingManager.openSession(PARAMS, EXECUTOR, callback2); + verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle2 = sessionHandleCaptor.getValue(); rangingManager.onRangingOpened(sessionHandle1); verify(callback1, times(1)).onOpened(any()); @@ -119,12 +93,17 @@ public class RangingManagerTest { @Test public void testCorrectCallbackInvoked() throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); + IUwbAdapter adapter = mock(IUwbAdapter.class); + RangingManager rangingManager = new RangingManager(adapter); RangingSession.Callback callback = mock(RangingSession.Callback.class); - SessionHandle handle = new SessionHandle(1); - when(ADAPTER.openRanging(any(), any())).thenReturn(handle); + + ArgumentCaptor<SessionHandle> sessionHandleCaptor = + ArgumentCaptor.forClass(SessionHandle.class); rangingManager.openSession(PARAMS, EXECUTOR, callback); + verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle handle = sessionHandleCaptor.getValue(); + rangingManager.onRangingOpened(handle); verify(callback, times(1)).onOpened(any()); @@ -156,20 +135,23 @@ public class RangingManagerTest { @Test public void testOnRangingClosed_MultipleSessionsRegistered() throws RemoteException { + IUwbAdapter adapter = mock(IUwbAdapter.class); // Verify that if multiple sessions are registered, only the session that is // requested to close receives the associated callbacks - SessionHandle sessionHandle1 = new SessionHandle(1); - SessionHandle sessionHandle2 = new SessionHandle(2); RangingSession.Callback callback1 = mock(RangingSession.Callback.class); RangingSession.Callback callback2 = mock(RangingSession.Callback.class); - when(ADAPTER.openRanging(any(), any())) - .thenReturn(sessionHandle1) - .thenReturn(sessionHandle2); + RangingManager rangingManager = new RangingManager(adapter); + ArgumentCaptor<SessionHandle> sessionHandleCaptor = + ArgumentCaptor.forClass(SessionHandle.class); - RangingManager rangingManager = new RangingManager(ADAPTER); rangingManager.openSession(PARAMS, EXECUTOR, callback1); + verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle1 = sessionHandleCaptor.getValue(); + rangingManager.openSession(PARAMS, EXECUTOR, callback2); + verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle2 = sessionHandleCaptor.getValue(); rangingManager.onRangingClosed(sessionHandle1, REASON, PARAMS); verify(callback1, times(1)).onClosed(anyInt(), any()); @@ -182,19 +164,22 @@ public class RangingManagerTest { @Test public void testOnRangingReport_MultipleSessionsRegistered() throws RemoteException { - SessionHandle sessionHandle1 = new SessionHandle(1); - SessionHandle sessionHandle2 = new SessionHandle(2); + IUwbAdapter adapter = mock(IUwbAdapter.class); RangingSession.Callback callback1 = mock(RangingSession.Callback.class); RangingSession.Callback callback2 = mock(RangingSession.Callback.class); - when(ADAPTER.openRanging(any(), any())) - .thenReturn(sessionHandle1) - .thenReturn(sessionHandle2); + ArgumentCaptor<SessionHandle> sessionHandleCaptor = + ArgumentCaptor.forClass(SessionHandle.class); - RangingManager rangingManager = new RangingManager(ADAPTER); + RangingManager rangingManager = new RangingManager(adapter); rangingManager.openSession(PARAMS, EXECUTOR, callback1); + verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle1 = sessionHandleCaptor.getValue(); + rangingManager.onRangingStarted(sessionHandle1, PARAMS); rangingManager.openSession(PARAMS, EXECUTOR, callback2); + verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle sessionHandle2 = sessionHandleCaptor.getValue(); rangingManager.onRangingStarted(sessionHandle2, PARAMS); rangingManager.onRangingResult(sessionHandle1, UwbTestUtils.getRangingReports(1)); @@ -232,17 +217,24 @@ public class RangingManagerTest { private void runReason(@RangingChangeReason int reasonIn, @RangingSession.Callback.Reason int reasonOut) throws RemoteException { - RangingManager rangingManager = new RangingManager(ADAPTER); + IUwbAdapter adapter = mock(IUwbAdapter.class); + RangingManager rangingManager = new RangingManager(adapter); RangingSession.Callback callback = mock(RangingSession.Callback.class); - SessionHandle handle = new SessionHandle(1); - when(ADAPTER.openRanging(any(), any())).thenReturn(handle); + + ArgumentCaptor<SessionHandle> sessionHandleCaptor = + ArgumentCaptor.forClass(SessionHandle.class); + rangingManager.openSession(PARAMS, EXECUTOR, callback); + verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any()); + SessionHandle handle = sessionHandleCaptor.getValue(); rangingManager.onRangingOpenFailed(handle, reasonIn, PARAMS); verify(callback, times(1)).onOpenFailed(eq(reasonOut), eq(PARAMS)); // Open a new session rangingManager.openSession(PARAMS, EXECUTOR, callback); + verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any()); + handle = sessionHandleCaptor.getValue(); rangingManager.onRangingOpened(handle); rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS); diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java index 8e7f7c562ade..75c6924a1939 100644 --- a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java +++ b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java @@ -16,34 +16,23 @@ package android.uwb; -import android.content.Context; -import android.content.pm.PackageManager; import android.os.SystemClock; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.Executor; public class UwbTestUtils { private UwbTestUtils() {} - public static boolean isUwbSupported(Context context) { - PackageManager packageManager = context.getPackageManager(); - return packageManager.hasSystemFeature(PackageManager.FEATURE_UWB); - } - public static AngleMeasurement getAngleMeasurement() { - return new AngleMeasurement.Builder() - .setRadians(getDoubleInRange(-Math.PI, Math.PI)) - .setErrorRadians(getDoubleInRange(0, Math.PI)) - .setConfidenceLevel(getDoubleInRange(0, 1)) - .build(); + return new AngleMeasurement( + getDoubleInRange(-Math.PI, Math.PI), + getDoubleInRange(0, Math.PI), + getDoubleInRange(0, 1)); } public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() { - return new AngleOfArrivalMeasurement.Builder() + return new AngleOfArrivalMeasurement.Builder(getAngleMeasurement()) .setAltitude(getAngleMeasurement()) - .setAzimuth(getAngleMeasurement()) .build(); } @@ -69,14 +58,6 @@ public class UwbTestUtils { .build(); } - public static List<RangingMeasurement> getRangingMeasurements(int num) { - List<RangingMeasurement> result = new ArrayList<>(); - for (int i = 0; i < num; i++) { - result.add(getRangingMeasurement()); - } - return result; - } - public static RangingReport getRangingReports(int numMeasurements) { RangingReport.Builder builder = new RangingReport.Builder(); for (int i = 0; i < numMeasurements; i++) { diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java index ed789f03f9ba..35b1c169f283 100644 --- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java +++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.ServiceManager; import android.os.ServiceSpecificException; -import android.security.usermanager.IKeystoreUserManager; +import android.security.maintenance.IKeystoreMaintenance; import android.system.keystore2.Domain; import android.system.keystore2.ResponseCode; import android.util.Log; @@ -34,9 +34,9 @@ public class AndroidKeyStoreMaintenance { public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; - private static IKeystoreUserManager getService() { - return IKeystoreUserManager.Stub.asInterface( - ServiceManager.checkService("android.security.usermanager")); + private static IKeystoreMaintenance getService() { + return IKeystoreMaintenance.Stub.asInterface( + ServiceManager.checkService("android.security.maintenance")); } /** @@ -121,4 +121,22 @@ public class AndroidKeyStoreMaintenance { return SYSTEM_ERROR; } } + + /** + * Queries user state from Keystore 2.0. + * + * @param userId - Android user id of the user. + * @return UserState enum variant as integer if successful or an error + */ + public static int getState(int userId) { + try { + return getService().getState(userId); + } catch (ServiceSpecificException e) { + Log.e(TAG, "getState failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 93658e69eac8..937f01ce3767 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -43,6 +43,7 @@ import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import android.security.keystore.KeystoreResponse; import android.security.keystore.UserNotAuthenticatedException; +import android.security.maintenance.UserState; import android.system.keystore2.Domain; import android.util.Log; @@ -196,6 +197,19 @@ public class KeyStore { public State state(int userId) { final int ret; try { + if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) { + int userState = AndroidKeyStoreMaintenance.getState(userId); + switch (userState) { + case UserState.UNINITIALIZED: + return KeyStore.State.UNINITIALIZED; + case UserState.LSKF_UNLOCKED: + return KeyStore.State.UNLOCKED; + case UserState.LSKF_LOCKED: + return KeyStore.State.LOCKED; + default: + throw new AssertionError(KeyStore.VALUE_CORRUPTED); + } + } ret = mBinder.getState(userId); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index f1eea820829c..11c36893d984 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -23,7 +23,6 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.res.Resources; import android.os.Build; -import android.security.KeyStore; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterCertificateChain; import android.security.keymaster.KeymasterDefs; @@ -34,9 +33,14 @@ import android.util.ArraySet; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.SecureRandom; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.spec.ECGenParameterSpec; import java.util.Collection; +import java.util.Random; import java.util.Set; /** @@ -256,22 +260,47 @@ public abstract class AttestationUtils { @NonNull public static X509Certificate[] attestDeviceIds(Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws DeviceIdAttestationException { - final KeymasterArguments attestArgs = prepareAttestationArgumentsForDeviceId( - context, idTypes, attestationChallenge); + String keystoreAlias = generateRandomAlias(); + KeyGenParameterSpec.Builder builder = + new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN) + .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) + .setDigests(KeyProperties.DIGEST_SHA256) + .setAttestationChallenge(attestationChallenge); - // Perform attestation. - final KeymasterCertificateChain outChain = new KeymasterCertificateChain(); - final int errorCode = KeyStore.getInstance().attestDeviceIds(attestArgs, outChain); - if (errorCode != KeyStore.NO_ERROR) { - throw new DeviceIdAttestationException("Unable to perform attestation", - KeyStore.getKeyStoreException(errorCode)); + if (idTypes != null) { + builder.setAttestationIds(idTypes); + builder.setDevicePropertiesAttestationIncluded(true); } try { - return parseCertificateChain(outChain); - } catch (KeyAttestationException e) { - throw new DeviceIdAttestationException(e.getMessage(), e); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); + keyPairGenerator.initialize(builder.build()); + keyPairGenerator.generateKeyPair(); + + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + + X509Certificate[] certificateChain = + (X509Certificate[]) keyStore.getCertificateChain(keystoreAlias); + + keyStore.deleteEntry(keystoreAlias); + + return certificateChain; + } catch (Exception e) { + throw new DeviceIdAttestationException("Unable to perform attestation", e); + } + } + + private static String generateRandomAlias() { + Random random = new SecureRandom(); + StringBuilder builder = new StringBuilder(); + // Pick random uppercase letters, A-Z. 20 of them gives us ~94 bits of entropy, which + // should prevent any conflicts with app-selected aliases, even for very unlucky users. + for (int i = 0; i < 20; ++i) { + builder.append(random.nextInt(26) + 'A'); } + return builder.toString(); } /** diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 72735a787b7f..5cb2c3b41517 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -467,8 +467,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * * @return The numeric namespace as configured in the keystore2_key_contexts files of Android's * SEPolicy. - * TODO b/171806779 link to public Keystore 2.0 documentation. - * See bug for more details for now. + * See <a href="https://source.android.com/security/keystore#access-control"> + * Keystore 2.0 access control</a> * @hide */ @SystemApi @@ -1042,9 +1042,9 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * keys between system and vendor components, e.g., WIFI settings and WPA supplicant. * * @param namespace Numeric SELinux namespace as configured in keystore2_key_contexts - * of Android's SEPolicy. - * TODO b/171806779 link to public Keystore 2.0 documentation. - * See bug for more details for now. + * of Android's SEPolicy. + * See <a href="https://source.android.com/security/keystore#access-control"> + * Keystore 2.0 access control</a> * @return this Builder object. * * @hide diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index d36695b9b410..fa852e33a1d8 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -340,11 +340,11 @@ public class AndroidKeyStoreProvider extends Provider { * @param keyStore The keystore2 backend. * @param alias The alias of the key in the Keystore database. * @param namespace The a Keystore namespace. This is used by system api only to request - * Android system specific keystore namespace, which can be configured - * in the device's SEPolicy. Third party apps and most system components - * set this parameter to -1 to indicate their application specific namespace. - * TODO b/171806779 link to public Keystore 2.0 documentation. - * See bug for more details for now. + * Android system specific keystore namespace, which can be configured + * in the device's SEPolicy. Third party apps and most system components + * set this parameter to -1 to indicate their application specific namespace. + * See <a href="https://source.android.com/security/keystore#access-control"> + * Keystore 2.0 access control</a> * @hide **/ @NonNull diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp index f8b4bdb1f4d5..50e0d336f981 100644 --- a/media/jni/soundpool/Sound.cpp +++ b/media/jni/soundpool/Sound.cpp @@ -99,8 +99,8 @@ static status_t decode(int fd, int64_t offset, int64_t length, __func__); break; } - int sampleSize = AMediaExtractor_readSampleData(ex.get(), buf, bufsize); - ALOGV("%s: read %d", __func__, sampleSize); + ssize_t sampleSize = AMediaExtractor_readSampleData(ex.get(), buf, bufsize); + ALOGV("%s: read %zd", __func__, sampleSize); if (sampleSize < 0) { sampleSize = 0; sawInputEOS = true; @@ -124,8 +124,8 @@ static status_t decode(int fd, int64_t offset, int64_t length, } AMediaCodecBufferInfo info; - const int status = AMediaCodec_dequeueOutputBuffer(codec.get(), &info, 1); - ALOGV("%s: dequeueoutput returned: %d", __func__, status); + const ssize_t status = AMediaCodec_dequeueOutputBuffer(codec.get(), &info, 1); + ALOGV("%s: dequeueoutput returned: %zd", __func__, status); if (status >= 0) { if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { ALOGV("%s: output EOS", __func__); @@ -167,10 +167,10 @@ static status_t decode(int fd, int64_t offset, int64_t length, } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { ALOGV("%s: no output buffer right now", __func__); } else if (status <= AMEDIA_ERROR_BASE) { - ALOGE("%s: decode error: %d", __func__, status); + ALOGE("%s: decode error: %zd", __func__, status); break; } else { - ALOGV("%s: unexpected info code: %d", __func__, status); + ALOGV("%s: unexpected info code: %zd", __func__, status); } } diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp index 73e319a5902e..f261bab0a20c 100644 --- a/media/jni/soundpool/Stream.cpp +++ b/media/jni/soundpool/Stream.cpp @@ -317,7 +317,8 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID, // audio track while the new one is being started and avoids processing them with // wrong audio audio buffer size (mAudioBufferSize) auto toggle = mToggle ^ 1; - void* userData = (void*)((uintptr_t)this | toggle); + // NOLINTNEXTLINE(performance-no-int-to-ptr) + void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle); audio_channel_mask_t soundChannelMask = sound->getChannelMask(); // When sound contains a valid channel mask, use it as is. // Otherwise, use stream count to calculate channel mask. @@ -386,6 +387,7 @@ exit: void Stream::staticCallback(int event, void* user, void* info) { const auto userAsInt = (uintptr_t)user; + // NOLINTNEXTLINE(performance-no-int-to-ptr) auto stream = reinterpret_cast<Stream*>(userAsInt & ~1); stream->callback(event, info, int(userAsInt & 1), 0 /* tries */); } diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp index 502ee00b583e..8b84bf3eb8d8 100644 --- a/media/jni/soundpool/StreamManager.cpp +++ b/media/jni/soundpool/StreamManager.cpp @@ -330,7 +330,7 @@ ssize_t StreamManager::removeFromQueues_l( // streams on mProcessingStreams are undergoing processing by the StreamManager thread // and do not participate in normal stream migration. - return found; + return (ssize_t)found; } void StreamManager::addToRestartQueue_l(Stream *stream) { diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp index 357cc63bd41e..a66d99fbd9f4 100644 --- a/media/jni/soundpool/android_media_SoundPool.cpp +++ b/media/jni/soundpool/android_media_SoundPool.cpp @@ -34,7 +34,8 @@ static struct fields_t { jclass mSoundPoolClass; } fields; static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) { - return (SoundPool*)env->GetLongField(thiz, fields.mNativeContext); + // NOLINTNEXTLINE(performance-no-int-to-ptr) + return reinterpret_cast<SoundPool*>(env->GetLongField(thiz, fields.mNativeContext)); } static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes"; struct audio_attributes_fields_t { diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt index a8f1a4d2a7f8..243e4ca4295a 100644 --- a/packages/Connectivity/framework/api/current.txt +++ b/packages/Connectivity/framework/api/current.txt @@ -143,6 +143,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); + ctor public ConnectivityManager.NetworkCallback(int); method public void onAvailable(@NonNull android.net.Network); method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); @@ -150,6 +151,7 @@ package android.net { method public void onLosing(@NonNull android.net.Network, int); method public void onLost(@NonNull android.net.Network); method public void onUnavailable(); + field public static final int FLAG_INCLUDE_LOCATION_INFO = 1; // 0x1 } public static interface ConnectivityManager.OnNetworkActiveListener { @@ -293,6 +295,7 @@ package android.net { method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); method public int getOwnerUid(); method public int getSignalStrength(); + method @NonNull public java.util.Set<java.lang.Integer> getSubIds(); method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); @@ -399,6 +402,11 @@ package android.net { method public android.net.NetworkRequest.Builder removeTransportType(int); method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>); + } + + public class ParseException extends java.lang.RuntimeException { + field public String response; } public class ProxyInfo implements android.os.Parcelable { diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt index d2ed73ef8298..4b3336644ef9 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -7,8 +7,9 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshot(); + method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); } @@ -51,6 +52,14 @@ package android.net { field public static final String TEST_TAP_PREFIX = "testtap"; } + public final class TestNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + ctor public TestNetworkSpecifier(@NonNull String); + method public int describeContents(); + method @Nullable public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkSpecifier> CREATOR; + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index a732430e6a9c..a98f14ea9408 100644 --- a/packages/Connectivity/framework/api/system-current.txt +++ b/packages/Connectivity/framework/api/system-current.txt @@ -296,6 +296,7 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>); method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); } diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index 45ed3179d78e..8c66db9a205a 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -16,10 +16,10 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; -import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; +import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; @@ -43,6 +43,7 @@ import android.net.SocketKeepalive.Callback; import android.net.TetheringManager.StartTetheringCallback; import android.net.TetheringManager.TetheringEventCallback; import android.net.TetheringManager.TetheringRequest; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; @@ -1314,7 +1315,7 @@ public class ConnectivityManager { } /** - * Returns an array of {@link android.net.NetworkCapabilities} objects, representing + * Returns an array of {@link NetworkCapabilities} objects, representing * the Networks that applications run by the given user will use by default. * @hide */ @@ -1394,11 +1395,19 @@ public class ConnectivityManager { } /** - * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This + * Get the {@link NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. * + * This will remove any location sensitive data in {@link TransportInfo} embedded in + * {@link NetworkCapabilities#getTransportInfo()}. Some transport info instances like + * {@link android.net.wifi.WifiInfo} contain location sensitive information. Retrieving + * this location sensitive information (subject to app's location permissions) will be + * noted by system. To include any location sensitive data in {@link TransportInfo}, + * use a {@link NetworkCallback} with + * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag. + * * @param network The {@link Network} object identifying the network in question. - * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. + * @return The {@link NetworkCapabilities} for the network, or {@code null}. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable @@ -1996,7 +2005,7 @@ public class ConnectivityManager { dup = createInvalidFd(); } return new NattSocketKeepalive(mService, network, dup, - INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback); + -1 /* Unused */, source, destination, executor, callback); } /** @@ -3244,6 +3253,54 @@ public class ConnectivityManager { */ public static class NetworkCallback { /** + * No flags associated with this callback. + * @hide + */ + public static final int FLAG_NONE = 0; + /** + * Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent + * via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}. + * <p> + * These include: + * <li> Some transport info instances (retrieved via + * {@link NetworkCapabilities#getTransportInfo()}) like {@link android.net.wifi.WifiInfo} + * contain location sensitive information. + * <li> OwnerUid (retrieved via {@link NetworkCapabilities#getOwnerUid()} is location + * sensitive for wifi suggestor apps (i.e using {@link WifiNetworkSuggestion}).</li> + * </p> + * <p> + * Note: + * <li> Retrieving this location sensitive information (subject to app's location + * permissions) will be noted by system. </li> + * <li> Without this flag any {@link NetworkCapabilities} provided via the callback does + * not include location sensitive info. + * </p> + */ + public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "FLAG_", value = { + FLAG_NONE, + FLAG_INCLUDE_LOCATION_INFO + }) + public @interface Flag { } + + /** + * All the valid flags for error checking. + */ + private static final int VALID_FLAGS = FLAG_INCLUDE_LOCATION_INFO; + + public NetworkCallback() { + this(FLAG_NONE); + } + + public NetworkCallback(@Flag int flags) { + Preconditions.checkArgument((flags & VALID_FLAGS) == flags); + mFlags = flags; + } + + /** * Called when the framework connects to a new network to evaluate whether it satisfies this * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} * callback. There is no guarantee that this new network will satisfy any requests, or that @@ -3380,7 +3437,7 @@ public class ConnectivityManager { * calling these methods while in a callback may return an outdated or even a null object. * * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this + * @param networkCapabilities The new {@link NetworkCapabilities} for this * network. */ public void onCapabilitiesChanged(@NonNull Network network, @@ -3449,6 +3506,7 @@ public class ConnectivityManager { public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} private NetworkRequest networkRequest; + private final int mFlags; } /** @@ -3638,14 +3696,15 @@ public class ConnectivityManager { } Messenger messenger = new Messenger(handler); Binder binder = new Binder(); + final int callbackFlags = callback.mFlags; if (reqType == LISTEN) { request = mService.listenForNetwork( - need, messenger, binder, callingPackageName, + need, messenger, binder, callbackFlags, callingPackageName, getAttributionTag()); } else { request = mService.requestNetwork( need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, - callingPackageName, getAttributionTag()); + callbackFlags, callingPackageName, getAttributionTag()); } if (request != null) { sCallbacks.put(request, callback); @@ -3692,7 +3751,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * <p>This method will attempt to find the best network that matches the passed * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the @@ -3776,7 +3835,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)} * but runs all the callbacks on the passed Handler. @@ -3798,7 +3857,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This function behaves identically to the non-timed-out version @@ -3833,7 +3892,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This method behaves identically to @@ -3878,7 +3937,7 @@ public class ConnectivityManager { /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This function behaves identically to the version that takes a NetworkCallback, but instead * of {@link NetworkCallback} a {@link PendingIntent} is used. This means @@ -4190,6 +4249,18 @@ public class ConnectivityManager { } /** + * @hide + */ + // TODO: Make it public api. + @SuppressLint("ExecutorRegistration") + public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { + final NetworkCapabilities nc = request.networkCapabilities; + final CallbackHandler cbHandler = new CallbackHandler(handler); + sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + } + + /** * Requests bandwidth update for a given {@link Network} and returns whether the update request * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying * network connection for updated bandwidth information. The caller will be notified via @@ -4898,7 +4969,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but + * Request a network to satisfy a set of {@link NetworkCapabilities}, but * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can * be used to request that the system provide a network without causing the network to be * in the foreground. @@ -4979,10 +5050,10 @@ public class ConnectivityManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK }) public void requestBackgroundNetwork(@NonNull NetworkRequest request, - @Nullable Handler handler, @NonNull NetworkCallback networkCallback) { + @NonNull Handler handler, @NonNull NetworkCallback networkCallback) { final NetworkCapabilities nc = request.networkCapabilities; sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, - TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler)); + TYPE_NONE, new CallbackHandler(handler)); } /** @@ -5040,4 +5111,21 @@ public class ConnectivityManager { throw e.rethrowFromSystemServer(); } } + + // The first network ID of IPSec tunnel interface. + private static final int TUN_INTF_NETID_START = 0xFC00; + // The network ID range of IPSec tunnel interface. + private static final int TUN_INTF_NETID_RANGE = 0x0400; + + /** + * Get the network ID range reserved for IPSec tunnel interfaces. + * + * @return A Range which indicates the network ID range of IPSec tunnel interface. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + public static Range<Integer> getIpSecNetIdRange() { + return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); + } } diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index cd49258d1c47..f9393e315b83 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -143,7 +143,7 @@ interface IConnectivityManager NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, - String callingPackageName, String callingAttributionTag); + int callbackFlags, String callingPackageName, String callingAttributionTag); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation, String callingPackageName, String callingAttributionTag); @@ -151,7 +151,7 @@ interface IConnectivityManager void releasePendingNetworkRequest(in PendingIntent operation); NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder, String callingPackageName, + in Messenger messenger, in IBinder binder, int callbackFlags, String callingPackageName, String callingAttributionTag); void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index c82cd3b4f357..058f3c999dd7 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -131,6 +132,7 @@ public final class NetworkCapabilities implements Parcelable { mPrivateDnsBroken = false; mRequestorUid = Process.INVALID_UID; mRequestorPackageName = null; + mSubIds = new ArraySet<>(); } /** @@ -159,6 +161,7 @@ public final class NetworkCapabilities implements Parcelable { mPrivateDnsBroken = nc.mPrivateDnsBroken; mRequestorUid = nc.mRequestorUid; mRequestorPackageName = nc.mRequestorPackageName; + mSubIds = new ArraySet<>(nc.mSubIds); } /** @@ -1048,6 +1051,16 @@ public final class NetworkCapabilities implements Parcelable { * * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have * this field cleared out. + * + * <p> + * This field will only be populated for VPN and wifi network suggestor apps (i.e using + * {@link WifiNetworkSuggestion}), and only for the network they own. + * In the case of wifi network suggestors apps, this field is also location sensitive, so the + * app needs to hold {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. If the + * app targets SDK version greater than or equal to {@link Build.VERSION_CODES#S}, then they + * also need to use {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} to get the info in their + * callback. The app will be blamed for location access if this field is included. + * </p> */ public int getOwnerUid() { return mOwnerUid; @@ -1655,6 +1668,7 @@ public final class NetworkCapabilities implements Parcelable { combineSSIDs(nc); combineRequestor(nc); combineAdministratorUids(nc); + combineSubIds(nc); } /** @@ -1674,8 +1688,9 @@ public final class NetworkCapabilities implements Parcelable { && satisfiedBySpecifier(nc) && (onlyImmutable || satisfiedBySignalStrength(nc)) && (onlyImmutable || satisfiedByUids(nc)) - && (onlyImmutable || satisfiedBySSID(nc))) - && (onlyImmutable || satisfiedByRequestor(nc)); + && (onlyImmutable || satisfiedBySSID(nc)) + && (onlyImmutable || satisfiedByRequestor(nc)) + && (onlyImmutable || satisfiedBySubIds(nc))); } /** @@ -1771,7 +1786,8 @@ public final class NetworkCapabilities implements Parcelable { && equalsOwnerUid(that) && equalsPrivateDnsBroken(that) && equalsRequestor(that) - && equalsAdministratorUids(that); + && equalsAdministratorUids(that) + && equalsSubIds(that); } @Override @@ -1793,7 +1809,8 @@ public final class NetworkCapabilities implements Parcelable { + Objects.hashCode(mPrivateDnsBroken) * 47 + Objects.hashCode(mRequestorUid) * 53 + Objects.hashCode(mRequestorPackageName) * 59 - + Arrays.hashCode(mAdministratorUids) * 61; + + Arrays.hashCode(mAdministratorUids) * 61 + + Objects.hashCode(mSubIds) * 67; } @Override @@ -1827,6 +1844,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeInt(mOwnerUid); dest.writeInt(mRequestorUid); dest.writeString(mRequestorPackageName); + dest.writeIntArray(CollectionUtils.toIntArray(mSubIds)); } public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR = @@ -1850,6 +1868,11 @@ public final class NetworkCapabilities implements Parcelable { netCap.mOwnerUid = in.readInt(); netCap.mRequestorUid = in.readInt(); netCap.mRequestorPackageName = in.readString(); + netCap.mSubIds = new ArraySet<>(); + final int[] subIdInts = Objects.requireNonNull(in.createIntArray()); + for (int i = 0; i < subIdInts.length; i++) { + netCap.mSubIds.add(subIdInts[i]); + } return netCap; } @Override @@ -1933,11 +1956,14 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" SSID: ").append(mSSID); } - if (mPrivateDnsBroken) { sb.append(" PrivateDnsBroken"); } + if (!mSubIds.isEmpty()) { + sb.append(" SubscriptionIds: ").append(mSubIds); + } + sb.append("]"); return sb.toString(); } @@ -2251,6 +2277,67 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Set of the subscription IDs that identifies the network or request, empty if none. + */ + @NonNull + private ArraySet<Integer> mSubIds = new ArraySet<>(); + + /** + * Sets the subscription ID set that associated to this network or request. + * + * @hide + */ + @NonNull + public NetworkCapabilities setSubIds(@NonNull Set<Integer> subIds) { + mSubIds = new ArraySet(Objects.requireNonNull(subIds)); + return this; + } + + /** + * Gets the subscription ID set that associated to this network or request. + * @return + */ + @NonNull + public Set<Integer> getSubIds() { + return new ArraySet<>(mSubIds); + } + + /** + * Tests if the subscription ID set of this network is the same as that of the passed one. + */ + private boolean equalsSubIds(@NonNull NetworkCapabilities nc) { + return Objects.equals(mSubIds, nc.mSubIds); + } + + /** + * Check if the subscription ID set requirements of this object are matched by the passed one. + * If specified in the request, the passed one need to have at least one subId and at least + * one of them needs to be in the request set. + */ + private boolean satisfiedBySubIds(@NonNull NetworkCapabilities nc) { + if (mSubIds.isEmpty()) return true; + if (nc.mSubIds.isEmpty()) return false; + for (final Integer subId : nc.mSubIds) { + if (mSubIds.contains(subId)) return true; + } + return false; + } + + /** + * Combine subscription ID set of the capabilities. + * + * <p>This is only legal if the subscription Ids are equal. + * + * <p>If both subscription IDs are not equal, they belong to different subscription + * (or no subscription). In this case, it would not make sense to add them together. + */ + private void combineSubIds(@NonNull NetworkCapabilities nc) { + if (!Objects.equals(mSubIds, nc.mSubIds)) { + throw new IllegalStateException("Can't combine two subscription ID sets"); + } + } + + /** * Builder class for NetworkCapabilities. * * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in @@ -2556,6 +2643,18 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Set the subscription ID set. + * + * @param subIds a set that represent the subscription IDs. Empty if clean up. + * @return this builder. + */ + @NonNull + public Builder setSubIds(@NonNull final Set<Integer> subIds) { + mCaps.setSubIds(subIds); + return this; + } + + /** * Builds the instance of the capabilities. * * @return the built instance of NetworkCapabilities. diff --git a/packages/Connectivity/framework/src/android/net/NetworkInfo.java b/packages/Connectivity/framework/src/android/net/NetworkInfo.java index d752901e2eb0..bb2349459331 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkInfo.java +++ b/packages/Connectivity/framework/src/android/net/NetworkInfo.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.Annotation.NetworkType; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; @@ -164,7 +163,7 @@ public class NetworkInfo implements Parcelable { * @param typeName a human-readable string for the network type, or an empty string or null. * @param subtypeName a human-readable string for the subtype, or an empty string or null. */ - public NetworkInfo(int type, @NetworkType int subtype, + public NetworkInfo(int type, int subtype, @Nullable String typeName, @Nullable String subtypeName) { if (!ConnectivityManager.isNetworkTypeValid(type) && type != ConnectivityManager.TYPE_NONE) { diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index b4a651c0607e..3fd95ee58df2 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -31,6 +31,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVIT import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; @@ -113,6 +114,10 @@ public class NetworkRequest implements Parcelable { * for the network (if any) that satisfies the default Internet * request. * + * - TRACK_BEST, which causes the framework to send callbacks about + * the single, highest scoring current network (if any) that matches + * the specified NetworkCapabilities. + * * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks * to retain the NET_CAPABILITY_FOREGROUND capability. A network with * no foreground requests is in the background. A network that has @@ -135,6 +140,7 @@ public class NetworkRequest implements Parcelable { REQUEST, BACKGROUND_REQUEST, TRACK_SYSTEM_DEFAULT, + TRACK_BEST, }; /** @@ -382,11 +388,17 @@ public class NetworkRequest implements Parcelable { return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() .setSubscriptionId(subId).build()); } catch (NumberFormatException nfe) { - // A StringNetworkSpecifier does not accept null or empty ("") strings. When network - // specifiers were strings a null string and an empty string were considered - // equivalent. Hence no meaning is attached to a null or empty ("") string. - return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null - : new StringNetworkSpecifier(networkSpecifier)); + // An EthernetNetworkSpecifier or TestNetworkSpecifier does not accept null or empty + // ("") strings. When network specifiers were strings a null string and an empty + // string were considered equivalent. Hence no meaning is attached to a null or + // empty ("") string. + if (TextUtils.isEmpty(networkSpecifier)) { + return setNetworkSpecifier((NetworkSpecifier) null); + } else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) { + return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier)); + } else { + return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier)); + } } } @@ -449,6 +461,21 @@ public class NetworkRequest implements Parcelable { } nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); } + + /** + * Sets the optional subscription ID set. + * <p> + * This specify the subscription IDs requirement. + * A network will satisfy this request only if it matches one of the subIds in this set. + * An empty set matches all networks, including those without a subId. + * + * @param subIds A {@code Set} that represents subscription IDs. + */ + @NonNull + public Builder setSubIds(@NonNull Set<Integer> subIds) { + mNetworkCapabilities.setSubIds(subIds); + return this; + } } // implement the Parcelable interface diff --git a/packages/Connectivity/framework/src/android/net/NetworkState.java b/packages/Connectivity/framework/src/android/net/NetworkState.java index d01026566ca0..9b69674728a8 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkState.java +++ b/packages/Connectivity/framework/src/android/net/NetworkState.java @@ -22,7 +22,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.util.Slog; +import android.util.Log; /** * Snapshot of network state. @@ -83,7 +83,7 @@ public class NetworkState implements Parcelable { if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) { if (networkInfo.isRoaming() == networkCapabilities .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) { - Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo + Log.wtf("NetworkState", "Roaming state disagreement between " + networkInfo + " and " + networkCapabilities); } } diff --git a/core/java/android/net/ParseException.java b/packages/Connectivity/framework/src/android/net/ParseException.java index bcfdd7ef09cc..bcfdd7ef09cc 100644 --- a/core/java/android/net/ParseException.java +++ b/packages/Connectivity/framework/src/android/net/ParseException.java diff --git a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java index d37c4691ddde..53d966937a70 100644 --- a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java +++ b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java @@ -92,7 +92,7 @@ public final class QosSocketInfo implements Parcelable { Objects.requireNonNull(socket, "socket cannot be null"); mNetwork = Objects.requireNonNull(network, "network cannot be null"); - mParcelFileDescriptor = ParcelFileDescriptor.dup(socket.getFileDescriptor$()); + mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket); mLocalSocketAddress = new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()); } @@ -114,10 +114,10 @@ public final class QosSocketInfo implements Parcelable { try { return new InetSocketAddress(InetAddress.getByAddress(address), port); } catch (final UnknownHostException e) { - /* The catch block was purposely left empty. UnknownHostException will never be thrown + /* This can never happen. UnknownHostException will never be thrown since the address provided is numeric and non-null. */ + throw new RuntimeException("UnknownHostException on numeric address", e); } - return new InetSocketAddress(); } @Override diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java b/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java new file mode 100644 index 000000000000..b7470a591d20 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify test interfaces. + * + * @see TestNetworkManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class TestNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public TestNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TestNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((TestNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "TestNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Creator<TestNetworkSpecifier> CREATOR = + new Creator<TestNetworkSpecifier>() { + public TestNetworkSpecifier createFromParcel(Parcel in) { + return new TestNetworkSpecifier(in.readString()); + } + public TestNetworkSpecifier[] newArray(int size) { + return new TestNetworkSpecifier[size]; + } + }; +} diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index c1dca5df1b2f..16a946dc7bc6 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -138,9 +138,6 @@ public class DynamicSystemInstallationService extends Service private long mCurrentPartitionSize; private long mCurrentPartitionInstalledSize; - private boolean mJustCancelledByUser; - private boolean mKeepNotification; - // This is for testing only now private boolean mEnableWhenCompleted; @@ -174,11 +171,6 @@ public class DynamicSystemInstallationService extends Service if (cache != null) { cache.flush(); } - - if (!mKeepNotification) { - // Cancel the persistent notification. - mNM.cancel(NOTIFICATION_ID); - } } @Override @@ -231,9 +223,11 @@ public class DynamicSystemInstallationService extends Service return; } + boolean removeNotification = false; switch (result) { case RESULT_CANCELLED: postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null); + removeNotification = true; break; case RESULT_ERROR_IO: @@ -251,7 +245,7 @@ public class DynamicSystemInstallationService extends Service } // if it's not successful, reset the task and stop self. - resetTaskAndStop(); + resetTaskAndStop(removeNotification); } private void executeInstallCommand(Intent intent) { @@ -302,12 +296,12 @@ public class DynamicSystemInstallationService extends Service return; } - stopForeground(true); - mJustCancelledByUser = true; - if (mInstallTask.cancel(false)) { - // Will stopSelf() in onResult() + // onResult() would call resetTaskAndStop() upon task completion. Log.d(TAG, "Cancel request filed successfully"); + // Dismiss the notification as soon as possible as DynamicSystemManager.remove() may + // block. + stopForeground(STOP_FOREGROUND_REMOVE); } else { Log.e(TAG, "Trying to cancel installation while it's already completed."); } @@ -322,8 +316,7 @@ public class DynamicSystemInstallationService extends Service if (!isDynamicSystemInstalled() && (getStatus() != STATUS_READY)) { Log.e(TAG, "Trying to discard AOT while there is no complete installation"); // Stop foreground state and dismiss stale notification. - stopForeground(STOP_FOREGROUND_REMOVE); - resetTaskAndStop(); + resetTaskAndStop(true); return; } @@ -331,8 +324,8 @@ public class DynamicSystemInstallationService extends Service getString(R.string.toast_dynsystem_discarded), Toast.LENGTH_LONG).show(); - resetTaskAndStop(); postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null); + resetTaskAndStop(true); mDynSystem.remove(); } @@ -412,12 +405,13 @@ public class DynamicSystemInstallationService extends Service } private void resetTaskAndStop() { - mInstallTask = null; + resetTaskAndStop(/* removeNotification= */ false); + } - new Handler().postDelayed(() -> { - stopForeground(STOP_FOREGROUND_DETACH); - stopSelf(); - }, 50); + private void resetTaskAndStop(boolean removeNotification) { + mInstallTask = null; + stopForeground(removeNotification ? STOP_FOREGROUND_REMOVE : STOP_FOREGROUND_DETACH); + stopSelf(); } private void prepareNotification() { @@ -525,7 +519,7 @@ public class DynamicSystemInstallationService extends Service private void postStatus(int status, int cause, Throwable detail) { String statusString; String causeString; - mKeepNotification = false; + boolean notifyOnNotificationBar = true; switch (status) { case STATUS_NOT_STARTED: @@ -551,18 +545,16 @@ public class DynamicSystemInstallationService extends Service break; case CAUSE_INSTALL_CANCELLED: causeString = "INSTALL_CANCELLED"; + notifyOnNotificationBar = false; break; case CAUSE_ERROR_IO: causeString = "ERROR_IO"; - mKeepNotification = true; break; case CAUSE_ERROR_INVALID_URL: causeString = "ERROR_INVALID_URL"; - mKeepNotification = true; break; case CAUSE_ERROR_EXCEPTION: causeString = "ERROR_EXCEPTION"; - mKeepNotification = true; break; default: causeString = "CAUSE_NOT_SPECIFIED"; @@ -571,16 +563,6 @@ public class DynamicSystemInstallationService extends Service Log.d(TAG, "status=" + statusString + ", cause=" + causeString + ", detail=" + detail); - boolean notifyOnNotificationBar = true; - - if (status == STATUS_NOT_STARTED - && cause == CAUSE_INSTALL_CANCELLED - && mJustCancelledByUser) { - // if task is cancelled by user, do not notify them - notifyOnNotificationBar = false; - mJustCancelledByUser = false; - } - if (notifyOnNotificationBar) { mNM.notify(NOTIFICATION_ID, buildNotification(status, cause, detail)); } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 4ef5e2b4f090..59ea9f0150bf 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -320,7 +320,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - private void installScratch() throws IOException, InterruptedException { + private void installScratch() throws IOException { final long scratchSize = mDynSystem.suggestScratchSize(); Thread thread = new Thread() { @Override @@ -347,7 +347,11 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog publishProgress(progress); } - Thread.sleep(100); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Ignore the error. + } } if (mInstallationSession == null) { @@ -361,7 +365,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - private void installUserdata() throws IOException, InterruptedException { + private void installUserdata() throws IOException { Thread thread = new Thread(() -> { mInstallationSession = mDynSystem.createPartition("userdata", mUserdataSize, false); }); @@ -383,7 +387,11 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog publishProgress(progress); } - Thread.sleep(100); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Ignore the error. + } } if (mInstallationSession == null) { @@ -397,8 +405,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - private void installImages() - throws IOException, InterruptedException, ImageValidationException { + private void installImages() throws IOException, ImageValidationException { if (mStream != null) { if (mIsZip) { installStreamingZipUpdate(); @@ -410,14 +417,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - private void installStreamingGzUpdate() - throws IOException, InterruptedException, ImageValidationException { + private void installStreamingGzUpdate() throws IOException, ImageValidationException { Log.d(TAG, "To install a streaming GZ update"); installImage("system", mSystemSize, new GZIPInputStream(mStream)); } - private void installStreamingZipUpdate() - throws IOException, InterruptedException, ImageValidationException { + private void installStreamingZipUpdate() throws IOException, ImageValidationException { Log.d(TAG, "To install a streaming ZIP update"); ZipInputStream zis = new ZipInputStream(mStream); @@ -432,8 +437,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - private void installLocalZipUpdate() - throws IOException, InterruptedException, ImageValidationException { + private void installLocalZipUpdate() throws IOException, ImageValidationException { Log.d(TAG, "To install a local ZIP update"); Enumeration<? extends ZipEntry> entries = mZipFile.entries(); @@ -449,7 +453,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } private boolean installImageFromAnEntry(ZipEntry entry, InputStream is) - throws IOException, InterruptedException, ImageValidationException { + throws IOException, ImageValidationException { String name = entry.getName(); Log.d(TAG, "ZipEntry: " + name); @@ -473,7 +477,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } private void installImage(String partitionName, long uncompressedSize, InputStream is) - throws IOException, InterruptedException, ImageValidationException { + throws IOException, ImageValidationException { SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is)); @@ -504,7 +508,11 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog return; } - Thread.sleep(100); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Ignore the error. + } } if (mInstallationSession == null) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 07b473caa9cc..afa3bd1da6e7 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -85,6 +85,7 @@ import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; import android.net.DataStallReportParcelable; import android.net.DnsResolverServiceManager; import android.net.ICaptivePortal; @@ -175,6 +176,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.sysprop.NetworkProperties; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; @@ -189,8 +191,6 @@ import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.IBatteryStats; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; @@ -201,7 +201,6 @@ import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; import com.android.net.module.util.LinkPropertiesUtils.CompareResult; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.PermissionUtils; -import com.android.server.am.BatteryStatsService; import com.android.server.connectivity.AutodestructReference; import com.android.server.connectivity.DnsManager; import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate; @@ -217,7 +216,6 @@ import com.android.server.connectivity.PermissionMonitor; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; import com.android.server.net.NetworkPolicyManagerInternal; -import com.android.server.utils.PriorityDump; import libcore.io.IoUtils; @@ -346,8 +344,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private String mCurrentTcpBufferSizes; private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames( - new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class, - NetworkAgentInfo.class }); + new Class[] { ConnectivityService.class, NetworkAgent.class, NetworkAgentInfo.class }); private enum ReapUnvalidatedNetworks { // Tear down networks that have no chance (e.g. even if validated) of becoming @@ -884,27 +881,59 @@ public class ConnectivityService extends IConnectivityManager.Stub } private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this); + final LocalPriorityDump mPriorityDumper = new LocalPriorityDump(); /** * Helper class which parses out priority arguments and dumps sections according to their * priority. If priority arguments are omitted, function calls the legacy dump command. */ - private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { - @Override - public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, new String[] {DIAG_ARG}, asProto); - doDump(fd, pw, new String[] {SHORT_ARG}, asProto); + private class LocalPriorityDump { + private static final String PRIORITY_ARG = "--dump-priority"; + private static final String PRIORITY_ARG_HIGH = "HIGH"; + private static final String PRIORITY_ARG_NORMAL = "NORMAL"; + + LocalPriorityDump() {} + + private void dumpHigh(FileDescriptor fd, PrintWriter pw) { + doDump(fd, pw, new String[] {DIAG_ARG}); + doDump(fd, pw, new String[] {SHORT_ARG}); } - @Override - public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, args, asProto); + private void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, args); } - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, args, asProto); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (args == null) { + dumpNormal(fd, pw, args); + return; + } + + String priority = null; + for (int argIndex = 0; argIndex < args.length; argIndex++) { + if (args[argIndex].equals(PRIORITY_ARG) && argIndex + 1 < args.length) { + argIndex++; + priority = args[argIndex]; + } + } + + if (PRIORITY_ARG_HIGH.equals(priority)) { + dumpHigh(fd, pw); + } else if (PRIORITY_ARG_NORMAL.equals(priority)) { + dumpNormal(fd, pw, args); + } else { + // ConnectivityService publishes binder service using publishBinderService() with + // no priority assigned will be treated as NORMAL priority. Dumpsys does not send + // "--dump-priority" arguments to the service. Thus, dump both NORMAL and HIGH to + // align the legacy design. + // TODO: Integrate into signal dump. + dumpNormal(fd, pw, args); + pw.println(); + pw.println("DUMP OF SERVICE HIGH connectivity"); + pw.println(); + dumpHigh(fd, pw); + } } - }; + } /** * Keeps track of the number of requests made under different uids. @@ -1035,19 +1064,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return new MultinetworkPolicyTracker(c, h, r); } - public IBatteryStats getBatteryStatsService() { - return BatteryStatsService.getService(); - } - /** * @see BatteryStatsManager */ public void reportNetworkInterfaceForTransports(Context context, String iface, int[] transportTypes) { - final BatteryStatsManager batteryStats = + final BatteryStatsManager batteryStats = context.getSystemService(BatteryStatsManager.class); batteryStats.reportNetworkInterfaceForTransports(iface, transportTypes); } + + public boolean getCellular464XlatEnabled() { + return NetworkProperties.isCellular464XlatEnabled().orElse(true); + } } public ConnectivityService(Context context) { @@ -1070,7 +1099,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRanker = new NetworkRanker(); final NetworkRequest defaultInternetRequest = createDefaultRequest(); mDefaultRequest = new NetworkRequestInfo( - defaultInternetRequest, null, new Binder(), + defaultInternetRequest, null, + new Binder(), NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, null /* attributionTags */); mNetworkRequests.put(defaultInternetRequest, mDefaultRequest); mDefaultNetworkRequests.add(mDefaultRequest); @@ -1246,8 +1276,7 @@ public class ConnectivityService extends IConnectivityManager.Stub new NetworkInfo(TYPE_NONE, 0, "", ""), new LinkProperties(), new NetworkCapabilities(), 0, mContext, null, new NetworkAgentConfig(), this, null, - null, 0, INVALID_UID, - mQosCallbackTracker); + null, 0, INVALID_UID, mQosCallbackTracker, mDeps); } private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { @@ -1327,7 +1356,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (enable) { handleRegisterNetworkRequest(new NetworkRequestInfo( - networkRequest, null, new Binder(), + networkRequest, null, + new Binder(), + NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, null /* attributionTags */)); } else { handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID, @@ -1489,11 +1520,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // but only exists if an app asks about them or requests them. Ensure the requesting app // gets the type it asks for. filtered.setType(type); - final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked) - ? DetailedState.BLOCKED - : filtered.getDetailedState(); - filtered.setDetailedState(getLegacyLockdownState(state), - "" /* reason */, null /* extraInfo */); + if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) { + filtered.setDetailedState(DetailedState.BLOCKED, null /* reason */, + null /* extraInfo */); + } + filterForLegacyLockdown(filtered); return filtered; } @@ -1569,8 +1600,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, false) ? DetailedState.BLOCKED : DetailedState.DISCONNECTED; - info.setDetailedState(getLegacyLockdownState(state), - "" /* reason */, null /* extraInfo */); + info.setDetailedState(state, null /* reason */, null /* extraInfo */); + filterForLegacyLockdown(info); return info; } @@ -1688,8 +1719,8 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( nai.network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, mDeps.getCallingUid(), callingPackageName, - callingAttributionTag)); + nc, false /* includeLocationSensitiveInfo */, + mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1702,7 +1733,9 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, mDeps.getCallingUid(), callingPackageName, + nc, + false /* includeLocationSensitiveInfo */, + mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1784,6 +1817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), + false /* includeLocationSensitiveInfo */, mDeps.getCallingUid(), callingPackageName, callingAttributionTag); } @@ -1817,8 +1851,8 @@ public class ConnectivityService extends IConnectivityManager.Stub @VisibleForTesting @Nullable NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( - @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName, - @Nullable String callingAttributionTag) { + @Nullable NetworkCapabilities nc, boolean includeLocationSensitiveInfo, + int callerUid, @NonNull String callerPkgName, @Nullable String callingAttributionTag) { if (nc == null) { return null; } @@ -1826,7 +1860,9 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkCapabilities newNc; // Avoid doing location permission check if the transport info has no location sensitive // data. - if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) { + if (includeLocationSensitiveInfo + && nc.getTransportInfo() != null + && nc.getTransportInfo().hasLocationSensitiveFields()) { hasLocationPermission = hasLocationPermission(callerUid, callerPkgName, callingAttributionTag); newNc = new NetworkCapabilities(nc, hasLocationPermission); @@ -1843,6 +1879,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // Owner UIDs already checked above. No need to re-check. return newNc; } + // If the caller does not want location sensitive data & target SDK >= S, then mask info. + // Else include the owner UID iff the caller has location permission to provide backwards + // compatibility for older apps. + if (!includeLocationSensitiveInfo + && isTargetSdkAtleast( + Build.VERSION_CODES.S, callerUid, callerPkgName)) { + newNc.setOwnerUid(INVALID_UID); + return newNc; + } + if (hasLocationPermission == null) { // Location permission not checked yet, check now for masking owner UID. hasLocationPermission = @@ -2364,9 +2410,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService"); } - // Public because it's used by mLockdownTracker. - public void sendConnectedBroadcast(NetworkInfo info) { - PermissionUtils.enforceNetworkStackPermission(mContext); + private void sendConnectedBroadcast(NetworkInfo info) { sendGeneralBroadcast(info, CONNECTIVITY_ACTION); } @@ -2603,7 +2647,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { - PriorityDump.dump(mPriorityDumper, fd, writer, args); + mPriorityDumper.dump(fd, writer, args); } private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { @@ -2618,10 +2662,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) { + private void doDump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); if (!checkDumpPermission(mContext, TAG, pw)) return; - if (asProto) return; if (CollectionUtils.contains(args, DIAG_ARG)) { dumpNetworkDiagnostics(pw); @@ -2864,22 +2907,6 @@ public class ConnectivityService extends IConnectivityManager.Stub super(looper); } - private boolean maybeHandleAsyncChannelMessage(Message msg) { - switch (msg.what) { - default: - return false; - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { - handleAsyncChannelHalfConnect(msg); - break; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { - handleAsyncChannelDisconnected(msg); - break; - } - } - return true; - } - private void maybeHandleNetworkAgentMessage(Message msg) { final Pair<NetworkAgentInfo, Object> arg = (Pair<NetworkAgentInfo, Object>) msg.obj; final NetworkAgentInfo nai = arg.first; @@ -3171,8 +3198,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void handleMessage(Message msg) { - if (!maybeHandleAsyncChannelMessage(msg) - && !maybeHandleNetworkMonitorMessage(msg) + if (!maybeHandleNetworkMonitorMessage(msg) && !maybeHandleNetworkAgentInfoMessage(msg)) { maybeHandleNetworkAgentMessage(msg); } @@ -3436,21 +3462,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - private void handleAsyncChannelHalfConnect(Message msg) { - ensureRunningOnConnectivityServiceThread(); - if (mNetworkProviderInfos.containsKey(msg.replyTo)) { - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - if (VDBG) log("NetworkFactory connected"); - // Finish setting up the full connection - NetworkProviderInfo npi = mNetworkProviderInfos.get(msg.replyTo); - sendAllRequestsToProvider(npi); - } else { - loge("Error connecting NetworkFactory"); - mNetworkProviderInfos.remove(msg.obj); - } - } - } - private void handleNetworkAgentRegistered(Message msg) { final NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj; if (!mNetworkAgentInfos.contains(nai)) { @@ -3481,14 +3492,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - // This is a no-op if it's called with a message designating a provider that has - // already been destroyed, because its reference will not be found in the relevant - // maps. - private void handleAsyncChannelDisconnected(Message msg) { - NetworkProviderInfo npi = mNetworkProviderInfos.remove(msg.replyTo); - if (DBG && npi != null) log("unregisterNetworkFactory for " + npi.name); - } - // Destroys a network, remove references to it from the internal state managed by // ConnectivityService, free its interfaces and clean up. // Must be called on the Handler thread. @@ -5012,8 +5015,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // The legacy lockdown VPN always uses the default network. // If the VPN's underlying network is no longer the current default network, it means that // the default network has just switched, and the VPN is about to disconnect. - // Report that the VPN is not connected, so when the state of NetworkInfo objects - // overwritten by getLegacyLockdownState will be set to CONNECTING and not CONNECTED. + // Report that the VPN is not connected, so the state of NetworkInfo objects overwritten + // by filterForLegacyLockdown will be set to CONNECTING and not CONNECTED. final NetworkAgentInfo defaultNetwork = getDefaultNetwork(); if (defaultNetwork == null || !defaultNetwork.network.equals(underlying[0])) { return null; @@ -5022,6 +5025,9 @@ public class ConnectivityService extends IConnectivityManager.Stub return nai; }; + // TODO: move all callers to filterForLegacyLockdown and delete this method. + // This likely requires making sendLegacyNetworkBroadcast take a NetworkInfo object instead of + // just a DetailedState object. private DetailedState getLegacyLockdownState(DetailedState origState) { if (origState != DetailedState.CONNECTED) { return origState; @@ -5031,6 +5037,23 @@ public class ConnectivityService extends IConnectivityManager.Stub : DetailedState.CONNECTED; } + private void filterForLegacyLockdown(NetworkInfo ni) { + if (!mLockdownEnabled || !ni.isConnected()) return; + // The legacy lockdown VPN replaces the state of every network in CONNECTED state with the + // state of its VPN. This is to ensure that when an underlying network connects, apps will + // not see a CONNECTIVITY_ACTION broadcast for a network in state CONNECTED until the VPN + // comes up, at which point there is a new CONNECTIVITY_ACTION broadcast for the underlying + // network, this time with a state of CONNECTED. + // + // Now that the legacy lockdown code lives in ConnectivityService, and no longer has access + // to the internal state of the Vpn object, always replace the state with CONNECTING. This + // is not too far off the truth, since an always-on VPN, when not connected, is always + // trying to reconnect. + if (getLegacyLockdownNai() == null) { + ni.setDetailedState(DetailedState.CONNECTING, "", null); + } + } + @Override public void setProvisioningNotificationVisible(boolean visible, int networkType, String action) { @@ -5109,8 +5132,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private final IBinder.DeathRecipient mDeathRecipient; public final int providerId; - NetworkProviderInfo(String name, Messenger messenger, AsyncChannel asyncChannel, - int providerId, @NonNull IBinder.DeathRecipient deathRecipient) { + NetworkProviderInfo(String name, Messenger messenger, int providerId, + @NonNull IBinder.DeathRecipient deathRecipient) { this.name = name; this.messenger = messenger; this.providerId = providerId; @@ -5204,6 +5227,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private final IBinder mBinder; final int mPid; final int mUid; + final @NetworkCallback.Flag int mCallbackFlags; @Nullable final String mCallingAttributionTag; // In order to preserve the mapping of NetworkRequest-to-callback when apps register @@ -5251,17 +5275,26 @@ public class ConnectivityService extends IConnectivityManager.Stub mPid = getCallingPid(); mUid = mDeps.getCallingUid(); mNetworkRequestCounter.incrementCountOrThrow(mUid); + /** + * Location sensitive data not included in pending intent. Only included in + * {@link NetworkCallback}. + */ + mCallbackFlags = NetworkCallback.FLAG_NONE; mCallingAttributionTag = callingAttributionTag; } NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final Messenger m, - @Nullable final IBinder binder, @Nullable String callingAttributionTag) { - this(Collections.singletonList(r), r, m, binder, callingAttributionTag); + @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @Nullable String callingAttributionTag) { + this(Collections.singletonList(r), r, m, binder, callbackFlags, callingAttributionTag); } NetworkRequestInfo(@NonNull final List<NetworkRequest> r, @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m, - @Nullable final IBinder binder, @Nullable String callingAttributionTag) { + @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @Nullable String callingAttributionTag) { super(); ensureAllNetworkRequestsHaveType(r); mRequests = initializeRequests(r); @@ -5272,6 +5305,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = mDeps.getCallingUid(); mPendingIntent = null; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = callbackFlags; mCallingAttributionTag = callingAttributionTag; try { @@ -5313,6 +5347,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = nri.mUid; mPendingIntent = nri.mPendingIntent; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = nri.mCallbackFlags; mCallingAttributionTag = nri.mCallingAttributionTag; } @@ -5362,7 +5397,8 @@ public class ConnectivityService extends IConnectivityManager.Stub + " callback request Id: " + mNetworkRequestForCallback.requestId + " " + mRequests - + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent); + + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent) + + "callback flags: " + mCallbackFlags; } } @@ -5446,13 +5482,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { - final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid()); + private boolean isTargetSdkAtleast(int version, int callingUid, + @NonNull String callingPackageName) { + final UserHandle user = UserHandle.getUserHandleForUid(callingUid); final PackageManager pm = mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); try { - final int callingVersion = pm.getApplicationInfo( - callingPackageName, 0 /* flags */).targetSdkVersion; + final int callingVersion = pm.getTargetSdkVersion(callingPackageName); if (callingVersion < version) return false; } catch (PackageManager.NameNotFoundException e) { } return true; @@ -5461,10 +5497,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder, - int legacyType, @NonNull String callingPackageName, + int legacyType, int callbackFlags, @NonNull String callingPackageName, @Nullable String callingAttributionTag) { if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) { + if (isTargetSdkAtleast(Build.VERSION_CODES.M, mDeps.getCallingUid(), + callingPackageName)) { throw new SecurityException("Insufficient permissions to specify legacy type"); } } @@ -5501,6 +5538,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // request if the app changes network state. http://b/29964605 enforceMeteredApnPolicy(networkCapabilities); break; + case TRACK_BEST: + throw new UnsupportedOperationException("Not implemented yet"); default: throw new IllegalArgumentException("Unsupported request type " + reqType); } @@ -5524,7 +5563,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), reqType); final NetworkRequestInfo nri = getNriToRegister( - networkRequest, messenger, binder, callingAttributionTag); + networkRequest, messenger, binder, callbackFlags, callingAttributionTag); if (DBG) log("requestNetwork for " + nri); // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were @@ -5559,6 +5598,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private NetworkRequestInfo getNriToRegister(@NonNull final NetworkRequest nr, @Nullable final Messenger msgr, @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, @Nullable String callingAttributionTag) { final List<NetworkRequest> requests; if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) { @@ -5567,7 +5607,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { requests = Collections.singletonList(nr); } - return new NetworkRequestInfo(requests, nr, msgr, binder, callingAttributionTag); + return new NetworkRequestInfo( + requests, nr, msgr, binder, callbackFlags, callingAttributionTag); } private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities, @@ -5693,8 +5734,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, IBinder binder, @NonNull String callingPackageName, - @Nullable String callingAttributionTag) { + Messenger messenger, IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @NonNull String callingPackageName, @NonNull String callingAttributionTag) { final int callingUid = mDeps.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); @@ -5715,7 +5757,8 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); NetworkRequestInfo nri = - new NetworkRequestInfo(networkRequest, messenger, binder, callingAttributionTag); + new NetworkRequestInfo(networkRequest, messenger, binder, callbackFlags, + callingAttributionTag); if (VDBG) log("listenForNetwork for " + nri); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); @@ -5784,8 +5827,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public int registerNetworkProvider(Messenger messenger, String name) { enforceNetworkFactoryOrSettingsPermission(); NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger, - null /* asyncChannel */, nextNetworkProviderId(), - () -> unregisterNetworkProvider(messenger)); + nextNetworkProviderId(), () -> unregisterNetworkProvider(messenger)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi)); return npi.providerId; } @@ -6106,7 +6148,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo nai = new NetworkAgentInfo(na, new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, providerId, uid, mQosCallbackTracker); + this, mNetd, mDnsResolver, providerId, uid, mQosCallbackTracker, mDeps); // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. processCapabilitiesFromAgent(nai, nc); @@ -7044,6 +7086,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) { putParcelable(bundle, networkAgent.network); } + final boolean includeLocationSensitiveInfo = + (nri.mCallbackFlags & NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) != 0; switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { final NetworkCapabilities nc = @@ -7052,7 +7096,8 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, nri.mUid, nrForCallback.getRequestorPackageName(), + nc, includeLocationSensitiveInfo, nri.mUid, + nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( networkAgent.linkProperties, nri.mPid, nri.mUid)); @@ -7072,7 +7117,8 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, nri.mUid, nrForCallback.getRequestorPackageName(), + netCap, includeLocationSensitiveInfo, nri.mUid, + nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); break; } @@ -7914,6 +7960,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // and is still connected. NetworkInfo info = new NetworkInfo(nai.networkInfo); info.setType(type); + filterForLegacyLockdown(info); if (state != DetailedState.DISCONNECTED) { info.setDetailedState(state, null, info.getExtraInfo()); sendConnectedBroadcast(info); diff --git a/services/core/java/com/android/server/ConnectivityServiceInitializer.java b/services/core/java/com/android/server/ConnectivityServiceInitializer.java index b9922087109f..2465479aadd8 100644 --- a/services/core/java/com/android/server/ConnectivityServiceInitializer.java +++ b/services/core/java/com/android/server/ConnectivityServiceInitializer.java @@ -16,9 +16,6 @@ package com.android.server; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; - import android.content.Context; import android.util.Log; @@ -42,6 +39,6 @@ public final class ConnectivityServiceInitializer extends SystemService { public void onStart() { Log.i(TAG, "Registering " + Context.CONNECTIVITY_SERVICE); publishBinderService(Context.CONNECTIVITY_SERVICE, mConnectivity, - /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); + /* allowIsolated= */ false); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 81d4b9da63c8..4c3c6ef21fc5 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -56,6 +56,7 @@ import android.system.Os; import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; +import android.util.Range; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -756,13 +757,9 @@ public class IpSecService extends IIpSecService.Stub { } } - // These values have been reserved in NetIdManager - @VisibleForTesting static final int TUN_INTF_NETID_START = 0xFC00; - - public static final int TUN_INTF_NETID_RANGE = 0x0400; - private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray(); - private int mNextTunnelNetIdIndex = 0; + final Range<Integer> mNetIdRange = ConnectivityManager.getIpSecNetIdRange(); + private int mNextTunnelNetId = mNetIdRange.getLower(); /** * Reserves a netId within the range of netIds allocated for IPsec tunnel interfaces @@ -775,11 +772,13 @@ public class IpSecService extends IIpSecService.Stub { */ @VisibleForTesting int reserveNetId() { + final int range = mNetIdRange.getUpper() - mNetIdRange.getLower() + 1; synchronized (mTunnelNetIds) { - for (int i = 0; i < TUN_INTF_NETID_RANGE; i++) { - int index = mNextTunnelNetIdIndex; - int netId = index + TUN_INTF_NETID_START; - if (++mNextTunnelNetIdIndex >= TUN_INTF_NETID_RANGE) mNextTunnelNetIdIndex = 0; + for (int i = 0; i < range; i++) { + final int netId = mNextTunnelNetId; + if (++mNextTunnelNetId > mNetIdRange.getUpper()) { + mNextTunnelNetId = mNetIdRange.getLower(); + } if (!mTunnelNetIds.get(netId)) { mTunnelNetIds.put(netId, true); return netId; diff --git a/services/core/java/com/android/server/NetIdManager.java b/services/core/java/com/android/server/NetIdManager.java index 097fb3ae47e3..61925c80a22b 100644 --- a/services/core/java/com/android/server/NetIdManager.java +++ b/services/core/java/com/android/server/NetIdManager.java @@ -17,6 +17,7 @@ package com.android.server; import android.annotation.NonNull; +import android.net.ConnectivityManager; import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; @@ -31,7 +32,7 @@ public class NetIdManager { // Sequence number for Networks; keep in sync with system/netd/NetworkController.cpp public static final int MIN_NET_ID = 100; // some reserved marks // Top IDs reserved by IpSecService - public static final int MAX_NET_ID = 65535 - IpSecService.TUN_INTF_NETID_RANGE; + public static final int MAX_NET_ID = ConnectivityManager.getIpSecNetIdRange().getLower() - 1; @GuardedBy("mNetIdInUse") private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray(); diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 222c96f2496b..3bcde1204079 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -19,6 +19,7 @@ per-file ServiceWatcher.java = sooniln@google.com per-file *Alarm* = file:/apex/jobscheduler/OWNERS per-file *AppOp* = file:/core/java/android/permission/OWNERS +per-file *Battery* = file:/BATTERY_STATS_OWNERS per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 55408ea61566..ee610671ff23 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -33,8 +33,8 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; import android.net.RouteInfo; -import android.net.StringNetworkSpecifier; import android.net.TestNetworkInterface; +import android.net.TestNetworkSpecifier; import android.net.util.NetdService; import android.os.Binder; import android.os.Handler; @@ -242,7 +242,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); - nc.setNetworkSpecifier(new StringNetworkSpecifier(iface)); + nc.setNetworkSpecifier(new TestNetworkSpecifier(iface)); nc.setAdministratorUids(administratorUids); if (!isMetered) { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 502e74a4cc6a..1ef93f4da255 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -667,6 +667,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull IVcnUnderlyingNetworkPolicyListener listener) { requireNonNull(listener, "listener was null"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.NETWORK_FACTORY, + "Must have permission NETWORK_FACTORY to unregister a policy listener"); + Binder.withCleanCallingIdentity(() -> { synchronized (mLock) { PolicyListenerBinderDeath listenerBinderDeath = diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java new file mode 100644 index 000000000000..b0335fe404f4 --- /dev/null +++ b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.apphibernation; + +/** + * App hibernation manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class AppHibernationManagerInternal { + + /** + * @see AppHibernationService#isHibernatingForUser + */ + public abstract boolean isHibernatingForUser(String packageName, int userId); + + /** + * @see AppHibernationService#setHibernatingForUser + */ + public abstract void setHibernatingForUser(String packageName, int userId, + boolean isHibernating); + + /** + * @see AppHibernationService#isHibernatingGlobally + */ + public abstract boolean isHibernatingGlobally(String packageName); + + /** + * @see AppHibernationService#setHibernatingGlobally + */ + public abstract void setHibernatingGlobally(String packageName, boolean isHibernating); +} diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 32ae87898085..968cf5f1df91 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -59,6 +59,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.LocalServices; import com.android.server.SystemService; import java.io.File; @@ -134,6 +135,8 @@ public final class AppHibernationService extends SystemService { intentFilter.addAction(ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); userAllContext.registerReceiver(mBroadcastReceiver, intentFilter); + + LocalServices.addService(AppHibernationManagerInternal.class, mLocalService); } @Override @@ -545,6 +548,36 @@ public final class AppHibernationService extends SystemService { } } + private final AppHibernationManagerInternal mLocalService = new LocalService(this); + + private static final class LocalService extends AppHibernationManagerInternal { + private final AppHibernationService mService; + + LocalService(AppHibernationService service) { + mService = service; + } + + @Override + public boolean isHibernatingForUser(String packageName, int userId) { + return mService.isHibernatingForUser(packageName, userId); + } + + @Override + public void setHibernatingForUser(String packageName, int userId, boolean isHibernating) { + mService.setHibernatingForUser(packageName, userId, isHibernating); + } + + @Override + public void setHibernatingGlobally(String packageName, boolean isHibernating) { + mService.setHibernatingGlobally(packageName, isHibernating); + } + + @Override + public boolean isHibernatingGlobally(String packageName) { + return mService.isHibernatingGlobally(packageName); + } + } + private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this); static final class AppHibernationServiceStub extends IAppHibernationService.Stub { diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index df83df9a73fb..ae9b0015de43 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import com.android.internal.compat.AndroidBuildClassifier; import com.android.internal.compat.CompatibilityChangeInfo; import com.android.internal.compat.OverrideAllowedState; import com.android.server.compat.config.Change; @@ -55,7 +56,7 @@ public final class CompatChange extends CompatibilityChangeInfo { * A change ID to be used only in the CTS test for this SystemApi */ @ChangeId - @EnabledSince(targetSdkVersion = 1235) // Needs to be > test APK targetSdkVersion. + @EnabledSince(targetSdkVersion = 31) // Needs to be > test APK targetSdkVersion. static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id. /** @@ -80,6 +81,15 @@ public final class CompatChange extends CompatibilityChangeInfo { } /** + * @param change an object generated by services/core/xsd/platform-compat-config.xsd + */ + public CompatChange(Change change) { + this(change.getId(), change.getName(), change.getEnableAfterTargetSdk(), + change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(), + change.getDescription(), change.getOverridable()); + } + + /** * @param changeId Unique ID for the change. See {@link android.compat.Compatibility}. * @param name Short descriptive name. * @param enableAfterTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledAfter}; @@ -93,15 +103,10 @@ public final class CompatChange extends CompatibilityChangeInfo { boolean overridable) { super(changeId, name, enableAfterTargetSdk, enableSinceTargetSdk, disabled, loggingOnly, description, overridable); - } - /** - * @param change an object generated by services/core/xsd/platform-compat-config.xsd - */ - public CompatChange(Change change) { - super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(), - change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(), - change.getDescription(), change.getOverridable()); + // Initialize override maps. + mEvaluatedOverrides = new HashMap<>(); + mRawOverrides = new HashMap<>(); } void registerListener(ChangeListener listener) { @@ -127,18 +132,13 @@ public final class CompatChange extends CompatibilityChangeInfo { throw new IllegalArgumentException( "Can't add overrides for a logging only change " + toString()); } - if (mEvaluatedOverrides == null) { - mEvaluatedOverrides = new HashMap<>(); - } mEvaluatedOverrides.put(pname, enabled); notifyListener(pname); } private void removePackageOverrideInternal(String pname) { - if (mEvaluatedOverrides != null) { - if (mEvaluatedOverrides.remove(pname) != null) { - notifyListener(pname); - } + if (mEvaluatedOverrides.remove(pname) != null) { + notifyListener(pname); } } @@ -157,9 +157,6 @@ public final class CompatChange extends CompatibilityChangeInfo { throw new IllegalArgumentException( "Can't add overrides for a logging only change " + toString()); } - if (mRawOverrides == null) { - mRawOverrides = new HashMap<>(); - } mRawOverrides.put(packageName, override); recheckOverride(packageName, allowedState, context); } @@ -212,7 +209,7 @@ public final class CompatChange extends CompatibilityChangeInfo { } boolean hasPackageOverride(String pname) { - return mRawOverrides != null && mRawOverrides.containsKey(pname); + return mRawOverrides.containsKey(pname); } /** * Remove any package override for the given package name, restoring the default behaviour. @@ -223,7 +220,7 @@ public final class CompatChange extends CompatibilityChangeInfo { */ boolean removePackageOverride(String pname, OverrideAllowedState allowedState, Context context) { - if (mRawOverrides != null && (mRawOverrides.remove(pname) != null)) { + if (mRawOverrides.remove(pname) != null) { recheckOverride(pname, allowedState, context); return true; } @@ -237,18 +234,24 @@ public final class CompatChange extends CompatibilityChangeInfo { * @param app Info about the app in question * @return {@code true} if the change should be enabled for the package. */ - boolean isEnabled(ApplicationInfo app) { + boolean isEnabled(ApplicationInfo app, AndroidBuildClassifier buildClassifier) { if (app == null) { return defaultValue(); } - if (mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(app.packageName)) { + if (mEvaluatedOverrides.containsKey(app.packageName)) { return mEvaluatedOverrides.get(app.packageName); } if (getDisabled()) { return false; } if (getEnableSinceTargetSdk() != -1) { - return app.targetSdkVersion >= getEnableSinceTargetSdk(); + // If the change is gated by a platform version newer than the one currently installed + // on the device, disregard the app's target sdk version. + int compareSdk = Math.min(app.targetSdkVersion, buildClassifier.platformTargetSdk()); + if (compareSdk != app.targetSdkVersion) { + compareSdk = app.targetSdkVersion; + } + return compareSdk >= getEnableSinceTargetSdk(); } return true; } @@ -289,7 +292,7 @@ public final class CompatChange extends CompatibilityChangeInfo { * @return true if there is such override */ private boolean hasOverride(String packageName) { - return mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(packageName); + return mEvaluatedOverrides.containsKey(packageName); } /** @@ -298,20 +301,15 @@ public final class CompatChange extends CompatibilityChangeInfo { * @return true if there is such a deferred override */ private boolean hasRawOverride(String packageName) { - return mRawOverrides != null && mRawOverrides.containsKey(packageName); + return mRawOverrides.containsKey(packageName); } - void loadOverrides(ChangeOverrides changeOverrides) { - if (mRawOverrides == null) { - mRawOverrides = new HashMap<>(); - } + void clearOverrides() { mRawOverrides.clear(); - - if (mEvaluatedOverrides == null) { - mEvaluatedOverrides = new HashMap<>(); - } mEvaluatedOverrides.clear(); + } + void loadOverrides(ChangeOverrides changeOverrides) { // Load deferred overrides for backwards compatibility if (changeOverrides.getDeferred() != null) { for (OverrideValue override : changeOverrides.getDeferred().getOverrideValue()) { @@ -345,34 +343,30 @@ public final class CompatChange extends CompatibilityChangeInfo { } ChangeOverrides saveOverrides() { - if (mRawOverrides == null || mRawOverrides.isEmpty()) { + if (mRawOverrides.isEmpty()) { return null; } ChangeOverrides changeOverrides = new ChangeOverrides(); changeOverrides.setChangeId(getId()); ChangeOverrides.Raw rawOverrides = new ChangeOverrides.Raw(); List<RawOverrideValue> rawList = rawOverrides.getRawOverrideValue(); - if (mRawOverrides != null) { - for (Map.Entry<String, PackageOverride> entry : mRawOverrides.entrySet()) { - RawOverrideValue override = new RawOverrideValue(); - override.setPackageName(entry.getKey()); - override.setMinVersionCode(entry.getValue().getMinVersionCode()); - override.setMaxVersionCode(entry.getValue().getMaxVersionCode()); - override.setEnabled(entry.getValue().getEnabled()); - rawList.add(override); - } + for (Map.Entry<String, PackageOverride> entry : mRawOverrides.entrySet()) { + RawOverrideValue override = new RawOverrideValue(); + override.setPackageName(entry.getKey()); + override.setMinVersionCode(entry.getValue().getMinVersionCode()); + override.setMaxVersionCode(entry.getValue().getMaxVersionCode()); + override.setEnabled(entry.getValue().getEnabled()); + rawList.add(override); } changeOverrides.setRaw(rawOverrides); ChangeOverrides.Validated validatedOverrides = new ChangeOverrides.Validated(); List<OverrideValue> validatedList = validatedOverrides.getOverrideValue(); - if (mEvaluatedOverrides != null) { - for (Map.Entry<String, Boolean> entry : mEvaluatedOverrides.entrySet()) { - OverrideValue override = new OverrideValue(); - override.setPackageName(entry.getKey()); - override.setEnabled(entry.getValue()); - validatedList.add(override); - } + for (Map.Entry<String, Boolean> entry : mEvaluatedOverrides.entrySet()) { + OverrideValue override = new OverrideValue(); + override.setPackageName(entry.getKey()); + override.setEnabled(entry.getValue()); + validatedList.add(override); } changeOverrides.setValidated(validatedOverrides); return changeOverrides; @@ -394,10 +388,10 @@ public final class CompatChange extends CompatibilityChangeInfo { if (getLoggingOnly()) { sb.append("; loggingOnly"); } - if (mEvaluatedOverrides != null && mEvaluatedOverrides.size() > 0) { + if (!mEvaluatedOverrides.isEmpty()) { sb.append("; packageOverrides=").append(mEvaluatedOverrides); } - if (mRawOverrides != null && mRawOverrides.size() > 0) { + if (!mRawOverrides.isEmpty()) { sb.append("; rawOverrides=").append(mRawOverrides); } if (getOverridable()) { diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 66a652053857..ef86f42d6c3c 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -67,18 +67,21 @@ final class CompatConfig { private static final String TAG = "CompatConfig"; private static final String APP_COMPAT_DATA_DIR = "/data/misc/appcompat"; + private static final String STATIC_OVERRIDES_PRODUCT_DIR = "/product/etc/appcompat"; private static final String OVERRIDES_FILE = "compat_framework_overrides.xml"; @GuardedBy("mChanges") private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); private final OverrideValidatorImpl mOverrideValidator; + private final AndroidBuildClassifier mAndroidBuildClassifier; private Context mContext; private File mOverridesFile; @VisibleForTesting CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) { mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this); + mAndroidBuildClassifier = androidBuildClassifier; mContext = context; } @@ -94,8 +97,7 @@ final class CompatConfig { config.initConfigFromLib(Environment.buildPath( apex.apexDirectory, "etc", "compatconfig")); } - File overridesFile = new File(APP_COMPAT_DATA_DIR, OVERRIDES_FILE); - config.initOverrides(overridesFile); + config.initOverrides(); config.invalidateCache(); return config; } @@ -133,7 +135,7 @@ final class CompatConfig { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { CompatChange c = mChanges.valueAt(i); - if (!c.isEnabled(app)) { + if (!c.isEnabled(app, mAndroidBuildClassifier)) { disabled.add(c.getId()); } } @@ -175,7 +177,7 @@ final class CompatConfig { // we know nothing about this change: default behaviour is enabled. return true; } - return c.isEnabled(app); + return c.isEnabled(app, mAndroidBuildClassifier); } } @@ -475,7 +477,7 @@ final class CompatConfig { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { CompatChange c = mChanges.valueAt(i); - if (c.isEnabled(applicationInfo)) { + if (c.isEnabled(applicationInfo, mAndroidBuildClassifier)) { enabled.add(c.getId()); } else { disabled.add(c.getId()); @@ -525,10 +527,34 @@ final class CompatConfig { } } - void initOverrides(File overridesFile) { + private void initOverrides() { + initOverrides(new File(APP_COMPAT_DATA_DIR, OVERRIDES_FILE), + new File(STATIC_OVERRIDES_PRODUCT_DIR, OVERRIDES_FILE)); + } + + @VisibleForTesting + void initOverrides(File dynamicOverridesFile, File staticOverridesFile) { + // Clear overrides from all changes before loading. + synchronized (mChanges) { + for (int i = 0; i < mChanges.size(); ++i) { + mChanges.valueAt(i).clearOverrides(); + } + } + + loadOverrides(staticOverridesFile); + + mOverridesFile = dynamicOverridesFile; + loadOverrides(dynamicOverridesFile); + + if (staticOverridesFile.exists()) { + // Only save overrides if there is a static overrides file. + saveOverrides(); + } + } + + private void loadOverrides(File overridesFile) { if (!overridesFile.exists()) { - mOverridesFile = overridesFile; - // There have not been any overrides added yet. + // Overrides file doesn't exist. return; } @@ -548,7 +574,6 @@ final class CompatConfig { Slog.w(TAG, "Error processing " + overridesFile + " " + e.toString()); return; } - mOverridesFile = overridesFile; } /** diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java index fe5b4a98797d..aa66a1a8b01f 100644 --- a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java +++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java @@ -22,6 +22,7 @@ import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARG import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE; import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH; import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE; +import static com.android.internal.compat.OverrideAllowedState.PLATFORM_TOO_OLD; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -85,6 +86,9 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub { if (debuggableBuild) { return new OverrideAllowedState(ALLOWED, -1, -1); } + if (maxTargetSdk >= mAndroidBuildClassifier.platformTargetSdk()) { + return new OverrideAllowedState(PLATFORM_TOO_OLD, -1, maxTargetSdk); + } PackageManager packageManager = mContext.getPackageManager(); if (packageManager == null) { throw new IllegalStateException("No PackageManager!"); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index edfc8b8f31b0..40e386359a40 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -66,18 +66,22 @@ public class PlatformCompat extends IPlatformCompat.Stub { private final Context mContext; private final ChangeReporter mChangeReporter; private final CompatConfig mCompatConfig; + private final AndroidBuildClassifier mBuildClassifier; public PlatformCompat(Context context) { mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); - mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext); + mBuildClassifier = new AndroidBuildClassifier(); + mCompatConfig = CompatConfig.create(mBuildClassifier, mContext); } @VisibleForTesting - PlatformCompat(Context context, CompatConfig compatConfig) { + PlatformCompat(Context context, CompatConfig compatConfig, + AndroidBuildClassifier buildClassifier) { mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); mCompatConfig = compatConfig; + mBuildClassifier = buildClassifier; registerPackageReceiver(context); } @@ -392,7 +396,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { return false; } if (change.getEnableSinceTargetSdk() > 0) { - return change.getEnableSinceTargetSdk() >= Build.VERSION_CODES.Q; + return change.getEnableSinceTargetSdk() >= Build.VERSION_CODES.Q + && change.getEnableSinceTargetSdk() <= mBuildClassifier.platformTargetSdk(); } return true; } diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index fa80b25f9026..c66a280f2b02 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -16,6 +16,8 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; + import static com.android.net.module.util.CollectionUtils.contains; import android.annotation.NonNull; @@ -35,6 +37,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.NetworkStackConstants; +import com.android.server.ConnectivityService; import java.net.Inet6Address; import java.util.Objects; @@ -94,12 +97,15 @@ public class Nat464Xlat { private Inet6Address mIPv6Address; private State mState = State.IDLE; + private boolean mEnableClatOnCellular; private boolean mPrefixDiscoveryRunning; - public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver) { + public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver, + ConnectivityService.Dependencies deps) { mDnsResolver = dnsResolver; mNetd = netd; mNetwork = nai; + mEnableClatOnCellular = deps.getCellular464XlatEnabled(); } /** @@ -111,7 +117,7 @@ public class Nat464Xlat { * @return true if the network requires clat, false otherwise. */ @VisibleForTesting - protected static boolean requiresClat(NetworkAgentInfo nai) { + protected boolean requiresClat(NetworkAgentInfo nai) { // TODO: migrate to NetworkCapabilities.TRANSPORT_*. final boolean supported = contains(NETWORK_TYPES, nai.networkInfo.getType()); final boolean connected = contains(NETWORK_STATES, nai.networkInfo.getState()); @@ -126,7 +132,9 @@ public class Nat464Xlat { final boolean skip464xlat = (nai.netAgentConfig() != null) && nai.netAgentConfig().skip464xlat; - return supported && connected && isIpv6OnlyNetwork && !skip464xlat; + return supported && connected && isIpv6OnlyNetwork && !skip464xlat + && (nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR) + ? isCellular464XlatEnabled() : true); } /** @@ -137,7 +145,7 @@ public class Nat464Xlat { * @return true if the network should start clat, false otherwise. */ @VisibleForTesting - protected static boolean shouldStartClat(NetworkAgentInfo nai) { + protected boolean shouldStartClat(NetworkAgentInfo nai) { LinkProperties lp = nai.linkProperties; return requiresClat(nai) && lp != null && lp.getNat64Prefix() != null; } @@ -507,4 +515,9 @@ public class Nat464Xlat { protected int getNetId() { return mNetwork.network.getNetId(); } + + @VisibleForTesting + protected boolean isCellular464XlatEnabled() { + return mEnableClatOnCellular; + } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 1d0e11569c80..803cc9d31c35 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -341,7 +341,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, int score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid, - QosCallbackTracker qosCallbackTracker) { + QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) { Objects.requireNonNull(net); Objects.requireNonNull(info); Objects.requireNonNull(lp); @@ -355,7 +355,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { linkProperties = lp; networkCapabilities = nc; mScore = score; - clatd = new Nat464Xlat(this, netd, dnsResolver); + clatd = new Nat464Xlat(this, netd, dnsResolver, deps); mConnService = connService; mContext = context; mHandler = handler; diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 9411e33434d8..488677ac1b59 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -31,14 +31,17 @@ import static android.os.Process.SYSTEM_UID; import static com.android.net.module.util.CollectionUtils.toIntArray; import android.annotation.NonNull; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageManagerInternal; import android.net.INetd; import android.net.UidRange; +import android.net.Uri; import android.os.Build; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -54,7 +57,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.CollectionUtils; -import com.android.server.LocalServices; import java.util.ArrayList; import java.util.HashMap; @@ -71,7 +73,7 @@ import java.util.Set; * * @hide */ -public class PermissionMonitor implements PackageManagerInternal.PackageListObserver { +public class PermissionMonitor { private static final String TAG = "PermissionMonitor"; private static final boolean DBG = true; protected static final Boolean SYSTEM = Boolean.TRUE; @@ -83,6 +85,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse private final SystemConfigManager mSystemConfigManager; private final INetd mNetd; private final Dependencies mDeps; + private final Context mContext; @GuardedBy("this") private final Set<UserHandle> mUsers = new HashSet<>(); @@ -102,6 +105,25 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse @GuardedBy("this") private final Set<Integer> mAllApps = new HashSet<>(); + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + final Uri packageData = intent.getData(); + final String packageName = + packageData != null ? packageData.getSchemeSpecificPart() : null; + + if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { + onPackageAdded(packageName, uid); + } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { + onPackageRemoved(packageName, uid); + } else { + Log.wtf(TAG, "received unexpected intent: " + action); + } + } + }; + /** * Dependencies of PermissionMonitor, for injection in tests. */ @@ -127,6 +149,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse mSystemConfigManager = context.getSystemService(SystemConfigManager.class); mNetd = netd; mDeps = deps; + mContext = context; } // Intended to be called only once at startup, after the system is ready. Installs a broadcast @@ -134,12 +157,14 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse public synchronized void startMonitoring() { log("Monitoring"); - PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); - if (pmi != null) { - pmi.getPackageList(this); - } else { - loge("failed to get the PackageManagerInternal service"); - } + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); + intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + intentFilter.addDataScheme("package"); + mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */).registerReceiver( + mIntentReceiver, intentFilter, null /* broadcastPermission */, + null /* scheduler */); + List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS | MATCH_ANY_USER); if (apps == null) { @@ -347,9 +372,10 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * * @hide */ - @Override public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) { - sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); + // TODO: Netd is using appId for checking traffic permission. Correct the methods that are + // using appId instead of uid actually + sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid)); // If multiple packages share a UID (cf: android:sharedUserId) and ask for different // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). @@ -384,9 +410,10 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * * @hide */ - @Override public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) { - sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); + // TODO: Netd is using appId for checking traffic permission. Correct the methods that are + // using appId instead of uid actually + sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid)); // If the newly-removed package falls within some VPN's uid range, update Netd with it. // This needs to happen before the mApps update below, since removeBypassingUids() depends @@ -432,19 +459,6 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } - /** - * Called when a package is changed. - * - * @param packageName The name of the changed package. - * @param uid The uid of the changed package. - * - * @hide - */ - @Override - public synchronized void onPackageChanged(@NonNull final String packageName, final int uid) { - sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); - } - private static int getNetdPermissionMask(String[] requestedPermissions, int[] requestedPermissionsFlags) { int permissions = 0; diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 48382a946d4b..6e99cba6ea91 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -64,6 +64,8 @@ class RebootEscrowManager { @VisibleForTesting public static final String REBOOT_ESCROW_ARMED_KEY = "reboot_escrow_armed_count"; + static final String REBOOT_ESCROW_KEY_ARMED_TIMESTAMP = "reboot_escrow_key_stored_timestamp"; + /** * Number of boots until we consider the escrow data to be stale for the purposes of metrics. * <p> @@ -144,8 +146,7 @@ class RebootEscrowManager { private RebootEscrowProviderInterface createRebootEscrowProvider() { RebootEscrowProviderInterface rebootEscrowProvider; - if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, - "server_based_ror_enabled", false)) { + if (serverBasedResumeOnReboot()) { Slog.i(TAG, "Using server based resume on reboot"); rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage); } else { @@ -166,6 +167,11 @@ class RebootEscrowManager { handler.postDelayed(runnable, delayMillis); } + public boolean serverBasedResumeOnReboot() { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, + "server_based_ror_enabled", false); + } + public Context getContext() { return mContext; } @@ -204,10 +210,12 @@ class RebootEscrowManager { DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS); } - public void reportMetric(boolean success) { - // TODO(b/179105110) design error code; and report the true value for other fields. - FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, 0, 1, 1, - -1, 0, -1); + public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, + int escrowDurationInSeconds, int vbmetaDigestStatus, + int durationSinceBootCompleteInSeconds) { + FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success, + errorCode, serviceType, attemptCount, escrowDurationInSeconds, + vbmetaDigestStatus, durationSinceBootCompleteInSeconds); } public RebootEscrowEventLog getEventLog() { @@ -230,7 +238,7 @@ class RebootEscrowManager { mKeyStoreManager = injector.getKeyStoreManager(); } - private void onGetRebootEscrowKeyFailed(List<UserInfo> users) { + private void onGetRebootEscrowKeyFailed(List<UserInfo> users, int attemptCount) { Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); for (UserInfo user : users) { mStorage.removeRebootEscrow(user.id); @@ -238,7 +246,7 @@ class RebootEscrowManager { // Clear the old key in keystore. mKeyStoreManager.clearKeyStoreEncryptionKey(); - onEscrowRestoreComplete(false); + onEscrowRestoreComplete(false, attemptCount); } void loadRebootEscrowDataIfAvailable(Handler retryHandler) { @@ -251,6 +259,8 @@ class RebootEscrowManager { } if (rebootEscrowUsers.isEmpty()) { + Slog.i(TAG, "No reboot escrow data found for users," + + " skipping loading escrow data"); return; } @@ -274,7 +284,7 @@ class RebootEscrowManager { } Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); - onGetRebootEscrowKeyFailed(users); + onGetRebootEscrowKeyFailed(users, attemptNumber); } void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber, @@ -297,7 +307,7 @@ class RebootEscrowManager { } if (escrowKey == null) { - onGetRebootEscrowKeyFailed(users); + onGetRebootEscrowKeyFailed(users, attemptNumber + 1); return; } @@ -311,16 +321,35 @@ class RebootEscrowManager { // Clear the old key in keystore. A new key will be generated by new RoR requests. mKeyStoreManager.clearKeyStoreEncryptionKey(); - onEscrowRestoreComplete(allUsersUnlocked); + onEscrowRestoreComplete(allUsersUnlocked, attemptNumber + 1); + } + + private void reportMetricOnRestoreComplete(boolean success, int attemptCount) { + int serviceType = mInjector.serverBasedResumeOnReboot() + ? FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__SERVER_BASED + : FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__HAL; + + long armedTimestamp = mStorage.getLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, -1, + USER_SYSTEM); + mStorage.removeKey(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, USER_SYSTEM); + int escrowDurationInSeconds = armedTimestamp != -1 + ? (int) (System.currentTimeMillis() - armedTimestamp) / 1000 : -1; + + // TODO(b/179105110) design error code; and report the true value for other fields. + int vbmetaDigestStatus = FrameworkStatsLog + .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; + + mInjector.reportMetric(success, 0 /* error code */, serviceType, attemptCount, + escrowDurationInSeconds, vbmetaDigestStatus, -1); } - private void onEscrowRestoreComplete(boolean success) { + private void onEscrowRestoreComplete(boolean success, int attemptCount) { int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM); mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); int bootCountDelta = mInjector.getBootCount() - previousBootCount; if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) { - mInjector.reportMetric(success); + reportMetricOnRestoreComplete(success, attemptCount); } } @@ -476,6 +505,8 @@ class RebootEscrowManager { boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); if (armedRebootEscrow) { mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); + mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, System.currentTimeMillis(), + USER_SYSTEM); mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformDecryptionKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformDecryptionKey.java index 35571f1f2728..e75aae1f99aa 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformDecryptionKey.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformDecryptionKey.java @@ -16,7 +16,7 @@ package com.android.server.locksettings.recoverablekeystore; -import android.security.keystore.AndroidKeyStoreSecretKey; +import javax.crypto.SecretKey; /** * Used to unwrap recoverable keys before syncing them with remote storage. @@ -30,7 +30,7 @@ import android.security.keystore.AndroidKeyStoreSecretKey; public class PlatformDecryptionKey { private final int mGenerationId; - private final AndroidKeyStoreSecretKey mKey; + private final SecretKey mKey; /** * A new instance. @@ -40,7 +40,7 @@ public class PlatformDecryptionKey { * * @hide */ - public PlatformDecryptionKey(int generationId, AndroidKeyStoreSecretKey key) { + public PlatformDecryptionKey(int generationId, SecretKey key) { mGenerationId = generationId; mKey = key; } @@ -59,7 +59,7 @@ public class PlatformDecryptionKey { * * @hide */ - public AndroidKeyStoreSecretKey getKey() { + public SecretKey getKey() { return mKey; } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformEncryptionKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformEncryptionKey.java index 38f5b45ea190..ee334462f7be 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformEncryptionKey.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformEncryptionKey.java @@ -16,7 +16,7 @@ package com.android.server.locksettings.recoverablekeystore; -import android.security.keystore.AndroidKeyStoreSecretKey; +import javax.crypto.SecretKey; /** * Private key stored in AndroidKeyStore. Used to wrap recoverable keys before writing them to disk. @@ -33,7 +33,7 @@ import android.security.keystore.AndroidKeyStoreSecretKey; public class PlatformEncryptionKey { private final int mGenerationId; - private final AndroidKeyStoreSecretKey mKey; + private final SecretKey mKey; /** * A new instance. @@ -41,7 +41,7 @@ public class PlatformEncryptionKey { * @param generationId The generation ID of the key. * @param key The secret key handle. Can be used to encrypt WITHOUT requiring screen unlock. */ - public PlatformEncryptionKey(int generationId, AndroidKeyStoreSecretKey key) { + public PlatformEncryptionKey(int generationId, SecretKey key) { mGenerationId = generationId; mKey = key; } @@ -56,7 +56,7 @@ public class PlatformEncryptionKey { /** * Returns the actual key, which can only be used to encrypt. */ - public AndroidKeyStoreSecretKey getKey() { + public SecretKey getKey() { return mKey; } } 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 202dfe798616..5e0620548076 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java @@ -21,7 +21,6 @@ import android.content.Context; import android.os.RemoteException; import android.os.UserHandle; import android.security.GateKeeper; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; @@ -237,7 +236,7 @@ public class PlatformKeyManager { if (!isKeyLoaded(userId, generationId)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } - AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( + SecretKey key = (SecretKey) mKeyStore.getKey( alias, /*password=*/ null); return new PlatformEncryptionKey(generationId, key); } @@ -289,7 +288,7 @@ public class PlatformKeyManager { if (!isKeyLoaded(userId, generationId)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } - AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( + SecretKey key = (SecretKey) mKeyStore.getKey( alias, /*password=*/ null); return new PlatformDecryptionKey(generationId, key); } diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS index fc7fd220b26a..174ad3ad2e25 100644 --- a/services/core/java/com/android/server/stats/OWNERS +++ b/services/core/java/com/android/server/stats/OWNERS @@ -1,7 +1,10 @@ jeffreyhuang@google.com joeo@google.com +jtnguyen@google.com muhammadq@google.com +rslawik@google.com ruchirr@google.com +sharaienko@google.com singhtejinder@google.com tsaichristine@google.com yaochen@google.com diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index b2db9f5af07e..8dcc547508ec 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -23,7 +23,6 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkCapabilities.NetCapability; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.os.Handler; @@ -115,33 +114,61 @@ public class UnderlyingNetworkTracker { getWifiNetworkRequest(), mHandler, mWifiBringupCallback); updateSubIdsAndCellularRequests(); - // register Network-selection request used to decide selected underlying Network + // Register Network-selection request used to decide selected underlying Network. All + // underlying networks must be VCN managed in order to be used. mConnectivityManager.requestBackgroundNetwork( - getNetworkRequestBase().build(), mHandler, mRouteSelectionCallback); + getBaseNetworkRequest(true /* requireVcnManaged */).build(), + mHandler, + mRouteSelectionCallback); } private NetworkRequest getWifiNetworkRequest() { - return getNetworkRequestBase().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(); + // Request exclusively VCN managed networks to ensure that we only ever keep carrier wifi + // alive. + return getBaseNetworkRequest(true /* requireVcnManaged */) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build(); } private NetworkRequest getCellNetworkRequestForSubId(int subId) { - return getNetworkRequestBase() + // Do not request NOT_VCN_MANAGED to ensure that the TelephonyNetworkFactory has a + // fulfillable request to bring up underlying cellular Networks even if the VCN is already + // connected. + return getBaseNetworkRequest(false /* requireVcnManaged */) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } - private NetworkRequest.Builder getNetworkRequestBase() { - NetworkRequest.Builder requestBase = new NetworkRequest.Builder(); - for (@NetCapability int capability : mRequiredUnderlyingNetworkCapabilities) { + /** + * Builds and returns a NetworkRequest builder common to all Underlying Network requests + * + * <p>A NetworkRequest may either (1) Require the presence of a capability by using + * addCapability(), (2) require the absence of a capability using unwanted capabilities, or (3) + * allow any state. Underlying networks are never desired to have the NOT_VCN_MANAGED + * capability, and only cases (2) and (3) are used. + * + * @param requireVcnManaged whether the underlying network is required to be VCN managed to + * match this request. If {@code true}, the NOT_VCN_MANAGED capability will be set as + * unwanted. Else, the NOT_VCN_MANAGED capability will be removed, and any state is + * acceptable. + */ + private NetworkRequest.Builder getBaseNetworkRequest(boolean requireVcnManaged) { + NetworkRequest.Builder requestBase = + new NetworkRequest.Builder() + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + + for (int capability : mRequiredUnderlyingNetworkCapabilities) { requestBase.addCapability(capability); } - return requestBase - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + if (requireVcnManaged) { + requestBase.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return requestBase; } /** diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index c55913e2e547..3f74938005a7 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -299,9 +299,7 @@ public class Vcn extends Handler { for (VcnGatewayConnectionConfig gatewayConnectionConfig : mConfig.getGatewayConnectionConfigs()) { if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { - Slog.v( - getLogTag(), - "Bringing up new VcnGatewayConnection for request " + request.requestId); + Slog.v(getLogTag(), "Bringing up new VcnGatewayConnection for request " + request); final VcnGatewayConnection vcnGatewayConnection = mDeps.newVcnGatewayConnection( diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 15429f455d6e..69a153f79a1b 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR; @@ -59,6 +60,7 @@ import android.net.ipsec.ike.exceptions.AuthenticationFailedException; import android.net.ipsec.ike.exceptions.IkeException; import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; +import android.net.vcn.VcnControlPlaneIkeConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnTransportInfo; import android.net.wifi.WifiInfo; @@ -1348,7 +1350,7 @@ public class VcnGatewayConnection extends StateMachine { mIkeSession = null; } - mIkeSession = buildIkeSession(); + mIkeSession = buildIkeSession(mUnderlying.network); } @Override @@ -1726,6 +1728,7 @@ public class VcnGatewayConnection extends StateMachine { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); builder.addTransportType(TRANSPORT_CELLULAR); + builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); builder.addCapability(NET_CAPABILITY_NOT_CONGESTED); builder.addCapability(NET_CAPABILITY_NOT_SUSPENDED); @@ -1939,23 +1942,29 @@ public class VcnGatewayConnection extends StateMachine { new EventDisconnectRequestedInfo(reason, shouldQuit)); } - private IkeSessionParams buildIkeParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + private IkeSessionParams buildIkeParams(@NonNull Network network) { + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + final IkeSessionParams.Builder builder = + new IkeSessionParams.Builder(controlPlaneConfig.getIkeSessionParams()); + builder.setConfiguredNetwork(network); + + return builder.build(); } private ChildSessionParams buildChildParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + return controlPlaneConfig.getChildSessionParams(); } @VisibleForTesting(visibility = Visibility.PRIVATE) - VcnIkeSession buildIkeSession() { + VcnIkeSession buildIkeSession(@NonNull Network network) { final int token = ++mCurrentToken; return mDeps.newIkeSession( mVcnContext, - buildIkeParams(), + buildIkeParams(network), buildChildParams(), new IkeSessionCallbackImpl(token), new VcnChildSessionCallback(token)); diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index 07f67327b2bf..1c9683803857 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -40,9 +40,11 @@ import android.content.pm.UserInfo; import android.net.Uri; import android.os.RemoteException; import android.os.UserManager; +import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; +import com.android.server.LocalServices; import com.android.server.SystemService; import org.junit.Before; @@ -60,6 +62,7 @@ import java.util.List; * Tests for {@link com.android.server.apphibernation.AppHibernationService} */ @SmallTest +@Presubmit public final class AppHibernationServiceTest { private static final String PACKAGE_SCHEME = "package"; private static final String PACKAGE_NAME_1 = "package1"; @@ -91,6 +94,7 @@ public final class AppHibernationServiceTest { MockitoAnnotations.initMocks(this); doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt()); + LocalServices.removeServiceForTest(AppHibernationManagerInternal.class); mAppHibernationService = new AppHibernationService(new MockInjector(mContext)); verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java index 59f3c35f2137..2237c845cde7 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java @@ -19,6 +19,7 @@ package com.android.server.apphibernation; import static org.junit.Assert.assertEquals; import android.os.FileUtils; +import android.platform.test.annotations.Presubmit; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; @@ -48,6 +49,7 @@ import java.util.concurrent.TimeoutException; @SmallTest +@Presubmit public class HibernationStateDiskStoreTest { private static final String STATES_FILE_NAME = "states"; private final MockScheduledExecutorService mMockScheduledExecutorService = diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java index f00edcc85404..fcd6b842426a 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java @@ -120,6 +120,11 @@ class CompatConfigBuilder { return this; } + CompatConfigBuilder addEnabledSinceApexChangeWithId(int sdk, long id) { + mChanges.add(new CompatChange(id, "", -1, sdk, false, false, "", false)); + return this; + } + CompatConfig build() { CompatConfig config = new CompatConfig(mBuildClassifier, mContext); config.forceNonDebuggableFinalForTest(false); diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index 8b0e948579fb..bd774056aef8 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -86,6 +86,7 @@ public class CompatConfigTest { // Assume userdebug/eng non-final build when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); + when(mBuildClassifier.platformTargetSdk()).thenReturn(30); ChangeIdStateCache.disable(); when(mPackageManager.getApplicationInfo(anyString(), anyInt())) .thenThrow(new NameNotFoundException()); @@ -567,6 +568,34 @@ public class CompatConfigTest { } @Test + public void testReadApexConfig() throws IOException { + String configXml = "<config>" + + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />" + + "<compat-change id=\"1235\" name=\"MY_CHANGE2\" disabled=\"true\" />" + + "<compat-change id=\"1236\" name=\"MY_CHANGE3\" />" + + "<compat-change id=\"1237\" name=\"MY_CHANGE4\" enableSinceTargetSdk=\"31\" />" + + "</config>"; + + File dir = createTempDir(); + writeToFile(dir, "platform_compat_config.xml", configXml); + CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + + compatConfig.initConfigFromLib(dir); + + assertThat(compatConfig.isChangeEnabled(1234L, + ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse(); + assertThat(compatConfig.isChangeEnabled(1234L, + ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue(); + assertThat(compatConfig.isChangeEnabled(1235L, + ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse(); + assertThat(compatConfig.isChangeEnabled(1236L, + ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue(); + assertThat(compatConfig.isChangeEnabled(1237L, + ApplicationInfoBuilder.create().withTargetSdk(31).build())).isTrue(); + } + + @Test public void testReadConfigMultipleFiles() throws IOException { String configXml1 = "<config>" + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />" @@ -602,12 +631,12 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) .thenReturn(ApplicationInfoBuilder.create() - .withPackageName("foo.bar") - .debuggable() - .build()); + .withPackageName("foo.bar") + .debuggable() + .build()); when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) .thenThrow(new NameNotFoundException()); @@ -649,7 +678,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L, new PackageOverride.Builder() @@ -673,11 +702,11 @@ public class CompatConfigTest { } @Test - public void testLoadOverridesRaw() throws Exception { + public void testInitOverridesRaw() throws Exception { File tempDir = createTempDir(); File overridesFile = new File(tempDir, "overrides.xml"); // Change 1 is enabled for foo.bar (validated) - // Change 2 is disabled for bar.baz (deferred) + // Change 2 is disabled for bar.baz (raw) String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<overrides>\n" + " <change-overrides changeId=\"1\">\n" @@ -709,7 +738,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("foo.bar") .withVersionCode(100L) @@ -728,7 +757,7 @@ public class CompatConfigTest { } @Test - public void testLoadOverridesDeferred() throws Exception { + public void testInitOverridesDeferred() throws Exception { File tempDir = createTempDir(); File overridesFile = new File(tempDir, "overrides.xml"); // Change 1 is enabled for foo.bar (validated) @@ -754,7 +783,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("foo.bar") .debuggable() @@ -767,4 +796,115 @@ public class CompatConfigTest { assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue(); assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse(); } + + @Test + public void testInitOverridesWithStaticFile() throws Exception { + File tempDir = createTempDir(); + File dynamicOverridesFile = new File(tempDir, "dynamic_overrides.xml"); + File staticOverridesFile = new File(tempDir, "static_overrides.xml"); + // Change 1 is enabled for foo.bar (raw) + // Change 2 is disabled for bar.baz (raw) + String dynamicXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>" + + "<change-overrides changeId=\"1\">" + + "<raw>" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "<change-overrides changeId=\"2\">" + + "<raw>" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "</overrides>"; + writeToFile(tempDir, "dynamic_overrides.xml", dynamicXmlData); + // Change 2 is enabled for foo.bar and bar.baz (raw) + // Change 3 is enabled for bar.baz (raw) + String staticXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>" + + "<change-overrides changeId=\"2\">" + + "<raw>" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "<change-overrides changeId=\"3\">" + + "<raw>" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "</overrides>"; + writeToFile(tempDir, "static_overrides.xml", staticXmlData); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1L) + .addDisabledChangeWithId(2L) + .addDisabledChangeWithId(3L) + .build(); + compatConfig.forceNonDebuggableFinalForTest(true); + // Adding an override that will be cleared after initOverrides is called. + compatConfig.addOverride(1L, "bar.baz", true); + compatConfig.initOverrides(dynamicOverridesFile, staticOverridesFile); + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenThrow(new NameNotFoundException()); + when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) + .thenThrow(new NameNotFoundException()); + + assertThat(compatConfig.willChangeBeEnabled(1L, "foo.bar")).isTrue(); + assertThat(compatConfig.willChangeBeEnabled(2L, "foo.bar")).isTrue(); + assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse(); + assertThat(compatConfig.willChangeBeEnabled(3L, "bar.baz")).isTrue(); + assertThat(readFile(dynamicOverridesFile)) + .isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + + "<overrides>\n" + + " <change-overrides changeId=\"1\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + " <change-overrides changeId=\"2\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + " <change-overrides changeId=\"3\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + "</overrides>\n"); + } } diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java index 0fd6445fbeeb..57fdcd340a02 100644 --- a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java @@ -22,6 +22,7 @@ import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARG import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE; import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH; import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE; +import static com.android.internal.compat.OverrideAllowedState.PLATFORM_TOO_OLD; import static com.google.common.truth.Truth.assertThat; @@ -52,6 +53,7 @@ public class OverrideValidatorImplTest { private static final int TARGET_SDK = 10; private static final int TARGET_SDK_BEFORE = 9; private static final int TARGET_SDK_AFTER = 11; + private static final int PLATFORM_SDK_VERSION = 30; @Mock private PackageManager mPackageManager; @@ -61,6 +63,7 @@ public class OverrideValidatorImplTest { private AndroidBuildClassifier debuggableBuild() { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(true); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -68,6 +71,7 @@ public class OverrideValidatorImplTest { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(false); when(buildClassifier.isFinalBuild()).thenReturn(false); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -75,6 +79,7 @@ public class OverrideValidatorImplTest { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(false); when(buildClassifier.isFinalBuild()).thenReturn(true); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -333,6 +338,26 @@ public class OverrideValidatorImplTest { } @Test + public void getOverrideAllowedState_targetSdkChangeGreaterThanOsVersion_rejectOverride() + throws Exception { + final AndroidBuildClassifier buildClassifier = finalBuild(); + CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) + .addEnabledSinceApexChangeWithId(PLATFORM_SDK_VERSION + 1, 1).build(); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .debuggable() + .build()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + assertThat(stateTargetSdkLessChange).isEqualTo( + new OverrideAllowedState(PLATFORM_TOO_OLD, -1, + PLATFORM_SDK_VERSION)); + } + + @Test public void getOverrideAllowedState_finalBuildEnabledChangeDebugApp_rejectOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index 799b06734b54..3fc6e9918382 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -78,11 +78,12 @@ public class PlatformCompatTest { when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenThrow(new PackageManager.NameNotFoundException()); mCompatConfig = new CompatConfig(mBuildClassifier, mContext); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Assume userdebug/eng non-final build mCompatConfig.forceNonDebuggableFinalForTest(false); when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); + when(mBuildClassifier.platformTargetSdk()).thenReturn(30); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); } @@ -99,7 +100,7 @@ public class PlatformCompatTest { .addLoggingOnlyChangeWithId(7L) .addOverridableChangeWithId(8L) .build(); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly( new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), @@ -125,8 +126,9 @@ public class PlatformCompatTest { .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.Q, 5L) .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.R, 6L) .addLoggingOnlyChangeWithId(7L) + .addEnableSinceSdkChangeWithId(31, 8L) .build(); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly( new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), @@ -144,7 +146,7 @@ public class PlatformCompatTest { .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.O, 3L) .build(); mCompatConfig.forceNonDebuggableFinalForTest(true); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Before adding overrides. assertThat(mPlatformCompat.isChangeEnabledByPackageName(1, PACKAGE_NAME, 0)).isTrue(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index b51f4df43259..91342ce925f6 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; @@ -109,7 +110,8 @@ public class RebootEscrowManagerTests { public interface MockableRebootEscrowInjected { int getBootCount(); - void reportMetric(boolean success); + void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, + int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootComplete); } static class MockInjector extends RebootEscrowManager.Injector { @@ -119,6 +121,7 @@ public class RebootEscrowManagerTests { private final UserManager mUserManager; private final MockableRebootEscrowInjected mInjected; private final RebootEscrowKeyStoreManager mKeyStoreManager; + private final boolean mServerBased; MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow, @@ -128,6 +131,7 @@ public class RebootEscrowManagerTests { super(context, storage); mRebootEscrow = rebootEscrow; mServiceConnection = null; + mServerBased = false; RebootEscrowProviderHalImpl.Injector halInjector = new RebootEscrowProviderHalImpl.Injector() { @Override @@ -149,6 +153,7 @@ public class RebootEscrowManagerTests { super(context, storage); mServiceConnection = serviceConnection; mRebootEscrow = null; + mServerBased = true; RebootEscrowProviderServerBasedImpl.Injector injector = new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection); mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(storage, injector); @@ -168,6 +173,11 @@ public class RebootEscrowManagerTests { } @Override + public boolean serverBasedResumeOnReboot() { + return mServerBased; + } + + @Override public RebootEscrowProviderInterface getRebootEscrowProvider() { return mRebootEscrowProvider; } @@ -195,8 +205,11 @@ public class RebootEscrowManagerTests { } @Override - public void reportMetric(boolean success) { - mInjected.reportMetric(success); + public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, + int escrowDurationInSeconds, int vbmetaDigestStatus, + int durationSinceBootComplete) { + mInjected.reportMetric(success, errorCode, serviceType, attemptCount, + escrowDurationInSeconds, vbmetaDigestStatus, durationSinceBootComplete); } } @@ -418,7 +431,9 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + eq(0) /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); mService.loadRebootEscrowDataIfAvailable(null); @@ -451,7 +466,9 @@ public class RebootEscrowManagerTests { // pretend reboot happens here when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + eq(0) /* error code */, eq(2) /* Server based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mServiceConnection.unwrap(any(), anyLong())) .thenAnswer(invocation -> invocation.getArgument(0)); @@ -485,7 +502,8 @@ public class RebootEscrowManagerTests { // pretend reboot happens here when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + anyInt(), anyInt(), eq(2) /* attempt count */, anyInt(), anyInt(), anyInt()); when(mServiceConnection.unwrap(any(), anyLong())) .thenThrow(new IOException()) @@ -528,7 +546,8 @@ public class RebootEscrowManagerTests { mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); - verify(mInjected, never()).reportMetric(anyBoolean()); + verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(), + anyInt(), anyInt(), anyInt()); } @Test @@ -554,7 +573,8 @@ public class RebootEscrowManagerTests { when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); mService.loadRebootEscrowDataIfAvailable(null); - verify(mInjected, never()).reportMetric(anyBoolean()); + verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(), + anyInt(), anyInt(), anyInt()); } @Test @@ -588,7 +608,8 @@ public class RebootEscrowManagerTests { when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); mService.loadRebootEscrowDataIfAvailable(null); - verify(mInjected).reportMetric(eq(true)); + verify(mInjected).reportMetric(eq(true), eq(0) /* error code */, eq(1) /* HAL based */, + eq(1) /* attempt count */, anyInt(), anyInt(), anyInt()); } @Test @@ -615,7 +636,9 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + anyInt() /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> new byte[32]); mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); 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 670bd8107bed..fd4fe56922dd 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 @@ -34,7 +34,6 @@ import android.app.KeyguardManager; import android.content.Context; import android.os.RemoteException; import android.security.GateKeeper; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; @@ -61,6 +60,7 @@ import java.security.UnrecoverableKeyException; import java.util.List; import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; @SmallTest @RunWith(AndroidJUnit4.class) @@ -586,7 +586,7 @@ public class PlatformKeyManagerTest { return (KeyProtection) mProtectionParameterCaptor.getValue(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -595,7 +595,7 @@ public class PlatformKeyManagerTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } class PlatformKeyManagerTestable extends PlatformKeyManager { diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index dc2fb948fdbe..f84dd7b0bb17 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -338,7 +338,7 @@ public abstract class Conference extends Conferenceable { * * @param videoState The video state in which to answer the connection. */ - public void onAnswer(int videoState) {} + public void onAnswer(@VideoProfile.VideoState int videoState) {} /** * Notifies this Conference, which is in {@code STATE_RINGING}, of diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 580513c12453..d82205e20538 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Service; import android.content.ComponentName; import android.content.Intent; @@ -1887,6 +1888,7 @@ public abstract class ConnectionService extends Service { /** {@inheritDoc} */ @Override public final IBinder onBind(Intent intent) { + onBindClient(intent); return mBinder; } @@ -1897,6 +1899,13 @@ public abstract class ConnectionService extends Service { return super.onUnbind(intent); } + /** + * Used for testing to let the test suite know when the connection service has been bound. + * @hide + */ + @TestApi + public void onBindClient(@Nullable Intent intent) { + } /** * This can be used by telecom to either create a new outgoing conference call or attach @@ -2544,9 +2553,9 @@ public abstract class ConnectionService extends Service { * @return The {@code Connection} object to satisfy this call, or {@code null} to * not handle the call. */ - public final RemoteConnection createRemoteIncomingConnection( - PhoneAccountHandle connectionManagerPhoneAccount, - ConnectionRequest request) { + public final @Nullable RemoteConnection createRemoteIncomingConnection( + @NonNull PhoneAccountHandle connectionManagerPhoneAccount, + @NonNull ConnectionRequest request) { return mRemoteConnectionManager.createRemoteConnection( connectionManagerPhoneAccount, request, true); } @@ -2563,9 +2572,9 @@ public abstract class ConnectionService extends Service { * @return The {@code Connection} object to satisfy this call, or {@code null} to * not handle the call. */ - public final RemoteConnection createRemoteOutgoingConnection( - PhoneAccountHandle connectionManagerPhoneAccount, - ConnectionRequest request) { + public final @Nullable RemoteConnection createRemoteOutgoingConnection( + @NonNull PhoneAccountHandle connectionManagerPhoneAccount, + @NonNull ConnectionRequest request) { return mRemoteConnectionManager.createRemoteConnection( connectionManagerPhoneAccount, request, false); } @@ -2805,12 +2814,14 @@ public abstract class ConnectionService extends Service { * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. * @param request Details about the incoming conference call. - * @return The {@code Conference} object to satisfy this call, or {@code null} to - * not handle the call. + * @return The {@code Conference} object to satisfy this call. If the conference attempt is + * failed, the return value will be a result of an invocation of + * {@link Connection#createFailedConnection(DisconnectCause)}. + * Return {@code null} if the {@link ConnectionService} cannot handle the call. */ public @Nullable Conference onCreateIncomingConference( - @Nullable PhoneAccountHandle connectionManagerPhoneAccount, - @Nullable ConnectionRequest request) { + @NonNull PhoneAccountHandle connectionManagerPhoneAccount, + @NonNull ConnectionRequest request) { return null; } @@ -2913,8 +2924,8 @@ public abstract class ConnectionService extends Service { * @param request The outgoing connection request. */ public void onCreateOutgoingConferenceFailed( - @Nullable PhoneAccountHandle connectionManagerPhoneAccount, - @Nullable ConnectionRequest request) { + @NonNull PhoneAccountHandle connectionManagerPhoneAccount, + @NonNull ConnectionRequest request) { } @@ -2978,12 +2989,14 @@ public abstract class ConnectionService extends Service { * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for * making the connection. * @param request Details about the outgoing call. - * @return The {@code Conference} object to satisfy this call, or the result of an invocation - * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call. + * @return The {@code Conference} object to satisfy this call. If the conference attempt is + * failed, the return value will be a result of an invocation of + * {@link Connection#createFailedConnection(DisconnectCause)}. + * Return {@code null} if the {@link ConnectionService} cannot handle the call. */ public @Nullable Conference onCreateOutgoingConference( - @Nullable PhoneAccountHandle connectionManagerPhoneAccount, - @Nullable ConnectionRequest request) { + @NonNull PhoneAccountHandle connectionManagerPhoneAccount, + @NonNull ConnectionRequest request) { return null; } diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java index b153fefce6e3..9e1dee0162b9 100644 --- a/telephony/java/android/telephony/CarrierBandwidth.java +++ b/telephony/java/android/telephony/CarrierBandwidth.java @@ -101,7 +101,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the primary network in Kbps. This always only refers to + * Retrieves the upstream bandwidth for the primary network in kbps. This always only refers to * the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -112,7 +112,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the primary network in Kbps. This always only refers + * Retrieves the downstream bandwidth for the primary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -123,7 +123,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the secondary network in Kbps. This always only refers + * Retrieves the upstream bandwidth for the secondary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: @@ -143,7 +143,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the secondary network in Kbps. This always only + * Retrieves the downstream bandwidth for the secondary network in kbps. This always only * refers to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 9c9670c99c2d..dc05488618cf 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -33,7 +33,11 @@ import android.os.RemoteException; import android.service.carrier.CarrierService; import android.telecom.TelecomManager; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.ImsSsData; +import android.telephony.ims.SipDelegateManager; +import android.telephony.ims.feature.MmTelFeature; +import android.telephony.ims.feature.RcsFeature; import com.android.internal.telephony.ICarrierConfigLoader; import com.android.telephony.Rlog; @@ -3941,6 +3945,43 @@ public class CarrierConfigManager { KEY_PREFIX + "enable_presence_publish_bool"; /** + * Each string in this array contains a mapping between the service-id and version portion + * of the service-description element and the associated IMS feature tag(s) that are + * associated with each element (see RCC.07 Table 7). + * <p> + * Each string contains 3 parts, which define the mapping between service-description and + * feature tag(s) that must be present in the IMS REGISTER for the RCS service to be + * published as part of the RCS PUBLISH procedure: + * [service-id]|[version]|[desc]|[feature_tag];[feature_tag];... + * <ul> + * <li>[service-id]: the service-id element associated with the RCS capability.</li> + * <li>[version]: The version element associated with that service-id</li> + * <li>[desc]: The optional desecription element associated with that service-id</li> + * <li>[feature_tag];[feature_tag]: The list of all feature tags associated with this + * capability that MUST ALL be present in the IMS registration for this this + * capability to be published to the network.</li> + * </ul> + * <p> + * Features managed by the framework will be considered capable when the ImsService reports + * that those services are capable via the + * {@link MmTelFeature#notifyCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities)} or + * {@link RcsFeature#notifyCapabilitiesStatusChanged(RcsFeature.RcsImsCapabilities)} APIs. + * For RCS services not managed by the framework, the capability of these services are + * determined by looking at the feature tags associated with the IMS registration using the + * {@link ImsRegistrationAttributes} API and mapping them to the service-description map. + * <p> + * The framework contains a default value of this key, which is based off of RCC.07 + * specification. Capabilities based of carrier extensions may be added to this list on a + * carrier-by-carrier basis as required in order to support additional services in the + * PUBLISH. If this list contains a service-id and version that overlaps with the default, + * it will override the framework default. + * @hide + */ + @SystemApi + public static final String KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY = + KEY_PREFIX + "publish_service_desc_feature_tag_map_override_string_array"; + + /** * Flag indicating whether or not this carrier supports the exchange of phone numbers with * the carrier's RCS presence server in order to retrieve the RCS capabilities of requested * contacts used in the RCS User Capability Exchange (UCE) procedure. See RCC.71, section 3 @@ -3999,6 +4040,8 @@ public class CarrierConfigManager { defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000); defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false); defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false); + defaults.putStringArray(KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY, + new String[] {}); defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false); defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false); defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index e3853fabfd7a..8244342eee19 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -14120,12 +14120,11 @@ public class TelephonyManager { * {@link #NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE} * </ol> * @return operation result. - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * @throws IllegalStateException if the Telephony process is not currently available. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public @EnableNrDualConnectivityResult int setNrDualConnectivityState( @NrDualConnectivityState int nrDualConnectivityState) { try { @@ -14721,13 +14720,17 @@ public class TelephonyManager { * </ul> * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN} - * @param nafId Network Application Function(NAF) fully qualified domain name and - * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first - * part is the constant string "3GPP-bootstrapping" (GBA_ME), - * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest), - * and the latter part shall be the FQDN of the NAF (e.g. - * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com", - * or "3GPP-bootstrapping-digest@naf1.operator.com"). + * @param nafId A URI to specify Network Application Function(NAF) fully qualified domain + * name (FQDN) and the selected GBA mode. The authority of the URI must contain two parts + * delimited by "@" sign. The first part is the constant string "3GPP-bootstrapping" (GBA_ME), + * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest). + * The second part shall be the FQDN of the NAF. The scheme of the URI is not actually used + * for the authentication, which may be set the same as the resource that the application is + * going to access. For example, the nafId can be + * "https://3GPP-bootstrapping@naf1.operator.com", + * "https://3GPP-bootstrapping-uicc@naf1.operator.com", + * "https://3GPP-bootstrapping-digest@naf1.operator.com", + * "ftps://3GPP-bootstrapping-digest@naf1.operator.com". * @param securityProtocol Security protocol identifier between UE and NAF. See * 3GPP TS 33.220 Annex H. Application can use * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId}, diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index ca1f861f9808..363e47a6d242 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -254,15 +254,15 @@ public class DataServiceCallback { } /** - * The APN is throttled for the duration specified in - * {@link DataCallResponse#getRetryDurationMillis}. Calling this method unthrottles that - * APN. + * Unthrottles the APN on the current transport. There is no matching "APN throttle" method. + * Instead, the APN is throttled for the time specified in + * {@link DataCallResponse#getRetryDurationMillis}. * <p/> * see: {@link DataCallResponse#getRetryDurationMillis} * * @param apn Access Point Name defined by the carrier. */ - public void onApnUnthrottled(@NonNull String apn) { + public void onApnUnthrottled(final @NonNull String apn) { if (mCallback != null) { try { if (DBG) Rlog.d(TAG, "onApnUnthrottled"); diff --git a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java index 041edc00c4d2..406c38bf60ef 100644 --- a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java +++ b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java @@ -184,16 +184,6 @@ public final class EpsBearerQosSessionAttributes implements Parcelable, QosSessi mRemoteAddresses = Collections.unmodifiableList(remoteAddresses); } - /** - * Creates attributes based off of a parcel - * @param in the parcel - * @return the attributes - */ - @NonNull - public static EpsBearerQosSessionAttributes create(@NonNull final Parcel in) { - return new EpsBearerQosSessionAttributes(in); - } - @Override public int describeContents() { return 0; diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index aa9145b01be9..1e80ab7a405c 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -993,6 +993,16 @@ public class ProvisioningManager { } } + @Override + public void onPreProvisioningReceived(byte[] configXml) { + final long identity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onPreProvisioningReceived(configXml)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + private void setExecutor(Executor executor) { mExecutor = executor; } @@ -1005,7 +1015,7 @@ public class ProvisioningManager { * due to various triggers defined in GSMA RCC.14 for ACS(auto configuration * server) or other operator defined triggers. If RCS provisioning is already * completed at the time of callback registration, then this method shall be - * invoked with the current configuration + * invoked with the current configuration. * @param configXml The RCS configuration XML received by OTA. It is defined * by GSMA RCC.07. */ @@ -1038,6 +1048,20 @@ public class ProvisioningManager { */ public void onRemoved() {} + /** + * Some carriers using ACS (auto configuration server) may send a carrier-specific + * pre-provisioning configuration XML if the user has not been provisioned for RCS + * services yet. When this provisioning XML is received, the framework will move + * into a "not provisioned" state for RCS. In order for provisioning to proceed, + * the application must parse this configuration XML and perform the carrier specific + * opt-in flow for RCS services. If the user accepts, {@link #triggerRcsReconfiguration} + * must be called in order for the device to move out of this state and try to fetch + * the RCS provisioning information. + * + * @param configXml the pre-provisioning config in carrier specified format. + */ + public void onPreProvisioningReceived(@NonNull byte[] configXml) {} + /**@hide*/ public final IRcsConfigCallback getBinder() { return mBinder; diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java index 5eb75e762fc9..9c28c36521f5 100644 --- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java +++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java @@ -21,11 +21,16 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SystemApi; import android.net.Uri; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -38,6 +43,17 @@ import java.util.List; @SystemApi public final class RcsContactPresenceTuple implements Parcelable { + private static final String LOG_TAG = "RcsContactPresenceTuple"; + + /** + * The service ID used to indicate that service discovery via presence is available. + * <p> + * See RCC.07 v5.0 specification for more information. + * @hide + */ + public static final String SERVICE_ID_PRESENCE = + "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp"; + /** * The service ID used to indicate that MMTEL service is available. * <p> @@ -329,6 +345,13 @@ public final class RcsContactPresenceTuple implements Parcelable { public @NonNull @DuplexMode List<String> getUnsupportedDuplexModes() { return Collections.unmodifiableList(mUnsupportedDuplexModeList); } + + @Override + public String toString() { + return "servCaps{" + "a=" + mIsAudioCapable + ", v=" + mIsVideoCapable + + ", supported=" + mSupportedDuplexModeList + ", unsupported=" + + mUnsupportedDuplexModeList + '}'; + } } /** @@ -353,7 +376,8 @@ public final class RcsContactPresenceTuple implements Parcelable { } /** - * The optional SIP Contact URI associated with the PIDF tuple element. + * The optional SIP Contact URI associated with the PIDF tuple element if the network + * expects the user to use the URI instead of the contact URI to contact it. */ public @NonNull Builder setContactUri(@NonNull Uri contactUri) { mPresenceTuple.mContactUri = contactUri; @@ -365,7 +389,7 @@ public final class RcsContactPresenceTuple implements Parcelable { * Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format * string per RFC3339. */ - public @NonNull Builder setTimestamp(@NonNull String timestamp) { + public @NonNull Builder setTime(@NonNull Instant timestamp) { mPresenceTuple.mTimestamp = timestamp; return this; } @@ -397,7 +421,7 @@ public final class RcsContactPresenceTuple implements Parcelable { } private Uri mContactUri; - private String mTimestamp; + private Instant mTimestamp; private @BasicStatus String mStatus; // The service information in the service-description element. @@ -416,7 +440,7 @@ public final class RcsContactPresenceTuple implements Parcelable { private RcsContactPresenceTuple(Parcel in) { mContactUri = in.readParcelable(Uri.class.getClassLoader()); - mTimestamp = in.readString(); + mTimestamp = convertStringFormatTimeToInstant(in.readString()); mStatus = in.readString(); mServiceId = in.readString(); mServiceVersion = in.readString(); @@ -427,7 +451,7 @@ public final class RcsContactPresenceTuple implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { out.writeParcelable(mContactUri, flags); - out.writeString(mTimestamp); + out.writeString(convertInstantToStringFormat(mTimestamp)); out.writeString(mStatus); out.writeString(mServiceId); out.writeString(mServiceVersion); @@ -453,6 +477,26 @@ public final class RcsContactPresenceTuple implements Parcelable { } }; + // Convert the Instant to the string format + private String convertInstantToStringFormat(Instant instant) { + if (instant == null) { + return ""; + } + return instant.toString(); + } + + // Convert the time string format to Instant + private @Nullable Instant convertStringFormatTimeToInstant(String timestamp) { + if (TextUtils.isEmpty(timestamp)) { + return null; + } + try { + return DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp, Instant::from); + } catch (DateTimeParseException e) { + return null; + } + } + /** @return the status of the tuple element. */ public @NonNull @BasicStatus String getStatus() { return mStatus; @@ -474,7 +518,7 @@ public final class RcsContactPresenceTuple implements Parcelable { } /** @return the timestamp element contained in the tuple if it exists */ - public @Nullable String getTimestamp() { + public @Nullable Instant getTime() { return mTimestamp; } @@ -487,4 +531,36 @@ public final class RcsContactPresenceTuple implements Parcelable { public @Nullable ServiceCapabilities getServiceCapabilities() { return mServiceCapabilities; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("{"); + if (Build.IS_ENG) { + builder.append("u="); + builder.append(mContactUri); + } else { + builder.append("u="); + builder.append(mContactUri != null ? "XXX" : "null"); + } + builder.append(", id="); + builder.append(mServiceId); + builder.append(", v="); + builder.append(mServiceVersion); + builder.append(", s="); + builder.append(mStatus); + if (mTimestamp != null) { + builder.append(", timestamp="); + builder.append(mTimestamp); + } + if (mServiceDescription != null) { + builder.append(", servDesc="); + builder.append(mServiceDescription); + } + if (mServiceCapabilities != null) { + builder.append(", servCaps="); + builder.append(mServiceCapabilities); + } + builder.append("}"); + return builder.toString(); + } } diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java index fe855023f5d0..52d0f036788c 100644 --- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java +++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -339,9 +340,45 @@ public final class RcsContactUceCapability implements Parcelable { } /** + * Retrieve the contact URI requested by the applications. * @return the URI representing the contact associated with the capabilities. */ public @NonNull Uri getContactUri() { return mContactUri; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("RcsContactUceCapability"); + if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) { + builder.append("(presence) {"); + } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) { + builder.append("(options) {"); + } else { + builder.append("(?) {"); + } + if (Build.IS_ENG) { + builder.append("uri="); + builder.append(mContactUri); + } else { + builder.append("uri (isNull)="); + builder.append(mContactUri != null ? "XXX" : "null"); + } + builder.append(", sourceType="); + builder.append(mSourceType); + builder.append(", requestResult="); + builder.append(mRequestResult); + + if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) { + builder.append(", presenceTuples={"); + builder.append(mPresenceTuples); + builder.append("}"); + } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) { + builder.append(", featureTags={"); + builder.append(mFeatureTags); + builder.append("}"); + } + + return builder.toString(); + } } diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index ce8bd7d8c28e..dd9102699529 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -36,6 +36,8 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -430,7 +432,8 @@ public class RcsUceAdapter { /** * The pending request has completed successfully due to all requested contacts information - * being delivered. + * being delivered. The callback {@link #onCapabilitiesReceived(List)} + * for each contacts is required to be called before {@link #onComplete} is called. */ void onComplete(); @@ -486,7 +489,7 @@ public class RcsUceAdapter { @SystemApi @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, Manifest.permission.READ_CONTACTS}) - public void requestCapabilities(@NonNull List<Uri> contactNumbers, + public void requestCapabilities(@NonNull Collection<Uri> contactNumbers, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c) throws ImsException { if (c == null) { @@ -538,7 +541,7 @@ public class RcsUceAdapter { try { imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(), - mContext.getAttributionTag(), contactNumbers, internalCallback); + mContext.getAttributionTag(), new ArrayList(contactNumbers), internalCallback); } catch (ServiceSpecificException e) { throw new ImsException(e.toString(), e.errorCode); } catch (RemoteException e) { @@ -569,6 +572,10 @@ public class RcsUceAdapter { * {@link CapabilitiesCallback} is called. * @param c A one-time callback for when the request for capabilities completes or there is * an error processing the request. + * @throws ImsException if the subscription associated with this instance of + * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not + * available. This can happen if the ImsService has crashed, for example, or if the subscription + * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl index 5a8973e37bce..d0853d1846ac 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl @@ -25,5 +25,6 @@ oneway interface IRcsConfigCallback { void onAutoConfigurationErrorReceived(int errorCode, String errorString); void onConfigurationReset(); void onRemoved(); + void onPreProvisioningReceived(in byte[] config); } diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 34984e05e181..4dcb7f59f4a7 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -542,11 +542,34 @@ public class ImsConfigImplBase { } mRcsCallbacks.broadcastAction(c -> { try { - //TODO compressed by default? c.onAutoConfigurationErrorReceived(errorCode, errorString); } catch (RemoteException e) { Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping."); } }); } + + /** + * Notifies application that pre-provisioning config is received. + * + * <p>Some carriers using ACS (auto configuration server) may send a carrier-specific + * pre-provisioning configuration XML if the user has not been provisioned for RCS + * services yet. When such provisioning XML is received, ACS client must call this + * method to notify the application with the XML. + * + * @param configXml the pre-provisioning config in carrier specified format. + */ + public final void notifyPreProvisioningReceived(@NonNull byte[] configXml) { + // can be null in testing + if (mRcsCallbacks == null) { + return; + } + mRcsCallbacks.broadcastAction(c -> { + try { + c.onPreProvisioningReceived(configXml); + } catch (RemoteException e) { + Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping."); + } + }); + } } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java index 908869beb607..03e17fbc2c0d 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -31,6 +31,7 @@ import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; @@ -241,7 +242,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}. + * {@link #subscribeForCapabilities(Collection, SubscribeResponseCallback)}. * <p> * If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the * framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate}, @@ -266,7 +267,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also + * {@link #subscribeForCapabilities(Collection, SubscribeResponseCallback)} that also * includes a reason provided in the “reason” header. See RFC3326 for more * information. * @@ -385,13 +386,13 @@ public class RcsCapabilityExchangeImplBase { * {@link SubscribeResponseCallback#onTerminated(String, long)} must be called for the * framework to finish listening for NOTIFY responses. * - * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE - * capabilities for. + * @param uris A {@link Collection} of the {@link Uri}s that the framework is requesting the + * UCE capabilities for. * @param cb The callback of the subscribe request. */ // executor used is defined in the constructor. @SuppressLint("ExecutorRegistration") - public void subscribeForCapabilities(@NonNull List<Uri> uris, + public void subscribeForCapabilities(@NonNull Collection<Uri> uris, @NonNull SubscribeResponseCallback cb) { // Stub - to be implemented by service Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation."); diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING index 89fc6ea2c47b..d659688700d3 100644 --- a/tests/net/TEST_MAPPING +++ b/tests/net/TEST_MAPPING @@ -9,6 +9,23 @@ "name": "FrameworksNetDeflakeTest" } ], + "auto-postsubmit": [ + // Test tag for automotive targets. These are only running in postsubmit so as to harden the + // automotive targets to avoid introducing additional test flake and build time. The plan for + // presubmit testing for auto is to augment the existing tests to cover auto use cases as well. + // Additionally, this tag is used in targeted test suites to limit resource usage on the test + // infra during the hardening phase. + // TODO: this tag to be removed once the above is no longer an issue. + { + "name": "FrameworksNetTests" + }, + { + "name": "FrameworksNetIntegrationTests" + }, + { + "name": "FrameworksNetDeflakeTest" + } + ], "imports": [ { "path": "cts/tests/tests/net" diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 5d0e016d50fa..0dfec7592274 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -28,6 +28,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; @@ -44,6 +45,10 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES; import static android.os.Process.INVALID_UID; +import static com.android.modules.utils.build.SdkLevel.isAtLeastR; +import static com.android.modules.utils.build.SdkLevel.isAtLeastS; +import static com.android.testutils.MiscAsserts.assertEmpty; +import static com.android.testutils.MiscAsserts.assertThrows; import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; import static com.android.testutils.ParcelUtils.parcelingRoundTrip; @@ -67,7 +72,7 @@ import android.util.ArraySet; import androidx.test.runner.AndroidJUnit4; -import com.android.modules.utils.build.SdkLevel; +import com.android.testutils.CompatUtil; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; @@ -84,6 +89,9 @@ import java.util.Set; public class NetworkCapabilitiesTest { private static final String TEST_SSID = "TEST_SSID"; private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID"; + private static final int TEST_SUBID1 = 1; + private static final int TEST_SUBID2 = 2; + private static final int TEST_SUBID3 = 3; @Rule public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); @@ -91,14 +99,6 @@ public class NetworkCapabilitiesTest { private DiscoverySession mDiscoverySession = Mockito.mock(DiscoverySession.class); private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class); - private boolean isAtLeastR() { - return SdkLevel.isAtLeastR(); - } - - private boolean isAtLeastS() { - return SdkLevel.isAtLeastS(); - } - @Test public void testMaybeMarkCapabilitiesRestricted() { // verify EIMS is restricted @@ -211,7 +211,7 @@ public class NetworkCapabilitiesTest { nc1 = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI); nc2 = new NetworkCapabilities() .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(new StringNetworkSpecifier("specs")); + .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier("eth42")); assertNotEquals("", nc1.describeImmutableDifferences(nc2)); assertEquals("", nc1.describeImmutableDifferences(nc1)); } @@ -304,7 +304,9 @@ public class NetworkCapabilitiesTest { .setUids(uids) .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED); - if (isAtLeastR()) { + if (isAtLeastS()) { + netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2)); + } else if (isAtLeastR()) { netCap.setOwnerUid(123); netCap.setAdministratorUids(new int[] {5, 11}); } @@ -379,7 +381,7 @@ public class NetworkCapabilitiesTest { private void testParcelSane(NetworkCapabilities cap) { if (isAtLeastS()) { - assertParcelSane(cap, 16); + assertParcelSane(cap, 17); } else if (isAtLeastR()) { assertParcelSane(cap, 15); } else { @@ -613,6 +615,20 @@ public class NetworkCapabilitiesTest { assertFalse(nc2.appliesToUid(12)); assertTrue(nc1.appliesToUid(22)); assertTrue(nc2.appliesToUid(22)); + + // Verify the subscription id list can be combined only when they are equal. + if (isAtLeastS()) { + nc1.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2)); + nc2.setSubIds(Set.of(TEST_SUBID2)); + assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1)); + + nc2.setSubIds(Set.of()); + assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1)); + + nc2.setSubIds(Set.of(TEST_SUBID2, TEST_SUBID1)); + nc2.combineCapabilities(nc1); + assertEquals(Set.of(TEST_SUBID2, TEST_SUBID1), nc2.getSubIds()); + } } @Test @IgnoreUpTo(Build.VERSION_CODES.Q) @@ -671,7 +687,7 @@ public class NetworkCapabilitiesTest { NetworkCapabilities nc1 = new NetworkCapabilities(); nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI); try { - nc1.setNetworkSpecifier(new StringNetworkSpecifier("specs")); + nc1.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier("eth0")); fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!"); } catch (IllegalStateException expected) { // empty @@ -680,7 +696,7 @@ public class NetworkCapabilitiesTest { // Sequence 2: Transport + NetworkSpecifier + Transport NetworkCapabilities nc2 = new NetworkCapabilities(); nc2.addTransportType(TRANSPORT_CELLULAR).setNetworkSpecifier( - new StringNetworkSpecifier("specs")); + CompatUtil.makeEthernetNetworkSpecifier("testtap3")); try { nc2.addTransportType(TRANSPORT_WIFI); fail("Cannot set a second TransportType of a network which has a NetworkSpecifier!"); @@ -761,6 +777,24 @@ public class NetworkCapabilitiesTest { nc1.setUids(uidRange(10, 13)); nc2.set(nc1); // Overwrites, as opposed to combineCapabilities assertEquals(nc1, nc2); + + if (isAtLeastS()) { + assertThrows(NullPointerException.class, () -> nc1.setSubIds(null)); + nc1.setSubIds(Set.of()); + nc2.set(nc1); + assertEquals(nc1, nc2); + + nc1.setSubIds(Set.of(TEST_SUBID1)); + nc2.set(nc1); + assertEquals(nc1, nc2); + + nc2.setSubIds(Set.of(TEST_SUBID2, TEST_SUBID1)); + nc2.set(nc1); + assertEquals(nc1, nc2); + + nc2.setSubIds(Set.of(TEST_SUBID3, TEST_SUBID2)); + assertNotEquals(nc1, nc2); + } } @Test @@ -841,6 +875,50 @@ public class NetworkCapabilitiesTest { } catch (NullPointerException expected) { } } + private static NetworkCapabilities capsWithSubIds(Integer ... subIds) { + // Since the NetworkRequest would put NOT_VCN_MANAGED capabilities in general, for + // every NetworkCapabilities that simulates networks needs to add it too in order to + // satisfy these requests. + final NetworkCapabilities nc = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) + .setSubIds(new ArraySet<>(subIds)).build(); + assertEquals(new ArraySet<>(subIds), nc.getSubIds()); + return nc; + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testSubIds() throws Exception { + final NetworkCapabilities ncWithoutId = capsWithSubIds(); + final NetworkCapabilities ncWithId = capsWithSubIds(TEST_SUBID1); + final NetworkCapabilities ncWithOtherIds = capsWithSubIds(TEST_SUBID1, TEST_SUBID3); + final NetworkCapabilities ncWithoutRequestedIds = capsWithSubIds(TEST_SUBID3); + + final NetworkRequest requestWithoutId = new NetworkRequest.Builder().build(); + assertEmpty(requestWithoutId.networkCapabilities.getSubIds()); + final NetworkRequest requestWithIds = new NetworkRequest.Builder() + .setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2)).build(); + assertEquals(Set.of(TEST_SUBID1, TEST_SUBID2), + requestWithIds.networkCapabilities.getSubIds()); + + assertFalse(requestWithIds.canBeSatisfiedBy(ncWithoutId)); + assertTrue(requestWithIds.canBeSatisfiedBy(ncWithOtherIds)); + assertFalse(requestWithIds.canBeSatisfiedBy(ncWithoutRequestedIds)); + assertTrue(requestWithIds.canBeSatisfiedBy(ncWithId)); + assertTrue(requestWithoutId.canBeSatisfiedBy(ncWithoutId)); + assertTrue(requestWithoutId.canBeSatisfiedBy(ncWithId)); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testEqualsSubIds() throws Exception { + assertEquals(capsWithSubIds(), capsWithSubIds()); + assertNotEquals(capsWithSubIds(), capsWithSubIds(TEST_SUBID1)); + assertEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID1)); + assertNotEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID2)); + assertNotEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID2, TEST_SUBID1)); + assertEquals(capsWithSubIds(TEST_SUBID1, TEST_SUBID2), + capsWithSubIds(TEST_SUBID2, TEST_SUBID1)); + } + @Test public void testLinkBandwidthKbps() { final NetworkCapabilities nc = new NetworkCapabilities(); @@ -1021,5 +1099,11 @@ public class NetworkCapabilitiesTest { fail("Should not set null into NetworkCapabilities.Builder"); } catch (NullPointerException expected) { } assertEquals(nc, new NetworkCapabilities.Builder(nc).build()); + + if (isAtLeastS()) { + final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() + .setSubIds(Set.of(TEST_SUBID1)).build(); + assertEquals(Set.of(TEST_SUBID1), nc2.getSubIds()); + } } } diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt index bcc907285e35..340e6f963137 100644 --- a/tests/net/common/java/android/net/NetworkProviderTest.kt +++ b/tests/net/common/java/android/net/NetworkProviderTest.kt @@ -27,6 +27,7 @@ import android.os.HandlerThread import android.os.Looper import androidx.test.InstrumentationRegistry import com.android.net.module.util.ArrayTrackRecord +import com.android.testutils.CompatUtil import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner import com.android.testutils.isDevSdkInRange @@ -102,7 +103,8 @@ class NetworkProviderTest { mCm.registerNetworkProvider(provider) assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE) - val specifier = StringNetworkSpecifier(UUID.randomUUID().toString()) + val specifier = CompatUtil.makeTestNetworkSpecifier( + UUID.randomUUID().toString()) val nr: NetworkRequest = NetworkRequest.Builder() .addTransportType(TRANSPORT_TEST) .setNetworkSpecifier(specifier) @@ -183,7 +185,8 @@ class NetworkProviderTest { mCm.registerNetworkProvider(provider) - val specifier = StringNetworkSpecifier(UUID.randomUUID().toString()) + val specifier = CompatUtil.makeTestNetworkSpecifier( + UUID.randomUUID().toString()) val nr: NetworkRequest = NetworkRequest.Builder() .addTransportType(TRANSPORT_TEST) .setNetworkSpecifier(specifier) diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index e1da3d0ae2b3..01d8186c7d1b 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -64,6 +64,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { private final HandlerThread mHandlerThread; private final Context mContext; private final String mLogTag; + private final NetworkAgentConfig mNetworkAgentConfig; private final ConditionVariable mDisconnected = new ConditionVariable(); private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); @@ -115,13 +116,19 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { mHandlerThread = new HandlerThread(mLogTag); mHandlerThread.start(); - mNetworkAgent = makeNetworkAgent(linkProperties, type, typeName); + // extraInfo is set to "" by default in NetworkAgentConfig. + final String extraInfo = (transport == TRANSPORT_CELLULAR) ? "internet.apn" : ""; + mNetworkAgentConfig = new NetworkAgentConfig.Builder() + .setLegacyType(type) + .setLegacyTypeName(typeName) + .setLegacyExtraInfo(extraInfo) + .build(); + mNetworkAgent = makeNetworkAgent(linkProperties, mNetworkAgentConfig); } protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, - final int type, final String typeName) - throws Exception { - return new InstrumentedNetworkAgent(this, linkProperties, type, typeName); + final NetworkAgentConfig nac) throws Exception { + return new InstrumentedNetworkAgent(this, linkProperties, nac); } public static class InstrumentedNetworkAgent extends NetworkAgent { @@ -129,11 +136,9 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider"; public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, - final int type, final String typeName) { + NetworkAgentConfig nac) { super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag, - wrapper.mNetworkCapabilities, lp, wrapper.mScore, - new NetworkAgentConfig.Builder() - .setLegacyType(type).setLegacyTypeName(typeName).build(), + wrapper.mNetworkCapabilities, lp, wrapper.mScore, nac, new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(), PROVIDER_NAME)); mWrapper = wrapper; @@ -301,6 +306,14 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { return mNetworkCapabilities; } + public int getLegacyType() { + return mNetworkAgentConfig.getLegacyType(); + } + + public String getExtraInfo() { + return mNetworkAgentConfig.getLegacyExtraInfo(); + } + public @NonNull ArrayTrackRecord<CallbackType>.ReadHead getCallbackHistory() { return mCallbackHistory; } diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java index 6a09b0237a38..6fc605e269fe 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/tests/net/java/android/net/ConnectivityManagerTest.java @@ -220,7 +220,7 @@ public class ConnectivityManagerTest { // register callback when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(request); + anyInt(), any(), nullable(String.class))).thenReturn(request); manager.requestNetwork(request, callback, handler); // callback triggers @@ -248,7 +248,7 @@ public class ConnectivityManagerTest { // register callback when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(req1); + anyInt(), any(), nullable(String.class))).thenReturn(req1); manager.requestNetwork(req1, callback, handler); // callback triggers @@ -266,7 +266,7 @@ public class ConnectivityManagerTest { // callback can be registered again when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(req2); + anyInt(), any(), nullable(String.class))).thenReturn(req2); manager.requestNetwork(req2, callback, handler); // callback triggers @@ -289,8 +289,8 @@ public class ConnectivityManagerTest { info.targetSdkVersion = VERSION_CODES.N_MR1 + 1; when(mCtx.getApplicationInfo()).thenReturn(info); - when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), any(), - nullable(String.class))).thenReturn(request); + when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(), + any(), nullable(String.class))).thenReturn(request); Handler handler = new Handler(Looper.getMainLooper()); manager.requestNetwork(request, callback, handler); @@ -358,34 +358,34 @@ public class ConnectivityManagerTest { manager.requestNetwork(request, callback); verify(mService).requestNetwork(eq(request.networkCapabilities), - eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); // Verify that register network callback does not calls requestNetwork at all. manager.registerNetworkCallback(request, callback); - verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), + verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(), any(), any()); - verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), + verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); manager.registerDefaultNetworkCallback(callback); verify(mService).requestNetwork(eq(null), - eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); - manager.requestBackgroundNetwork(request, null, callback); + Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); + manager.requestBackgroundNetwork(request, handler, callback); verify(mService).requestNetwork(eq(request.networkCapabilities), - eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); - Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); manager.registerSystemDefaultNetworkCallback(callback, handler); verify(mService).requestNetwork(eq(null), - eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a643bc8a94c0..2c8c8a6409ea 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -266,7 +266,6 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.app.IBatteryStats; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.internal.util.ArrayUtils; @@ -428,7 +427,6 @@ public class ConnectivityServiceTest { @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; @Mock NetworkStatsManager mStatsManager; - @Mock IBatteryStats mBatteryStatsService; @Mock IDnsResolver mMockDnsResolver; @Mock INetd mMockNetd; @Mock NetworkStackClient mNetworkStack; @@ -720,7 +718,7 @@ public class ConnectivityServiceTest { @Override protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, - final int type, final String typeName) throws Exception { + NetworkAgentConfig nac) throws Exception { mNetworkMonitor = mock(INetworkMonitor.class); final Answer validateAnswer = inv -> { @@ -739,8 +737,8 @@ public class ConnectivityServiceTest { any() /* name */, nmCbCaptor.capture()); - final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties, - type, typeName) { + final InstrumentedNetworkAgent na = + new InstrumentedNetworkAgent(this, linkProperties, nac) { @Override public void networkStatus(int status, String redirectUrl) { mRedirectUrl = redirectUrl; @@ -1456,6 +1454,8 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mPackageManager.getTargetSdkVersion(anyString())) + .thenReturn(applicationInfo.targetSdkVersion); when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. @@ -1527,12 +1527,12 @@ public class ConnectivityServiceTest { doReturn(mSystemProperties).when(deps).getSystemProperties(); doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); - doReturn(mBatteryStatsService).when(deps).getBatteryStatsService(); doAnswer(inv -> { mPolicyTracker = new WrappedMultinetworkPolicyTracker( inv.getArgument(0), inv.getArgument(1), inv.getArgument(2)); return mPolicyTracker; }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any()); + doReturn(true).when(deps).getCellular464XlatEnabled(); return deps; } @@ -1743,11 +1743,29 @@ public class ConnectivityServiceTest { return expected; } + private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) { + final DetailedState state = ni.getDetailedState(); + if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false; + // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION + // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also + // nulls out extraInfo. + if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false; + // Can't make any assertions about DISCONNECTED broadcasts. When a network actually + // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo + // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to + // a network switch, extraInfo will likely be populated. + // This is likely a bug in CS, but likely not one we can fix without impacting apps. + return true; + } + private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) { - return registerConnectivityBroadcastThat(1, intent -> - type == intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) && state.equals( - ((NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO)) - .getDetailedState())); + return registerConnectivityBroadcastThat(1, intent -> { + final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1); + final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO); + return type == actualType + && state == ni.getDetailedState() + && extraInfoInBroadcastHasExpectedNullness(ni); + }); } @Test @@ -3733,8 +3751,8 @@ public class ConnectivityServiceTest { networkCapabilities.addTransportType(TRANSPORT_WIFI) .setNetworkSpecifier(new MatchAllNetworkSpecifier()); mService.requestNetwork(networkCapabilities, NetworkRequest.Type.REQUEST.ordinal(), - null, 0, null, ConnectivityManager.TYPE_WIFI, mContext.getPackageName(), - getAttributionTag()); + null, 0, null, ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE, + mContext.getPackageName(), getAttributionTag()); }); class NonParcelableSpecifier extends NetworkSpecifier { @@ -4011,7 +4029,8 @@ public class ConnectivityServiceTest { grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); final TestNetworkCallback cellBgCallback = new TestNetworkCallback(); mCm.requestBackgroundNetwork(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(), null, cellBgCallback); + .addTransportType(TRANSPORT_CELLULAR).build(), + mCsHandlerThread.getThreadHandler(), cellBgCallback); // Make callbacks for monitoring. final NetworkRequest request = new NetworkRequest.Builder().build(); @@ -7185,12 +7204,14 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); setUidRulesChanged(RULE_REJECT_ALL); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mCellNetworkAgent); // ConnectivityService should cache it not to invoke the callback again. setUidRulesChanged(RULE_REJECT_METERED); @@ -7201,12 +7222,14 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); setUidRulesChanged(RULE_REJECT_METERED); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mCellNetworkAgent); // Restrict the network based on UID rule and NOT_METERED capability change. mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); @@ -7215,6 +7238,7 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, @@ -7223,12 +7247,14 @@ public class ConnectivityServiceTest { assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mCellNetworkAgent); setUidRulesChanged(RULE_ALLOW_METERED); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); setUidRulesChanged(RULE_NONE); cellNetworkCallback.assertNoCallback(); @@ -7239,6 +7265,7 @@ public class ConnectivityServiceTest { assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mCellNetworkAgent); setRestrictBackgroundChanged(true); cellNetworkCallback.assertNoCallback(); @@ -7246,12 +7273,14 @@ public class ConnectivityServiceTest { cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); setRestrictBackgroundChanged(false); cellNetworkCallback.assertNoCallback(); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); mCm.unregisterNetworkCallback(cellNetworkCallback); } @@ -7310,6 +7339,15 @@ public class ConnectivityServiceTest { assertNotNull(ni); assertEquals(type, ni.getType()); assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState()); + if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) { + assertNotNull(ni.getExtraInfo()); + } else { + // Technically speaking, a network that's in CONNECTING state will generally have a + // non-null extraInfo. This doesn't actually happen in this test because it never calls + // a legacy API while a network is connecting. When a network is in CONNECTING state + // because of legacy lockdown VPN, its extraInfo is always null. + assertNull(ni.getExtraInfo()); + } } private void assertActiveNetworkInfo(int type, DetailedState state) { @@ -7319,6 +7357,26 @@ public class ConnectivityServiceTest { checkNetworkInfo(mCm.getNetworkInfo(type), type, state); } + private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) { + final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork()); + final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType()); + if (present) { + assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo()); + assertEquals(network.getExtraInfo(), niForType.getExtraInfo()); + } else { + assertNull(niForNetwork.getExtraInfo()); + assertNull(niForType.getExtraInfo()); + } + } + + private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) { + assertExtraInfoFromCm(network, false); + } + + private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) { + assertExtraInfoFromCm(network, true); + } + // Checks that each of the |agents| receive a blocked status change callback with the specified // |blocked| value, in any order. This is needed because when an event affects multiple // networks, ConnectivityService does not guarantee the order in which callbacks are fired. @@ -7633,6 +7691,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mCellNetworkAgent); // TODO: it would be nice if we could simply rely on the production code here, and have // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with @@ -7661,6 +7720,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mCellNetworkAgent); assertTrue(vpnNc.hasTransport(TRANSPORT_VPN)); assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR)); assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI)); @@ -7703,6 +7763,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED); + assertExtraInfoFromCmBlocked(mWiFiNetworkAgent); // The VPN comes up again on wifi. b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED); @@ -7717,6 +7778,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mWiFiNetworkAgent); vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); assertTrue(vpnNc.hasTransport(TRANSPORT_VPN)); assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI)); @@ -7733,6 +7795,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); + assertExtraInfoFromCmPresent(mWiFiNetworkAgent); b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); mWiFiNetworkAgent.disconnect(); @@ -7812,7 +7875,6 @@ public class ConnectivityServiceTest { verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, cellLp.getInterfaceName(), new int[] { TRANSPORT_CELLULAR }); - reset(mBatteryStatsService); final LinkProperties wifiLp = new LinkProperties(); wifiLp.setInterfaceName("wifi0"); @@ -7822,7 +7884,6 @@ public class ConnectivityServiceTest { verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, wifiLp.getInterfaceName(), new int[] { TRANSPORT_WIFI }); - reset(mBatteryStatsService); mCellNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect(); @@ -7905,7 +7966,6 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); reset(mMockDnsResolver); reset(mMockNetd); - reset(mBatteryStatsService); // Connect with ipv6 link properties. Expect prefix discovery to be started. mCellNetworkAgent.connect(true); @@ -8268,6 +8328,45 @@ public class ConnectivityServiceTest { } @Test + public void testWith464XlatDisable() throws Exception { + doReturn(false).when(mDeps).getCellular464XlatEnabled(); + + final TestNetworkCallback callback = new TestNetworkCallback(); + final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + final NetworkRequest networkRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_INTERNET) + .build(); + mCm.registerNetworkCallback(networkRequest, callback); + mCm.registerDefaultNetworkCallback(defaultCallback); + + // Bring up validated cell. + final LinkProperties cellLp = new LinkProperties(); + cellLp.setInterfaceName(MOBILE_IFNAME); + cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); + cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME)); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + + mCellNetworkAgent.sendLinkProperties(cellLp); + mCellNetworkAgent.connect(true); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + final int cellNetId = mCellNetworkAgent.getNetwork().netId; + waitForIdle(); + + verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId); + Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); + assertTrue("Nat464Xlat was not IDLE", !clat.isStarted()); + + // This cannot happen because prefix discovery cannot succeed if it is never started. + mService.mResolverUnsolEventCallback.onNat64PrefixEvent( + makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96)); + + // ... but still, check that even if it did, clatd would not be started. + verify(mMockNetd, never()).clatdStart(anyString(), anyString()); + assertTrue("Nat464Xlat was not IDLE", !clat.isStarted()); + } + + @Test public void testDataActivityTracking() throws Exception { final TestNetworkCallback networkCallback = new TestNetworkCallback(); final NetworkRequest networkRequest = new NetworkRequest.Builder() @@ -8659,6 +8758,7 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = targetSdk; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mPackageManager.getTargetSdkVersion(any())).thenReturn(targetSdk); when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); @@ -8673,102 +8773,183 @@ public class ConnectivityServiceTest { } } - private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) { + private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid, + boolean includeLocationSensitiveInfo) { final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, callerUid, mContext.getPackageName(), getAttributionTag()).getOwnerUid(); + netCap, includeLocationSensitiveInfo, callerUid, + mContext.getPackageName(), getAttributionTag()) + .getOwnerUid(); } - private void verifyWifiInfoCopyNetCapsForCallerPermission( - int callerUid, boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { + private void verifyWifiInfoCopyNetCapsPermission( + int callerUid, boolean includeLocationSensitiveInfo, + boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { final WifiInfo wifiInfo = mock(WifiInfo.class); when(wifiInfo.hasLocationSensitiveFields()).thenReturn(true); final NetworkCapabilities netCap = new NetworkCapabilities().setTransportInfo(wifiInfo); mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, callerUid, mContext.getPackageName(), getAttributionTag()); + netCap, includeLocationSensitiveInfo, callerUid, + mContext.getPackageName(), getAttributionTag()); verify(wifiInfo).makeCopy(eq(shouldMakeCopyWithLocationSensitiveFieldsParcelable)); } + private void verifyOwnerUidAndWifiInfoNetCapsPermission( + boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag, + boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag, + boolean shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag, + boolean shouldInclLocationSensitiveWifiInfoWithIncludeFlag) { + final int myUid = Process.myUid(); + + final int expectedOwnerUidWithoutIncludeFlag = + shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag + ? Process.myUid() : INVALID_UID; + assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission( + myUid, myUid, false /* includeLocationSensitiveInfo */)); + + final int expectedOwnerUidWithIncludeFlag = + shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID; + assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission( + myUid, myUid, true /* includeLocationSensitiveInfo */)); + + verifyWifiInfoCopyNetCapsPermission(myUid, + false, /* includeLocationSensitiveInfo */ + shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag); + + verifyWifiInfoCopyNetCapsPermission(myUid, + true, /* includeLocationSensitiveInfo */ + shouldInclLocationSensitiveWifiInfoWithIncludeFlag); + + } + @Test - public void testCreateForCallerWithLocationInfoSanitizedWithFineLocationAfterQ() + public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQ() throws Exception { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we include owner uid even if the request asks to remove it since the + // app has necessary permissions and targetSdk < S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); + } - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + @Test + public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag() + throws Exception { + setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we include owner uid even if the request asks to remove it since the + // app has necessary permissions and targetSdk < S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationPreQ() + public void + testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag() + throws Exception { + setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we owner UID if the request asks us to remove it even if the app + // has necessary permissions since targetSdk >= S. + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); + } + + @Test + public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ() throws Exception { setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we owner UID if the request asks us to remove it even if the app + // has necessary permissions since targetSdk >= S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedLocationOff() throws Exception { + public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception { // Test that even with fine location permission, and UIDs matching, the UID is sanitized. setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWrongUid() throws Exception { + public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception { // Test that even with fine location permission, not being the owner leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + assertEquals(Process.INVALID_UID, + getOwnerUidNetCapsPermission(myUid + 1, myUid, + true /* includeLocationSensitiveInfo */)); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationAfterQ() + public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ() throws Exception { // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - // Test that without the location permission, the owner field is sanitized. - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithoutLocationPermission() + public void testCreateWithLocationInfoSanitizedWithoutLocationPermission() throws Exception { + // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); - // Test that without the location permission, the owner field is sanitized. - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) @@ -8973,7 +9154,7 @@ public class ConnectivityServiceTest { TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE)); return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(), nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0, - INVALID_UID, mQosCallbackTracker); + INVALID_UID, mQosCallbackTracker, new ConnectivityService.Dependencies()); } @Test @@ -9359,8 +9540,8 @@ public class ConnectivityServiceTest { assertThrows("Expect throws for invalid request type " + reqTypeInt, IllegalArgumentException.class, () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null, - ConnectivityManager.TYPE_NONE, mContext.getPackageName(), - getAttributionTag()) + ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE, + mContext.getPackageName(), getAttributionTag()) ); } } @@ -10930,4 +11111,12 @@ public class ConnectivityServiceTest { verifyNoNetwork(); mCm.unregisterNetworkCallback(cellCb); } + + @Test + public void testRegisterBestMatchingNetworkCallback() throws Exception { + final NetworkRequest request = new NetworkRequest.Builder().build(); + assertThrows(UnsupportedOperationException.class, + () -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(), + mCsHandlerThread.getThreadHandler())); + } } diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index f97eabf6366d..6232423b4f9e 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.net.ConnectivityManager; import android.net.INetd; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; @@ -47,6 +48,7 @@ import android.os.Process; import android.system.ErrnoException; import android.system.Os; import android.system.StructStat; +import android.util.Range; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -647,9 +649,9 @@ public class IpSecServiceTest { @Test public void testReserveNetId() { - int start = mIpSecService.TUN_INTF_NETID_START; - for (int i = 0; i < mIpSecService.TUN_INTF_NETID_RANGE; i++) { - assertEquals(start + i, mIpSecService.reserveNetId()); + final Range<Integer> netIdRange = ConnectivityManager.getIpSecNetIdRange(); + for (int netId = netIdRange.getLower(); netId <= netIdRange.getUpper(); netId++) { + assertEquals(netId, mIpSecService.reserveNetId()); } // Check that resource exhaustion triggers an exception @@ -661,7 +663,7 @@ public class IpSecServiceTest { // Now release one and try again int releasedNetId = - mIpSecService.TUN_INTF_NETID_START + mIpSecService.TUN_INTF_NETID_RANGE / 2; + netIdRange.getLower() + (netIdRange.getUpper() - netIdRange.getLower()) / 2; mIpSecService.releaseNetId(releasedNetId); assertEquals(releasedNetId, mIpSecService.reserveNetId()); } diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index a913673c2a1e..1c0ba4f8d8f5 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -357,7 +357,7 @@ public class LingerMonitorTest { NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, new LinkProperties(), caps, 50, mCtx, null, new NetworkAgentConfig() /* config */, mConnService, mNetd, mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), - mQosCallbackTracker); + mQosCallbackTracker, new ConnectivityService.Dependencies()); nai.everValidated = true; return nai; } diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java index 950d7163c78a..38f6d7f3172d 100644 --- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java +++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java @@ -46,12 +46,12 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.EthernetNetworkSpecifier; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkPolicy; import android.net.NetworkPolicyManager; import android.net.NetworkTemplate; -import android.net.StringNetworkSpecifier; import android.net.TelephonyNetworkSpecifier; import android.os.Handler; import android.os.UserHandle; @@ -240,7 +240,7 @@ public class MultipathPolicyTrackerTest { NetworkCapabilities capabilities = new NetworkCapabilities() .addCapability(NET_CAPABILITY_INTERNET) .addTransportType(TRANSPORT_CELLULAR) - .setNetworkSpecifier(new StringNetworkSpecifier("234")); + .setNetworkSpecifier(new EthernetNetworkSpecifier("eth234")); if (!roaming) { capabilities.addCapability(NET_CAPABILITY_NOT_ROAMING); } diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index 5f56e25356c2..9b2a638f8b39 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -16,11 +16,15 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -34,6 +38,7 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkAgentConfig; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.Handler; import android.os.test.TestLooper; @@ -72,11 +77,15 @@ public class Nat464XlatTest { Handler mHandler; NetworkAgentConfig mAgentConfig = new NetworkAgentConfig(); - Nat464Xlat makeNat464Xlat() { - return new Nat464Xlat(mNai, mNetd, mDnsResolver) { + Nat464Xlat makeNat464Xlat(boolean isCellular464XlatEnabled) { + return new Nat464Xlat(mNai, mNetd, mDnsResolver, new ConnectivityService.Dependencies()) { @Override protected int getNetId() { return NETID; } + + @Override protected boolean isCellular464XlatEnabled() { + return isCellular464XlatEnabled; + } }; } @@ -99,6 +108,7 @@ public class Nat464XlatTest { mNai.linkProperties.setInterfaceName(BASE_IFACE); mNai.networkInfo = new NetworkInfo(null); mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI); + mNai.networkCapabilities = new NetworkCapabilities(); markNetworkConnected(); when(mNai.connService()).thenReturn(mConnectivity); when(mNai.netAgentConfig()).thenReturn(mAgentConfig); @@ -110,21 +120,23 @@ public class Nat464XlatTest { } private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) { + Nat464Xlat nat = makeNat464Xlat(true); String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b " + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), nai.networkInfo.getDetailedState(), mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), nai.linkProperties.getLinkAddresses()); - assertEquals(msg, expected, Nat464Xlat.requiresClat(nai)); + assertEquals(msg, expected, nat.requiresClat(nai)); } private void assertShouldStartClat(boolean expected, NetworkAgentInfo nai) { + Nat464Xlat nat = makeNat464Xlat(true); String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b " + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), nai.networkInfo.getDetailedState(), mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), nai.linkProperties.getLinkAddresses()); - assertEquals(msg, expected, Nat464Xlat.shouldStartClat(nai)); + assertEquals(msg, expected, nat.shouldStartClat(nai)); } @Test @@ -194,7 +206,7 @@ public class Nat464XlatTest { } private void checkNormalStartAndStop(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); mNai.linkProperties.addLinkAddress(V6ADDR); @@ -245,7 +257,7 @@ public class Nat464XlatTest { } private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception { - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); InOrder inOrder = inOrder(mNetd, mConnectivity); @@ -335,7 +347,7 @@ public class Nat464XlatTest { @Test public void testClatdCrashWhileRunning() throws Exception { - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); @@ -372,7 +384,7 @@ public class Nat464XlatTest { } private void checkStopBeforeClatdStarts(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); @@ -414,7 +426,7 @@ public class Nat464XlatTest { } private void checkStopAndClatdNeverStarts(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); @@ -450,7 +462,7 @@ public class Nat464XlatTest { final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX); final IpPrefix prefixFromRa = new IpPrefix(OTHER_NAT64_PREFIX); - Nat464Xlat nat = makeNat464Xlat(); + Nat464Xlat nat = makeNat464Xlat(true); final LinkProperties emptyLp = new LinkProperties(); LinkProperties fixedupLp; @@ -486,10 +498,57 @@ public class Nat464XlatTest { assertEquals(null, fixedupLp.getNat64Prefix()); } + private void checkClatDisabledOnCellular(boolean onCellular) throws Exception { + // Disable 464xlat on cellular networks. + Nat464Xlat nat = makeNat464Xlat(false); + mNai.linkProperties.addLinkAddress(V6ADDR); + mNai.networkCapabilities.setTransportType(TRANSPORT_CELLULAR, onCellular); + nat.update(); + + final IpPrefix nat64Prefix = new IpPrefix(NAT64_PREFIX); + if (onCellular) { + // Prefix discovery is never started. + verify(mDnsResolver, never()).startPrefix64Discovery(eq(NETID)); + assertIdle(nat); + + // If a NAT64 prefix comes in from an RA, clat is not started either. + mNai.linkProperties.setNat64Prefix(nat64Prefix); + nat.setNat64PrefixFromRa(nat64Prefix); + nat.update(); + verify(mNetd, never()).clatdStart(anyString(), anyString()); + assertIdle(nat); + } else { + // Prefix discovery is started. + verify(mDnsResolver).startPrefix64Discovery(eq(NETID)); + assertIdle(nat); + + // If a NAT64 prefix comes in from an RA, clat is started. + mNai.linkProperties.setNat64Prefix(nat64Prefix); + nat.setNat64PrefixFromRa(nat64Prefix); + nat.update(); + verify(mNetd).clatdStart(BASE_IFACE, NAT64_PREFIX); + assertStarting(nat); + } + } + + @Test + public void testClatDisabledOnCellular() throws Exception { + checkClatDisabledOnCellular(true); + } + + @Test + public void testClatDisabledOnNonCellular() throws Exception { + checkClatDisabledOnCellular(false); + } + static void assertIdle(Nat464Xlat nat) { assertTrue("Nat464Xlat was not IDLE", !nat.isStarted()); } + static void assertStarting(Nat464Xlat nat) { + assertTrue("Nat464Xlat was not STARTING", nat.isStarting()); + } + static void assertRunning(Nat464Xlat nat) { assertTrue("Nat464Xlat was not RUNNING", nat.isRunning()); } diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index e4e24b464838..fec5ef39374a 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -48,18 +48,22 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.net.INetd; import android.net.UidRange; +import android.net.Uri; import android.os.Build; import android.os.SystemConfigManager; import android.os.UserHandle; @@ -70,12 +74,11 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.server.LocalServices; -import com.android.server.pm.PackageList; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.AdditionalAnswers; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -112,7 +115,6 @@ public class PermissionMonitorTest { @Mock private Context mContext; @Mock private PackageManager mPackageManager; @Mock private INetd mNetdService; - @Mock private PackageManagerInternal mMockPmi; @Mock private UserManager mUserManager; @Mock private PermissionMonitor.Dependencies mDeps; @Mock private SystemConfigManager mSystemConfigManager; @@ -131,16 +133,14 @@ public class PermissionMonitorTest { when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE)) .thenReturn(mSystemConfigManager); when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); + final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); + doReturn(UserHandle.ALL).when(asUserCtx).getUser(); + when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); - LocalServices.removeServiceForTest(PackageManagerInternal.class); - LocalServices.addService(PackageManagerInternal.class, mMockPmi); - when(mMockPmi.getPackageList(any())).thenReturn(new PackageList(new ArrayList<String>(), - /* observer */ null)); when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(/* empty app list */ null); mPermissionMonitor.startMonitoring(); - verify(mMockPmi).getPackageList(mPermissionMonitor); } private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, @@ -770,4 +770,32 @@ public class PermissionMonitorTest { INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{ MOCK_UID2 }); } + + @Test + public void testIntentReceiver() throws Exception { + final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); + final ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(), any(), any(), any()); + final BroadcastReceiver receiver = receiverCaptor.getValue(); + + // Verify receiving PACKAGE_ADDED intent. + final Intent addedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED, + Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */)); + addedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1); + setPackagePermissions(MOCK_PACKAGE1, MOCK_UID1, + new String[] { INTERNET, UPDATE_DEVICE_STATS }); + receiver.onReceive(mContext, addedIntent); + mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET + | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[] { MOCK_UID1 }); + + // Verify receiving PACKAGE_REMOVED intent. + when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(null); + final Intent removedIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED, + Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */)); + removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1); + receiver.onReceive(mContext, removedIntent); + mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 }); + } + } diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 11498dec8165..a02002752c38 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -593,6 +593,16 @@ public class VcnManagementServiceTest { mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); } + @Test(expected = SecurityException.class) + public void testRemoveVcnUnderlyingNetworkPolicyListenerInvalidPermission() { + doThrow(new SecurityException()) + .when(mMockContext) + .enforceCallingOrSelfPermission( + eq(android.Manifest.permission.NETWORK_FACTORY), any()); + + mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); + } + @Test public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() { mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java index 1d459a347526..1ef1a61f17ea 100644 --- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java @@ -194,29 +194,35 @@ public class UnderlyingNetworkTrackerTest { } private NetworkRequest getWifiRequest() { - return getExpectedRequestBase() + return getExpectedRequestBase(true) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); } private NetworkRequest getCellRequestForSubId(int subId) { - return getExpectedRequestBase() + return getExpectedRequestBase(false) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } private NetworkRequest getRouteSelectionRequest() { - return getExpectedRequestBase().build(); + return getExpectedRequestBase(true).build(); } - private NetworkRequest.Builder getExpectedRequestBase() { - return new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + private NetworkRequest.Builder getExpectedRequestBase(boolean requireVcnManaged) { + final NetworkRequest.Builder builder = + new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + + if (requireVcnManaged) { + builder.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return builder; } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 4bf849111a5d..0e5f5e43f282 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -73,7 +73,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1); - mIkeSession = mGatewayConnection.buildIkeSession(); + mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network); mGatewayConnection.setIkeSession(mIkeSession); mGatewayConnection.transitionTo(mGatewayConnection.mConnectedState); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index d07d2cf4f1bb..7afa4494ee8b 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -25,12 +25,15 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.net.ipsec.ike.IkeSessionParams; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; /** Tests for VcnGatewayConnection.ConnectingState */ @RunWith(AndroidJUnit4.class) @@ -51,7 +54,12 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testEnterStateCreatesNewIkeSession() throws Exception { - verify(mDeps).newIkeSession(any(), any(), any(), any(), any()); + final ArgumentCaptor<IkeSessionParams> paramsCaptor = + ArgumentCaptor.forClass(IkeSessionParams.class); + verify(mDeps).newIkeSession(any(), paramsCaptor.capture(), any(), any(), any()); + assertEquals( + TEST_UNDERLYING_NETWORK_RECORD_1.network, + paramsCaptor.getValue().getConfiguredNetwork()); } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index 661e03af4f84..99feffdebc8e 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -38,7 +38,8 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec public void setUp() throws Exception { super.setUp(); - mGatewayConnection.setIkeSession(mGatewayConnection.buildIkeSession()); + mGatewayConnection.setIkeSession( + mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_2.network)); // ensure that mGatewayConnection has an underlying Network before entering // DisconnectingState diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index 748c7924685d..d08af9dd3370 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -18,6 +18,7 @@ package com.android.server.vcn; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; @@ -87,6 +88,7 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { private void verifyBuildNetworkCapabilitiesCommon(int transportType) { final NetworkCapabilities underlyingCaps = new NetworkCapabilities(); underlyingCaps.addTransportType(transportType); + underlyingCaps.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_METERED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_ROAMING); |