diff options
54 files changed, 1579 insertions, 1017 deletions
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 6fb9630fe847..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(); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 62a5f4644a09..a9e3fb54c7eb 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(); } } @@ -10565,7 +10565,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(); 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/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/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/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/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/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 78853c777254..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; @@ -190,7 +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.util.AsyncChannel; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; @@ -344,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 @@ -1100,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); @@ -1356,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, @@ -1717,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)); } } @@ -1731,7 +1733,9 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, mDeps.getCallingUid(), callingPackageName, + nc, + false /* includeLocationSensitiveInfo */, + mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1813,6 +1817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), + false /* includeLocationSensitiveInfo */, mDeps.getCallingUid(), callingPackageName, callingAttributionTag); } @@ -1846,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; } @@ -1855,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); @@ -1872,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 = @@ -2890,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; @@ -3197,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); } @@ -3462,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)) { @@ -3507,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. @@ -5155,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; @@ -5250,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 @@ -5297,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); @@ -5318,6 +5305,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = mDeps.getCallingUid(); mPendingIntent = null; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = callbackFlags; mCallingAttributionTag = callingAttributionTag; try { @@ -5359,6 +5347,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = nri.mUid; mPendingIntent = nri.mPendingIntent; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = nri.mCallbackFlags; mCallingAttributionTag = nri.mCallingAttributionTag; } @@ -5408,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; } } @@ -5492,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; @@ -5507,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"); } } @@ -5547,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); } @@ -5570,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 @@ -5605,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) { @@ -5613,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, @@ -5739,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(); @@ -5761,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)); @@ -5830,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; } @@ -7090,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 = @@ -7098,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)); @@ -7118,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; } 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/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/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/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 240464a560af..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) { @@ -276,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, @@ -299,7 +307,7 @@ class RebootEscrowManager { } if (escrowKey == null) { - onGetRebootEscrowKeyFailed(users); + onGetRebootEscrowKeyFailed(users, attemptNumber + 1); return; } @@ -313,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); } } @@ -478,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/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/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 b022154ea917..d82205e20538 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -2553,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); } @@ -2572,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); } @@ -2814,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; } @@ -2922,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) { } @@ -2987,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/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/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/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 15a7b913ab45..2c8c8a6409ea 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1454,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. @@ -3749,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 { @@ -4027,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(); @@ -8755,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); @@ -8769,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 */ + ); + } + + @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 + testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag() + throws Exception { + setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); - 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. + 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 testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationPreQ() + 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) @@ -9455,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()) ); } } @@ -11026,4 +11111,12 @@ public class ConnectivityServiceTest { verifyNoNetwork(); mCm.unregisterNetworkCallback(cellCb); } -}
\ No newline at end of file + + @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/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/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 }); + } + } |