diff options
135 files changed, 3265 insertions, 1537 deletions
diff --git a/Android.bp b/Android.bp index facc741578e0..56962b24da3d 100644 --- a/Android.bp +++ b/Android.bp @@ -455,6 +455,8 @@ java_library { "telecomm/java/com/android/internal/telecom/IInCallService.aidl", "telecomm/java/com/android/internal/telecom/ITelecomService.aidl", "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl", + "telephony/java/android/telephony/data/IDataService.aidl", + "telephony/java/android/telephony/data/IDataServiceCallback.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl", @@ -462,8 +464,6 @@ java_library { "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsRegistration.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsRegistrationCallback.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl", "telephony/java/android/telephony/ims/internal/aidl/IImsSmsListener.aidl", @@ -483,6 +483,8 @@ java_library { "telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl", "telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl", "telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl", + "telephony/java/com/android/ims/internal/IImsRegistration.aidl", + "telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl", "telephony/java/com/android/ims/internal/IImsRcsFeature.aidl", "telephony/java/com/android/ims/internal/IImsService.aidl", "telephony/java/com/android/ims/internal/IImsServiceController.aidl", @@ -510,9 +512,21 @@ java_library { "telephony/java/com/android/internal/telephony/ITelephony.aidl", "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl", "telephony/java/com/android/internal/telephony/IWapPushManager.aidl", + "telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl", "telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl", "telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl", "telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl", + "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl", "wifi/java/android/net/wifi/IWifiManager.aidl", "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl", "wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl", diff --git a/Android.mk b/Android.mk index 2d74249d9bb9..cf6aa2a0c298 100644 --- a/Android.mk +++ b/Android.mk @@ -82,7 +82,7 @@ framework_base_android_test_runner_excluding_mock_src_files := \ # to document and check apis files_to_check_apis := \ $(call find-other-java-files, \ - legacy-test/src \ + test-base/src \ $(non_base_dirs) \ ) diff --git a/api/current.txt b/api/current.txt index c1cf404afd3d..40452b763663 100644 --- a/api/current.txt +++ b/api/current.txt @@ -19873,6 +19873,13 @@ package android.icu.util { ctor public ICUUncheckedIOException(java.lang.String, java.lang.Throwable); } + public class IllformedLocaleException extends java.lang.RuntimeException { + ctor public IllformedLocaleException(); + ctor public IllformedLocaleException(java.lang.String); + ctor public IllformedLocaleException(java.lang.String, int); + method public int getErrorIndex(); + } + public class IndianCalendar extends android.icu.util.Calendar { ctor public IndianCalendar(); ctor public IndianCalendar(android.icu.util.TimeZone); @@ -19957,6 +19964,32 @@ package android.icu.util { field public static final int TAISHO; } + public final class LocaleData { + method public static android.icu.util.VersionInfo getCLDRVersion(); + method public java.lang.String getDelimiter(int); + method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale); + method public static final android.icu.util.LocaleData getInstance(); + method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale); + method public boolean getNoSubstitute(); + method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale); + method public void setNoSubstitute(boolean); + field public static final int ALT_QUOTATION_END = 3; // 0x3 + field public static final int ALT_QUOTATION_START = 2; // 0x2 + field public static final int QUOTATION_END = 1; // 0x1 + field public static final int QUOTATION_START = 0; // 0x0 + } + + public static final class LocaleData.MeasurementSystem { + field public static final android.icu.util.LocaleData.MeasurementSystem SI; + field public static final android.icu.util.LocaleData.MeasurementSystem UK; + field public static final android.icu.util.LocaleData.MeasurementSystem US; + } + + public static final class LocaleData.PaperSize { + method public int getHeight(); + method public int getWidth(); + } + public class Measure { ctor public Measure(java.lang.Number, android.icu.util.MeasureUnit); method public java.lang.Number getNumber(); @@ -25781,12 +25814,18 @@ package android.net { } public final class IpSecManager { - method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException; - method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; - method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + method public void applyTransportModeTransform(java.net.Socket, int, android.net.IpSecTransform) throws java.io.IOException; + method public void applyTransportModeTransform(java.net.DatagramSocket, int, android.net.IpSecTransform) throws java.io.IOException; + method public void applyTransportModeTransform(java.io.FileDescriptor, int, android.net.IpSecTransform) throws java.io.IOException; method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; - method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public void removeTransportModeTransforms(java.net.Socket) throws java.io.IOException; + method public void removeTransportModeTransforms(java.net.DatagramSocket) throws java.io.IOException; + method public void removeTransportModeTransforms(java.io.FileDescriptor) throws java.io.IOException; + field public static final int DIRECTION_IN = 0; // 0x0 + field public static final int DIRECTION_OUT = 1; // 0x1 } public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException { @@ -25809,18 +25848,15 @@ package android.net { public final class IpSecTransform implements java.lang.AutoCloseable { method public void close(); - field public static final int DIRECTION_IN = 0; // 0x0 - field public static final int DIRECTION_OUT = 1; // 0x1 } public static class IpSecTransform.Builder { ctor public IpSecTransform.Builder(android.content.Context); - method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; - method public android.net.IpSecTransform.Builder setAuthenticatedEncryption(int, android.net.IpSecAlgorithm); - method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm); - method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + method public android.net.IpSecTransform.Builder setAuthenticatedEncryption(android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setAuthentication(android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setEncryption(android.net.IpSecAlgorithm); method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int); - method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex); } public class LinkAddress implements android.os.Parcelable { @@ -25905,10 +25941,10 @@ package android.net { } public final class MacAddress implements android.os.Parcelable { - method public int addressType(); method public int describeContents(); method public static android.net.MacAddress fromBytes(byte[]); method public static android.net.MacAddress fromString(java.lang.String); + method public int getAddressType(); method public boolean isLocallyAssigned(); method public byte[] toByteArray(); method public java.lang.String toOuiString(); @@ -25918,7 +25954,6 @@ package android.net { field public static final int TYPE_BROADCAST = 3; // 0x3 field public static final int TYPE_MULTICAST = 2; // 0x2 field public static final int TYPE_UNICAST = 1; // 0x1 - field public static final int TYPE_UNKNOWN = 0; // 0x0 } public class MailTo { @@ -40457,6 +40492,7 @@ package android.telephony { method public void onServiceStateChanged(android.telephony.ServiceState); method public deprecated void onSignalStrengthChanged(int); method public void onSignalStrengthsChanged(android.telephony.SignalStrength); + method public void onUserMobileDataStateChanged(boolean); field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8 field public static final int LISTEN_CALL_STATE = 32; // 0x20 field public static final int LISTEN_CELL_INFO = 1024; // 0x400 @@ -40468,6 +40504,7 @@ package android.telephony { field public static final int LISTEN_SERVICE_STATE = 1; // 0x1 field public static final deprecated int LISTEN_SIGNAL_STRENGTH = 2; // 0x2 field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100 + field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000 } public final class RadioAccessSpecifier implements android.os.Parcelable { @@ -40737,6 +40774,8 @@ package android.telephony { method public int getSimState(); method public int getSimState(int); method public java.lang.String getSubscriberId(); + method public int getSubscriptionCarrierId(); + method public java.lang.String getSubscriptionCarrierName(); method public java.lang.String getVisualVoicemailPackageName(); method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); @@ -40781,6 +40820,7 @@ package android.telephony { field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION"; + field public static final java.lang.String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED"; field public static final int APPTYPE_CSIM = 4; // 0x4 field public static final int APPTYPE_ISIM = 5; // 0x5 field public static final int APPTYPE_RUIM = 3; // 0x3 @@ -40801,6 +40841,8 @@ package android.telephony { field public static final int DATA_DISCONNECTED = 0; // 0x0 field public static final int DATA_SUSPENDED = 3; // 0x3 field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT"; + field public static final java.lang.String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID"; + field public static final java.lang.String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME"; field public static final java.lang.String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS"; field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number"; field public static final java.lang.String EXTRA_IS_REFRESH = "android.telephony.extra.IS_REFRESH"; @@ -40811,6 +40853,7 @@ package android.telephony { field public static final java.lang.String EXTRA_STATE_IDLE; field public static final java.lang.String EXTRA_STATE_OFFHOOK; field public static final java.lang.String EXTRA_STATE_RINGING; + field public static final java.lang.String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID"; field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER"; field public static final java.lang.String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU"; field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7 @@ -40846,6 +40889,7 @@ package android.telephony { field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3 field public static final int SIM_STATE_READY = 5; // 0x5 field public static final int SIM_STATE_UNKNOWN = 0; // 0x0 + field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm"; diff --git a/api/system-current.txt b/api/system-current.txt index 4eb5c0875e6d..282dfaa6a25f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4076,11 +4076,11 @@ package android.telephony { package android.telephony.data { public final class DataCallResponse implements android.os.Parcelable { - ctor public DataCallResponse(int, int, int, int, java.lang.String, java.lang.String, java.util.List<android.telephony.data.InterfaceAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.lang.String>, int); + ctor public DataCallResponse(int, int, int, int, java.lang.String, java.lang.String, java.util.List<android.net.LinkAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.lang.String>, int); ctor public DataCallResponse(android.os.Parcel); method public int describeContents(); method public int getActive(); - method public java.util.List<android.telephony.data.InterfaceAddress> getAddresses(); + method public java.util.List<android.net.LinkAddress> getAddresses(); method public int getCallId(); method public java.util.List<java.net.InetAddress> getDnses(); method public java.util.List<java.net.InetAddress> getGateways(); @@ -4123,15 +4123,36 @@ package android.telephony.data { field public static final int TYPE_COMMON = 0; // 0x0 } - public final class InterfaceAddress implements android.os.Parcelable { - ctor public InterfaceAddress(java.net.InetAddress, int); - ctor public InterfaceAddress(java.lang.String, int) throws java.net.UnknownHostException; - ctor public InterfaceAddress(android.os.Parcel); - method public int describeContents(); - method public java.net.InetAddress getAddress(); - method public int getNetworkPrefixLength(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.telephony.data.InterfaceAddress> CREATOR; + public abstract class DataService extends android.app.Service { + method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int); + field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID"; + field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService"; + } + + public class DataService.DataServiceProvider { + ctor public DataService.DataServiceProvider(int); + method public void deactivateDataCall(int, boolean, boolean, android.telephony.data.DataServiceCallback); + method public void getDataCallList(android.telephony.data.DataServiceCallback); + method public final int getSlotId(); + method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>); + method protected void onDestroy(); + method public void setDataProfile(java.util.List<android.telephony.data.DataProfile>, boolean, android.telephony.data.DataServiceCallback); + method public void setInitialAttachApn(android.telephony.data.DataProfile, boolean, android.telephony.data.DataServiceCallback); + method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, boolean, android.net.LinkProperties, android.telephony.data.DataServiceCallback); + } + + public class DataServiceCallback { + method public void onDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>); + method public void onDeactivateDataCallComplete(int); + method public void onGetDataCallListComplete(int, java.util.List<android.telephony.data.DataCallResponse>); + method public void onSetDataProfileComplete(int); + method public void onSetInitialAttachApnComplete(int); + method public void onSetupDataCallComplete(int, android.telephony.data.DataCallResponse); + field public static final int RESULT_ERROR_BUSY = 3; // 0x3 + field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 + field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2 + field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 } } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 45f7eba2af02..2ecd3120345d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -366,7 +366,7 @@ public final class ActivityThread { ActivityInfo activityInfo; CompatibilityInfo compatInfo; - LoadedApk packageInfo; + LoadedApk loadedApk; List<ResultInfo> pendingResults; List<ReferrerIntent> pendingIntents; @@ -542,7 +542,7 @@ public final class ActivityThread { } static final class AppBindData { - LoadedApk info; + LoadedApk loadedApk; String processName; ApplicationInfo appInfo; List<ProviderInfo> providers; @@ -1584,7 +1584,7 @@ public final class ActivityThread { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; - r.packageInfo = getPackageInfoNoCheck( + r.loadedApk = getLoadedApkNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); @@ -1832,9 +1832,11 @@ public final class ActivityThread { handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1, (IVoiceInteractor) ((SomeArgs) msg.obj).arg2); break; - case ATTACH_AGENT: - handleAttachAgent((String) msg.obj); + case ATTACH_AGENT: { + Application app = getApplication(); + handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null); break; + } case APPLICATION_INFO_CHANGED: mUpdatingSystemConfig = true; try { @@ -1971,13 +1973,13 @@ public final class ActivityThread { return mH; } - public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, - int flags) { - return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId()); + public final LoadedApk getLoadedApkForPackageName(String packageName, + CompatibilityInfo compatInfo, int flags) { + return getLoadedApkForPackageName(packageName, compatInfo, flags, UserHandle.myUserId()); } - public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, - int flags, int userId) { + public final LoadedApk getLoadedApkForPackageName(String packageName, + CompatibilityInfo compatInfo, int flags, int userId) { final boolean differentUser = (UserHandle.myUserId() != userId); synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; @@ -1990,13 +1992,13 @@ public final class ActivityThread { ref = mResourcePackages.get(packageName); } - LoadedApk packageInfo = ref != null ? ref.get() : null; - //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); - //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir - // + ": " + packageInfo.mResources.getAssets().isUpToDate()); - if (packageInfo != null && (packageInfo.mResources == null - || packageInfo.mResources.getAssets().isUpToDate())) { - if (packageInfo.isSecurityViolation() + LoadedApk loadedApk = ref != null ? ref.get() : null; + //Slog.i(TAG, "getLoadedApkForPackageName " + packageName + ": " + loadedApk); + //if (loadedApk != null) Slog.i(TAG, "isUptoDate " + loadedApk.mResDir + // + ": " + loadedApk.mResources.getAssets().isUpToDate()); + if (loadedApk != null && (loadedApk.mResources == null + || loadedApk.mResources.getAssets().isUpToDate())) { + if (loadedApk.isSecurityViolation() && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { throw new SecurityException( "Requesting code from " + packageName @@ -2004,7 +2006,7 @@ public final class ActivityThread { + mBoundApplication.processName + "/" + mBoundApplication.appInfo.uid); } - return packageInfo; + return loadedApk; } } @@ -2019,13 +2021,13 @@ public final class ActivityThread { } if (ai != null) { - return getPackageInfo(ai, compatInfo, flags); + return getLoadedApk(ai, compatInfo, flags); } return null; } - public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, + public final LoadedApk getLoadedApk(ApplicationInfo ai, CompatibilityInfo compatInfo, int flags) { boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; boolean securityViolation = includeCode && ai.uid != 0 @@ -2047,16 +2049,16 @@ public final class ActivityThread { throw new SecurityException(msg); } } - return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode, + return getLoadedApk(ai, compatInfo, null, securityViolation, includeCode, registerPackage); } - public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, + public final LoadedApk getLoadedApkNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) { - return getPackageInfo(ai, compatInfo, null, false, true, false); + return getLoadedApk(ai, compatInfo, null, false, true, false); } - public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { + public final LoadedApk peekLoadedApk(String packageName, boolean includeCode) { synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; if (includeCode) { @@ -2068,7 +2070,7 @@ public final class ActivityThread { } } - private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, + private LoadedApk getLoadedApk(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) { final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid)); @@ -2083,35 +2085,35 @@ public final class ActivityThread { ref = mResourcePackages.get(aInfo.packageName); } - LoadedApk packageInfo = ref != null ? ref.get() : null; - if (packageInfo == null || (packageInfo.mResources != null - && !packageInfo.mResources.getAssets().isUpToDate())) { + LoadedApk loadedApk = ref != null ? ref.get() : null; + if (loadedApk == null || (loadedApk.mResources != null + && !loadedApk.mResources.getAssets().isUpToDate())) { if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " : "Loading resource-only package ") + aInfo.packageName + " (in " + (mBoundApplication != null ? mBoundApplication.processName : null) + ")"); - packageInfo = + loadedApk = new LoadedApk(this, aInfo, compatInfo, baseLoader, securityViolation, includeCode && (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); if (mSystemThread && "android".equals(aInfo.packageName)) { - packageInfo.installSystemApplicationInfo(aInfo, - getSystemContext().mPackageInfo.getClassLoader()); + loadedApk.installSystemApplicationInfo(aInfo, + getSystemContext().mLoadedApk.getClassLoader()); } if (differentUser) { // Caching not supported across users } else if (includeCode) { mPackages.put(aInfo.packageName, - new WeakReference<LoadedApk>(packageInfo)); + new WeakReference<LoadedApk>(loadedApk)); } else { mResourcePackages.put(aInfo.packageName, - new WeakReference<LoadedApk>(packageInfo)); + new WeakReference<LoadedApk>(loadedApk)); } } - return packageInfo; + return loadedApk; } } @@ -2645,8 +2647,8 @@ public final class ActivityThread { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; - if (r.packageInfo == null) { - r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, + if (r.loadedApk == null) { + r.loadedApk = getLoadedApk(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } @@ -2683,15 +2685,15 @@ public final class ActivityThread { } try { - Application app = r.packageInfo.makeApplication(false, mInstrumentation); + Application app = r.loadedApk.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() - + ", pkg=" + r.packageInfo.getPackageName() + + ", pkg=" + r.loadedApk.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() - + ", dir=" + r.packageInfo.getAppDir()); + + ", dir=" + r.loadedApk.getAppDir()); if (activity != null) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); @@ -2809,7 +2811,7 @@ public final class ActivityThread { } ContextImpl appContext = ContextImpl.createActivityContext( - this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); + this, r.loadedApk, r.activityInfo, r.token, displayId, r.overrideConfig); final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); // For debugging purposes, if the activity's package name contains the value of @@ -2817,7 +2819,7 @@ public final class ActivityThread { // its content on a secondary display if there is one. String pkgName = SystemProperties.get("debug.second-display.pkg"); if (pkgName != null && !pkgName.isEmpty() - && r.packageInfo.mPackageName.contains(pkgName)) { + && r.loadedApk.mPackageName.contains(pkgName)) { for (int id : dm.getDisplayIds()) { if (id != Display.DEFAULT_DISPLAY) { Display display = @@ -3119,11 +3121,23 @@ public final class ActivityThread { } } - static final void handleAttachAgent(String agent) { + private static boolean attemptAttachAgent(String agent, ClassLoader classLoader) { try { - VMDebug.attachAgent(agent); + VMDebug.attachAgent(agent, classLoader); + return true; } catch (IOException e) { - Slog.e(TAG, "Attaching agent failed: " + agent); + Slog.e(TAG, "Attaching agent with " + classLoader + " failed: " + agent); + return false; + } + } + + static void handleAttachAgent(String agent, LoadedApk loadedApk) { + ClassLoader classLoader = loadedApk != null ? loadedApk.getClassLoader() : null; + if (attemptAttachAgent(agent, classLoader)) { + return; + } + if (classLoader != null) { + attemptAttachAgent(agent, null); } } @@ -3145,7 +3159,7 @@ public final class ActivityThread { String component = data.intent.getComponent().getClassName(); - LoadedApk packageInfo = getPackageInfoNoCheck( + LoadedApk loadedApk = getLoadedApkNoCheck( data.info.applicationInfo, data.compatInfo); IActivityManager mgr = ActivityManager.getService(); @@ -3154,7 +3168,7 @@ public final class ActivityThread { BroadcastReceiver receiver; ContextImpl context; try { - app = packageInfo.makeApplication(false, mInstrumentation); + app = loadedApk.makeApplication(false, mInstrumentation); context = (ContextImpl) app.getBaseContext(); if (data.info.splitName != null) { context = (ContextImpl) context.createContextForSplit(data.info.splitName); @@ -3178,9 +3192,9 @@ public final class ActivityThread { TAG, "Performing receive of " + data.intent + ": app=" + app + ", appName=" + app.getPackageName() - + ", pkg=" + packageInfo.getPackageName() + + ", pkg=" + loadedApk.getPackageName() + ", comp=" + data.intent.getComponent().toShortString() - + ", dir=" + packageInfo.getAppDir()); + + ", dir=" + loadedApk.getAppDir()); sCurrentBroadcastIntent.set(data.intent); receiver.setPendingResult(data); @@ -3225,8 +3239,8 @@ public final class ActivityThread { unscheduleGcIdler(); // instantiate the BackupAgent class named in the manifest - LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); - String packageName = packageInfo.mPackageName; + LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo); + String packageName = loadedApk.mPackageName; if (packageName == null) { Slog.d(TAG, "Asked to create backup agent for nonexistent package"); return; @@ -3252,11 +3266,11 @@ public final class ActivityThread { try { if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); - java.lang.ClassLoader cl = packageInfo.getClassLoader(); + java.lang.ClassLoader cl = loadedApk.getClassLoader(); agent = (BackupAgent) cl.loadClass(classname).newInstance(); // set up the agent's context - ContextImpl context = ContextImpl.createAppContext(this, packageInfo); + ContextImpl context = ContextImpl.createAppContext(this, loadedApk); context.setOuterContext(agent); agent.attach(context); @@ -3292,8 +3306,8 @@ public final class ActivityThread { private void handleDestroyBackupAgent(CreateBackupAgentData data) { if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); - LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); - String packageName = packageInfo.mPackageName; + LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo); + String packageName = loadedApk.mPackageName; BackupAgent agent = mBackupAgents.get(packageName); if (agent != null) { try { @@ -3313,11 +3327,11 @@ public final class ActivityThread { // we are back active so skip it. unscheduleGcIdler(); - LoadedApk packageInfo = getPackageInfoNoCheck( + LoadedApk loadedApk = getLoadedApkNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { - java.lang.ClassLoader cl = packageInfo.getClassLoader(); + java.lang.ClassLoader cl = loadedApk.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { @@ -3330,10 +3344,10 @@ public final class ActivityThread { try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); - ContextImpl context = ContextImpl.createAppContext(this, packageInfo); + ContextImpl context = ContextImpl.createAppContext(this, loadedApk); context.setOuterContext(service); - Application app = packageInfo.makeApplication(false, mInstrumentation); + Application app = loadedApk.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); @@ -3943,7 +3957,7 @@ public final class ActivityThread { Bundle.dumpStats(pw, persistentState); if (ex instanceof TransactionTooLargeException - && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { + && activity.loadedApk.getTargetSdkVersion() < Build.VERSION_CODES.N) { Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex); return; } @@ -4238,11 +4252,11 @@ public final class ActivityThread { } private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) { - LoadedApk apk = peekPackageInfo(data.pkg, false); + LoadedApk apk = peekLoadedApk(data.pkg, false); if (apk != null) { apk.setCompatibilityInfo(data.info); } - apk = peekPackageInfo(data.pkg, true); + apk = peekLoadedApk(data.pkg, true); if (apk != null) { apk.setCompatibilityInfo(data.info); } @@ -4739,7 +4753,7 @@ public final class ActivityThread { if (a != null) { Configuration thisConfig = applyConfigCompatMainThread( mCurDefaultDisplayDpi, newConfig, - ar.packageInfo.getCompatibilityInfo()); + ar.loadedApk.getCompatibilityInfo()); if (!ar.activity.mFinished && (allActivities || !ar.paused)) { // If the activity is currently resumed, its configuration // needs to change right now. @@ -5209,7 +5223,7 @@ public final class ActivityThread { } final void handleDispatchPackageBroadcast(int cmd, String[] packages) { - boolean hasPkgInfo = false; + boolean hasLoadedApk = false; switch (cmd) { case ApplicationThreadConstants.PACKAGE_REMOVED: case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL: @@ -5220,14 +5234,14 @@ public final class ActivityThread { } synchronized (mResourcesManager) { for (int i = packages.length - 1; i >= 0; i--) { - if (!hasPkgInfo) { + if (!hasLoadedApk) { WeakReference<LoadedApk> ref = mPackages.get(packages[i]); if (ref != null && ref.get() != null) { - hasPkgInfo = true; + hasLoadedApk = true; } else { ref = mResourcePackages.get(packages[i]); if (ref != null && ref.get() != null) { - hasPkgInfo = true; + hasLoadedApk = true; } } } @@ -5247,21 +5261,21 @@ public final class ActivityThread { synchronized (mResourcesManager) { for (int i = packages.length - 1; i >= 0; i--) { WeakReference<LoadedApk> ref = mPackages.get(packages[i]); - LoadedApk pkgInfo = ref != null ? ref.get() : null; - if (pkgInfo != null) { - hasPkgInfo = true; + LoadedApk loadedApk = ref != null ? ref.get() : null; + if (loadedApk != null) { + hasLoadedApk = true; } else { ref = mResourcePackages.get(packages[i]); - pkgInfo = ref != null ? ref.get() : null; - if (pkgInfo != null) { - hasPkgInfo = true; + loadedApk = ref != null ? ref.get() : null; + if (loadedApk != null) { + hasLoadedApk = true; } } // If the package is being replaced, yet it still has a valid // LoadedApk object, the package was updated with _DONT_KILL. // Adjust it's internal references to the application info and // resources. - if (pkgInfo != null) { + if (loadedApk != null) { try { final String packageName = packages[i]; final ApplicationInfo aInfo = @@ -5275,13 +5289,13 @@ public final class ActivityThread { if (ar.activityInfo.applicationInfo.packageName .equals(packageName)) { ar.activityInfo.applicationInfo = aInfo; - ar.packageInfo = pkgInfo; + ar.loadedApk = loadedApk; } } } final List<String> oldPaths = sPackageManager.getPreviousCodePaths(packageName); - pkgInfo.updateApplicationInfo(aInfo, oldPaths); + loadedApk.updateApplicationInfo(aInfo, oldPaths); } catch (RemoteException e) { } } @@ -5290,7 +5304,7 @@ public final class ActivityThread { break; } } - ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo); + ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasLoadedApk); } final void handleLowMemory() { @@ -5441,12 +5455,16 @@ public final class ActivityThread { mCompatConfiguration = new Configuration(data.config); mProfiler = new Profiler(); + String agent = null; if (data.initProfilerInfo != null) { mProfiler.profileFile = data.initProfilerInfo.profileFile; mProfiler.profileFd = data.initProfilerInfo.profileFd; mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput; + if (data.initProfilerInfo.attachAgentDuringBind) { + agent = data.initProfilerInfo.agent; + } } // send up app name; do this *before* waiting for debugger @@ -5494,7 +5512,11 @@ public final class ActivityThread { applyCompatConfiguration(mCurDefaultDisplayDpi); } - data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); + data.loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo); + + if (agent != null) { + handleAttachAgent(agent, data.loadedApk); + } /** * Switch this process to density compatibility mode if needed. @@ -5562,7 +5584,7 @@ public final class ActivityThread { // XXX should have option to change the port. Debug.changeDebugPort(8100); if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) { - Slog.w(TAG, "Application " + data.info.getPackageName() + Slog.w(TAG, "Application " + data.loadedApk.getPackageName() + " is waiting for the debugger on port 8100..."); IActivityManager mgr = ActivityManager.getService(); @@ -5581,7 +5603,7 @@ public final class ActivityThread { } } else { - Slog.w(TAG, "Application " + data.info.getPackageName() + Slog.w(TAG, "Application " + data.loadedApk.getPackageName() + " can be debugged on port 8100..."); } } @@ -5629,14 +5651,14 @@ public final class ActivityThread { mInstrumentationAppDir = ii.sourceDir; mInstrumentationSplitAppDirs = ii.splitSourceDirs; mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii); - mInstrumentedAppDir = data.info.getAppDir(); - mInstrumentedSplitAppDirs = data.info.getSplitAppDirs(); - mInstrumentedLibDir = data.info.getLibDir(); + mInstrumentedAppDir = data.loadedApk.getAppDir(); + mInstrumentedSplitAppDirs = data.loadedApk.getSplitAppDirs(); + mInstrumentedLibDir = data.loadedApk.getLibDir(); } else { ii = null; } - final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); + final ContextImpl appContext = ContextImpl.createAppContext(this, data.loadedApk); updateLocaleListFromAppContext(appContext, mResourcesManager.getConfiguration().getLocales()); @@ -5666,9 +5688,9 @@ public final class ActivityThread { final ApplicationInfo instrApp = new ApplicationInfo(); ii.copyTo(instrApp); instrApp.initForUser(UserHandle.myUserId()); - final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, + final LoadedApk loadedApk = getLoadedApk(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); - final ContextImpl instrContext = ContextImpl.createAppContext(this, pi); + final ContextImpl instrContext = ContextImpl.createAppContext(this, loadedApk); try { final ClassLoader cl = instrContext.getClassLoader(); @@ -5712,7 +5734,7 @@ public final class ActivityThread { try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. - app = data.info.makeApplication(data.restrictedBackupMode, null); + app = data.loadedApk.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the @@ -5766,7 +5788,7 @@ public final class ActivityThread { final int preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { - data.info.getResources().preloadFonts(preloadedFontsResource); + data.loadedApk.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { @@ -6361,8 +6383,8 @@ public final class ActivityThread { try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( - this, getSystemContext().mPackageInfo); - mInitialApplication = context.mPackageInfo.makeApplication(true, null); + this, getSystemContext().mLoadedApk); + mInitialApplication = context.mLoadedApk.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 156df36a600c..5822f5c8f6c1 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -187,7 +187,7 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { */ /* package */ final void attach(Context context) { attachBaseContext(context); - mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; + mLoadedApk = ContextImpl.getImpl(context).mLoadedApk; } /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 0eafdec6bb0f..4d47d82260c2 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1379,7 +1379,7 @@ public class ApplicationPackageManager extends PackageManager { sameUid ? app.sourceDir : app.publicSourceDir, sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs, app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY, - mContext.mPackageInfo); + mContext.mLoadedApk); if (r != null) { return r; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 5f3432264ca0..64ddfbceeda4 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -159,7 +159,7 @@ class ContextImpl extends Context { private ArrayMap<String, File> mSharedPrefsPaths; final @NonNull ActivityThread mMainThread; - final @NonNull LoadedApk mPackageInfo; + final @NonNull LoadedApk mLoadedApk; private @Nullable ClassLoader mClassLoader; private final @Nullable IBinder mActivityToken; @@ -252,8 +252,8 @@ class ContextImpl extends Context { @Override public Context getApplicationContext() { - return (mPackageInfo != null) ? - mPackageInfo.getApplication() : mMainThread.getApplication(); + return (mLoadedApk != null) ? + mLoadedApk.getApplication() : mMainThread.getApplication(); } @Override @@ -297,15 +297,15 @@ class ContextImpl extends Context { @Override public ClassLoader getClassLoader() { - return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader()); + return mClassLoader != null ? mClassLoader : (mLoadedApk != null ? mLoadedApk.getClassLoader() : ClassLoader.getSystemClassLoader()); } @Override public String getPackageName() { - if (mPackageInfo != null) { - return mPackageInfo.getPackageName(); + if (mLoadedApk != null) { + return mLoadedApk.getPackageName(); } - // No mPackageInfo means this is a Context for the system itself, + // No mLoadedApk means this is a Context for the system itself, // and this here is its name. return "android"; } @@ -324,24 +324,24 @@ class ContextImpl extends Context { @Override public ApplicationInfo getApplicationInfo() { - if (mPackageInfo != null) { - return mPackageInfo.getApplicationInfo(); + if (mLoadedApk != null) { + return mLoadedApk.getApplicationInfo(); } throw new RuntimeException("Not supported in system context"); } @Override public String getPackageResourcePath() { - if (mPackageInfo != null) { - return mPackageInfo.getResDir(); + if (mLoadedApk != null) { + return mLoadedApk.getResDir(); } throw new RuntimeException("Not supported in system context"); } @Override public String getPackageCodePath() { - if (mPackageInfo != null) { - return mPackageInfo.getAppDir(); + if (mLoadedApk != null) { + return mLoadedApk.getAppDir(); } throw new RuntimeException("Not supported in system context"); } @@ -351,7 +351,7 @@ class ContextImpl extends Context { // At least one application in the world actually passes in a null // name. This happened to work because when we generated the file name // we would stringify it to "null.xml". Nice. - if (mPackageInfo.getApplicationInfo().targetSdkVersion < + if (mLoadedApk.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.KITKAT) { if (name == null) { name = "null"; @@ -1093,11 +1093,11 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); IIntentReceiver rd = null; if (resultReceiver != null) { - if (mPackageInfo != null) { + if (mLoadedApk != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = mPackageInfo.getReceiverDispatcher( + rd = mLoadedApk.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { @@ -1197,11 +1197,11 @@ class ContextImpl extends Context { Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { - if (mPackageInfo != null) { + if (mLoadedApk != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = mPackageInfo.getReceiverDispatcher( + rd = mLoadedApk.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { @@ -1251,11 +1251,11 @@ class ContextImpl extends Context { warnIfCallingFromSystemProcess(); IIntentReceiver rd = null; if (resultReceiver != null) { - if (mPackageInfo != null) { + if (mLoadedApk != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = mPackageInfo.getReceiverDispatcher( + rd = mLoadedApk.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { @@ -1333,11 +1333,11 @@ class ContextImpl extends Context { Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { - if (mPackageInfo != null) { + if (mLoadedApk != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = mPackageInfo.getReceiverDispatcher( + rd = mLoadedApk.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { @@ -1414,11 +1414,11 @@ class ContextImpl extends Context { Handler scheduler, Context context, int flags) { IIntentReceiver rd = null; if (receiver != null) { - if (mPackageInfo != null && context != null) { + if (mLoadedApk != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = mPackageInfo.getReceiverDispatcher( + rd = mLoadedApk.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { @@ -1445,8 +1445,8 @@ class ContextImpl extends Context { @Override public void unregisterReceiver(BroadcastReceiver receiver) { - if (mPackageInfo != null) { - IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( + if (mLoadedApk != null) { + IIntentReceiver rd = mLoadedApk.forgetReceiverDispatcher( getOuterContext(), receiver); try { ActivityManager.getService().unregisterReceiver(rd); @@ -1579,7 +1579,7 @@ class ContextImpl extends Context { @Override public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler, int flags) { - return mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); + return mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags); } /** @hide */ @@ -1601,16 +1601,16 @@ class ContextImpl extends Context { if (conn == null) { throw new IllegalArgumentException("connection is null"); } - if (mPackageInfo != null) { - sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); + if (mLoadedApk != null) { + sd = mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags); } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { IBinder token = getActivityToken(); - if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null - && mPackageInfo.getApplicationInfo().targetSdkVersion + if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mLoadedApk != null + && mLoadedApk.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } @@ -1634,8 +1634,8 @@ class ContextImpl extends Context { if (conn == null) { throw new IllegalArgumentException("connection is null"); } - if (mPackageInfo != null) { - IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( + if (mLoadedApk != null) { + IServiceConnection sd = mLoadedApk.forgetServiceDispatcher( getOuterContext(), conn); try { ActivityManager.getService().unbindService(sd); @@ -1980,40 +1980,20 @@ class ContextImpl extends Context { } } - private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName, - int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) { - final String[] splitResDirs; - final ClassLoader classLoader; - try { - splitResDirs = pi.getSplitPaths(splitName); - classLoader = pi.getSplitClassLoader(splitName); - } catch (NameNotFoundException e) { - throw new RuntimeException(e); - } - return ResourcesManager.getInstance().getResources(activityToken, - pi.getResDir(), - splitResDirs, - pi.getOverlayDirs(), - pi.getApplicationInfo().sharedLibraryFiles, - displayId, - overrideConfig, - compatInfo, - classLoader); - } - @Override public Context createApplicationContext(ApplicationInfo application, int flags) throws NameNotFoundException { - LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), + LoadedApk loadedApk = mMainThread.getLoadedApk(application, + mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE); - if (pi != null) { - ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, + if (loadedApk != null) { + ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken, new UserHandle(UserHandle.getUserId(application.uid)), flags, null); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; - c.setResources(createResources(mActivityToken, pi, null, displayId, null, + c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; @@ -2037,20 +2017,21 @@ class ContextImpl extends Context { if (packageName.equals("system") || packageName.equals("android")) { // The system resources are loaded in every application, so we can safely copy // the context without reloading Resources. - return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user, + return new ContextImpl(this, mMainThread, mLoadedApk, null, mActivityToken, user, flags, null); } - LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), + LoadedApk loadedApk = mMainThread.getLoadedApkForPackageName(packageName, + mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); - if (pi != null) { - ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user, + if (loadedApk != null) { + ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken, user, flags, null); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; - c.setResources(createResources(mActivityToken, pi, null, displayId, null, + c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; @@ -2064,30 +2045,21 @@ class ContextImpl extends Context { @Override public Context createContextForSplit(String splitName) throws NameNotFoundException { - if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { + if (!mLoadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) { // All Splits are always loaded. return this; } - final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName); - final String[] paths = mPackageInfo.getSplitPaths(splitName); + final ClassLoader classLoader = mLoadedApk.getSplitClassLoader(splitName); - final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName, + final ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, splitName, mActivityToken, mUser, mFlags, classLoader); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; - context.setResources(ResourcesManager.getInstance().getResources( - mActivityToken, - mPackageInfo.getResDir(), - paths, - mPackageInfo.getOverlayDirs(), - mPackageInfo.getApplicationInfo().sharedLibraryFiles, - displayId, - null, - mPackageInfo.getCompatibilityInfo(), - classLoader)); + context.setResources(mLoadedApk.getOrCreateResourcesForSplit(splitName, + mActivityToken, displayId)); return context; } @@ -2097,11 +2069,11 @@ class ContextImpl extends Context { throw new IllegalArgumentException("overrideConfiguration must not be null"); } - ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, + ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser, mFlags, mClassLoader); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; - context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, + context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId, overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo())); return context; } @@ -2112,11 +2084,11 @@ class ContextImpl extends Context { throw new IllegalArgumentException("display must not be null"); } - ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, + ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser, mFlags, mClassLoader); final int displayId = display.getDisplayId(); - context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, + context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); context.mDisplay = display; return context; @@ -2126,7 +2098,7 @@ class ContextImpl extends Context { public Context createDeviceProtectedStorageContext() { final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) | Context.CONTEXT_DEVICE_PROTECTED_STORAGE; - return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, + return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser, flags, mClassLoader); } @@ -2134,7 +2106,7 @@ class ContextImpl extends Context { public Context createCredentialProtectedStorageContext() { final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE) | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; - return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, + return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser, flags, mClassLoader); } @@ -2183,14 +2155,14 @@ class ContextImpl extends Context { @Override public File getDataDir() { - if (mPackageInfo != null) { + if (mLoadedApk != null) { File res = null; if (isCredentialProtectedStorage()) { - res = mPackageInfo.getCredentialProtectedDataDirFile(); + res = mLoadedApk.getCredentialProtectedDataDirFile(); } else if (isDeviceProtectedStorage()) { - res = mPackageInfo.getDeviceProtectedDataDirFile(); + res = mLoadedApk.getDeviceProtectedDataDirFile(); } else { - res = mPackageInfo.getDataDirFile(); + res = mLoadedApk.getDataDirFile(); } if (res != null) { @@ -2241,10 +2213,10 @@ class ContextImpl extends Context { } static ContextImpl createSystemContext(ActivityThread mainThread) { - LoadedApk packageInfo = new LoadedApk(mainThread); - ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, + LoadedApk loadedApk = new LoadedApk(mainThread); + ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0, null); - context.setResources(packageInfo.getResources()); + context.setResources(loadedApk.getResources()); context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(), context.mResourcesManager.getDisplayMetrics()); return context; @@ -2255,35 +2227,35 @@ class ContextImpl extends Context { * Make sure that the created system UI context shares the same LoadedApk as the system context. */ static ContextImpl createSystemUiContext(ContextImpl systemContext) { - final LoadedApk packageInfo = systemContext.mPackageInfo; - ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null, + final LoadedApk loadedApk = systemContext.mLoadedApk; + ContextImpl context = new ContextImpl(null, systemContext.mMainThread, loadedApk, null, null, null, 0, null); - context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null, - packageInfo.getCompatibilityInfo())); + context.setResources(loadedApk.createResources(null, null, Display.DEFAULT_DISPLAY, null, + loadedApk.getCompatibilityInfo())); return context; } - static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { - if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); - ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, + static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk loadedApk) { + if (loadedApk == null) throw new IllegalArgumentException("loadedApk"); + ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0, null); - context.setResources(packageInfo.getResources()); + context.setResources(loadedApk.getResources()); return context; } static ContextImpl createActivityContext(ActivityThread mainThread, - LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId, + LoadedApk loadedApk, ActivityInfo activityInfo, IBinder activityToken, int displayId, Configuration overrideConfiguration) { - if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); + if (loadedApk == null) throw new IllegalArgumentException("loadedApk"); - String[] splitDirs = packageInfo.getSplitResDirs(); - ClassLoader classLoader = packageInfo.getClassLoader(); + String[] splitDirs = loadedApk.getSplitResDirs(); + ClassLoader classLoader = loadedApk.getClassLoader(); - if (packageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { + if (loadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "SplitDependencies"); try { - classLoader = packageInfo.getSplitClassLoader(activityInfo.splitName); - splitDirs = packageInfo.getSplitPaths(activityInfo.splitName); + classLoader = loadedApk.getSplitClassLoader(activityInfo.splitName); + splitDirs = loadedApk.getSplitPaths(activityInfo.splitName); } catch (NameNotFoundException e) { // Nothing above us can handle a NameNotFoundException, better crash. throw new RuntimeException(e); @@ -2292,14 +2264,14 @@ class ContextImpl extends Context { } } - ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName, + ContextImpl context = new ContextImpl(null, mainThread, loadedApk, activityInfo.splitName, activityToken, null, 0, classLoader); // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY) - ? packageInfo.getCompatibilityInfo() + ? loadedApk.getCompatibilityInfo() : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; final ResourcesManager resourcesManager = ResourcesManager.getInstance(); @@ -2307,10 +2279,10 @@ class ContextImpl extends Context { // Create the base resources for which all configuration contexts for this Activity // will be rebased upon. context.setResources(resourcesManager.createBaseActivityResources(activityToken, - packageInfo.getResDir(), + loadedApk.getResDir(), splitDirs, - packageInfo.getOverlayDirs(), - packageInfo.getApplicationInfo().sharedLibraryFiles, + loadedApk.getOverlayDirs(), + loadedApk.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfiguration, compatInfo, @@ -2321,7 +2293,7 @@ class ContextImpl extends Context { } private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread, - @NonNull LoadedApk packageInfo, @Nullable String splitName, + @NonNull LoadedApk loadedApk, @Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user, int flags, @Nullable ClassLoader classLoader) { mOuterContext = this; @@ -2330,10 +2302,10 @@ class ContextImpl extends Context { // location for application. if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) { - final File dataDir = packageInfo.getDataDirFile(); - if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) { + final File dataDir = loadedApk.getDataDirFile(); + if (Objects.equals(dataDir, loadedApk.getCredentialProtectedDataDirFile())) { flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; - } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) { + } else if (Objects.equals(dataDir, loadedApk.getDeviceProtectedDataDirFile())) { flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE; } } @@ -2347,7 +2319,7 @@ class ContextImpl extends Context { } mUser = user; - mPackageInfo = packageInfo; + mLoadedApk = loadedApk; mSplitName = splitName; mClassLoader = classLoader; mResourcesManager = ResourcesManager.getInstance(); @@ -2358,8 +2330,8 @@ class ContextImpl extends Context { setResources(container.mResources); mDisplay = container.mDisplay; } else { - mBasePackageName = packageInfo.mPackageName; - ApplicationInfo ainfo = packageInfo.getApplicationInfo(); + mBasePackageName = loadedApk.mPackageName; + ApplicationInfo ainfo = loadedApk.getApplicationInfo(); if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) { // Special case: system components allow themselves to be loaded in to other // processes. For purposes of app ops, we must then consider the context as @@ -2382,7 +2354,7 @@ class ContextImpl extends Context { } void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { - mPackageInfo.installSystemApplicationInfo(info, classLoader); + mLoadedApk.installSystemApplicationInfo(info, classLoader); } final void scheduleFinalCleanup(String who, String what) { @@ -2391,7 +2363,7 @@ class ContextImpl extends Context { final void performFinalCleanup(String who, String what) { //Log.i(TAG, "Cleanup up context: " + this); - mPackageInfo.removeContextRegistrations(getOuterContext(), who, what); + mLoadedApk.removeContextRegistrations(getOuterContext(), who, what); } final Context getReceiverRestrictedContext() { diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index f6d9710dae69..236a42c583e8 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -31,6 +31,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.split.SplitDependencyLoader; import android.content.res.AssetManager; import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; @@ -48,15 +49,13 @@ import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.Log; +import android.util.LogPrinter; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayAdjustments; - import com.android.internal.util.ArrayUtils; - import dalvik.system.VMRuntime; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -948,14 +947,78 @@ public final class LoadedApk { throw new AssertionError("null split not found"); } - mResources = ResourcesManager.getInstance().getResources(null, mResDir, - splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, - Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), + mResources = ResourcesManager.getInstance().getResources( + null, + mResDir, + splitPaths, + mOverlayDirs, + mApplicationInfo.sharedLibraryFiles, + Display.DEFAULT_DISPLAY, + null, + getCompatibilityInfo(), getClassLoader()); } return mResources; } + public Resources getOrCreateResourcesForSplit(@NonNull String splitName, + @Nullable IBinder activityToken, int displayId) throws NameNotFoundException { + return ResourcesManager.getInstance().getResources( + activityToken, + mResDir, + getSplitPaths(splitName), + mOverlayDirs, + mApplicationInfo.sharedLibraryFiles, + displayId, + null, + getCompatibilityInfo(), + getSplitClassLoader(splitName)); + } + + /** + * Creates the top level resources for the given package. Will return an existing + * Resources if one has already been created. + */ + public Resources getOrCreateTopLevelResources(@NonNull ApplicationInfo appInfo) { + // Request for this app, short circuit + if (appInfo.uid == Process.myUid()) { + return getResources(); + } + + // Get resources for a different package + return ResourcesManager.getInstance().getResources( + null, + appInfo.publicSourceDir, + appInfo.splitPublicSourceDirs, + appInfo.resourceDirs, + appInfo.sharedLibraryFiles, + Display.DEFAULT_DISPLAY, + null, + getCompatibilityInfo(), + getClassLoader()); + } + + public Resources createResources(IBinder activityToken, String splitName, + int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) { + final String[] splitResDirs; + final ClassLoader classLoader; + try { + splitResDirs = getSplitPaths(splitName); + classLoader = getSplitClassLoader(splitName); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + return ResourcesManager.getInstance().getResources(activityToken, + mResDir, + splitResDirs, + mOverlayDirs, + mApplicationInfo.sharedLibraryFiles, + displayId, + overrideConfig, + compatInfo, + classLoader); + } + public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java index fad4798e3a3e..044b78003bd7 100644 --- a/core/java/android/app/ProfilerInfo.java +++ b/core/java/android/app/ProfilerInfo.java @@ -54,14 +54,24 @@ public class ProfilerInfo implements Parcelable { */ public final String agent; + /** + * Whether the {@link agent} should be attached early (before bind-application) or during + * bind-application. Agents attached prior to binding cannot be loaded from the app's APK + * directly and must be given as an absolute path (or available in the default LD_LIBRARY_PATH). + * Agents attached during bind-application will miss early setup (e.g., resource initialization + * and classloader generation), but are searched in the app's library search path. + */ + public final boolean attachAgentDuringBind; + public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, - boolean streaming, String agent) { + boolean streaming, String agent, boolean attachAgentDuringBind) { profileFile = filename; profileFd = fd; samplingInterval = interval; autoStopProfiler = autoStop; streamingOutput = streaming; this.agent = agent; + this.attachAgentDuringBind = attachAgentDuringBind; } public ProfilerInfo(ProfilerInfo in) { @@ -71,6 +81,7 @@ public class ProfilerInfo implements Parcelable { autoStopProfiler = in.autoStopProfiler; streamingOutput = in.streamingOutput; agent = in.agent; + attachAgentDuringBind = in.attachAgentDuringBind; } /** @@ -109,6 +120,7 @@ public class ProfilerInfo implements Parcelable { out.writeInt(autoStopProfiler ? 1 : 0); out.writeInt(streamingOutput ? 1 : 0); out.writeString(agent); + out.writeBoolean(attachAgentDuringBind); } public static final Parcelable.Creator<ProfilerInfo> CREATOR = @@ -131,5 +143,6 @@ public class ProfilerInfo implements Parcelable { autoStopProfiler = in.readInt() != 0; streamingOutput = in.readInt() != 0; agent = in.readString(); + attachAgentDuringBind = in.readBoolean(); } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index c7be0f36ecef..cdc881a25aa5 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1671,6 +1671,27 @@ public final class BluetoothAdapter { } /** + * Get the maximum number of connected audio devices. + * + * @return the maximum number of connected audio devices + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getMaxConnectedAudioDevices() { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.getMaxConnectedAudioDevices(); + } + } catch (RemoteException e) { + Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e); + } finally { + mServiceLock.readLock().unlock(); + } + return 1; + } + + /** * Return true if hardware has entries available for matching beacons * * @return true if there are hw entries available for matching beacons diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java index dc00d63043fc..d46b2e37467b 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java @@ -73,17 +73,18 @@ public final class BluetoothHeadsetClientCall implements Parcelable { private final boolean mOutgoing; private final UUID mUUID; private final long mCreationElapsedMilli; + private final boolean mInBandRing; /** * Creates BluetoothHeadsetClientCall instance. */ public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number, - boolean multiParty, boolean outgoing) { - this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing); + boolean multiParty, boolean outgoing, boolean inBandRing) { + this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing); } public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state, - String number, boolean multiParty, boolean outgoing) { + String number, boolean multiParty, boolean outgoing, boolean inBandRing) { mDevice = device; mId = id; mUUID = uuid; @@ -91,6 +92,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { mNumber = number != null ? number : ""; mMultiParty = multiParty; mOutgoing = outgoing; + mInBandRing = inBandRing; mCreationElapsedMilli = SystemClock.elapsedRealtime(); } @@ -200,6 +202,16 @@ public final class BluetoothHeadsetClientCall implements Parcelable { return mOutgoing; } + /** + * Checks if the ringtone will be generated by the connected phone + * + * @return <code>true</code> if in band ring is enabled, <code>false</code> otherwise. + */ + public boolean isInBandRing() { + return mInBandRing; + } + + @Override public String toString() { return toString(false); @@ -253,6 +265,8 @@ public final class BluetoothHeadsetClientCall implements Parcelable { builder.append(mMultiParty); builder.append(", mOutgoing: "); builder.append(mOutgoing); + builder.append(", mInBandRing: "); + builder.append(mInBandRing); builder.append("}"); return builder.toString(); } @@ -266,7 +280,8 @@ public final class BluetoothHeadsetClientCall implements Parcelable { public BluetoothHeadsetClientCall createFromParcel(Parcel in) { return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null), in.readInt(), UUID.fromString(in.readString()), in.readInt(), - in.readString(), in.readInt() == 1, in.readInt() == 1); + in.readString(), in.readInt() == 1, in.readInt() == 1, + in.readInt() == 1); } @Override @@ -284,6 +299,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { out.writeString(mNumber); out.writeInt(mMultiParty ? 1 : 0); out.writeInt(mOutgoing ? 1 : 0); + out.writeInt(mInBandRing ? 1 : 0); } @Override diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d9b57db18071..790c80b1d934 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -31,7 +31,7 @@ import android.os.ParcelFileDescriptor; interface IIpSecService { IpSecSpiResponse allocateSecurityParameterIndex( - int direction, in String remoteAddress, int requestedSpi, in IBinder binder); + in String destinationAddress, int requestedSpi, in IBinder binder); void releaseSecurityParameterIndex(int resourceId); @@ -43,7 +43,7 @@ interface IIpSecService void deleteTransportModeTransform(int transformId); - void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId); + void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); - void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId); + void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 7d752e89e6f6..c69a4d4c0bee 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -256,13 +256,19 @@ public final class IpSecAlgorithm implements Parcelable { return getName().equals(AUTH_CRYPT_AES_GCM); } + // Because encryption keys are sensitive and userdebug builds are used by large user pools + // such as beta testers, we only allow sensitive info such as keys on eng builds. + private static boolean isUnsafeBuild() { + return Build.IS_DEBUGGABLE && Build.IS_ENG; + } + @Override public String toString() { return new StringBuilder() .append("{mName=") .append(mName) .append(", mKey=") - .append(Build.IS_DEBUGGABLE ? HexDump.toHexString(mKey) : "<hidden>") + .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>") .append(", mTruncLenBits=") .append(mTruncLenBits) .append("}") diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index f54ceb5c142a..80b0af33735b 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -32,59 +32,29 @@ public final class IpSecConfig implements Parcelable { // MODE_TRANSPORT or MODE_TUNNEL private int mMode = IpSecTransform.MODE_TRANSPORT; - // Needs to be valid only for tunnel mode // Preventing this from being null simplifies Java->Native binder - private String mLocalAddress = ""; + private String mSourceAddress = ""; // Preventing this from being null simplifies Java->Native binder - private String mRemoteAddress = ""; + private String mDestinationAddress = ""; // The underlying Network that represents the "gateway" Network // for outbound packets. It may also be used to select packets. private Network mNetwork; - /** - * This class captures the parameters that specifically apply to inbound or outbound traffic. - */ - public static class Flow { - // Minimum requirements for identifying a transform - // SPI identifying the IPsec flow in packet processing - // and a remote IP address - private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; - - // Encryption Algorithm - private IpSecAlgorithm mEncryption; - - // Authentication Algorithm - private IpSecAlgorithm mAuthentication; - - // Authenticated Encryption Algorithm - private IpSecAlgorithm mAuthenticatedEncryption; - - @Override - public String toString() { - return new StringBuilder() - .append("{mSpiResourceId=") - .append(mSpiResourceId) - .append(", mEncryption=") - .append(mEncryption) - .append(", mAuthentication=") - .append(mAuthentication) - .append(", mAuthenticatedEncryption=") - .append(mAuthenticatedEncryption) - .append("}") - .toString(); - } - - static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) { - if (lhs == null || rhs == null) return (lhs == rhs); - return (lhs.mSpiResourceId == rhs.mSpiResourceId - && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) - && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); - } - } + // Minimum requirements for identifying a transform + // SPI identifying the IPsec SA in packet processing + // and a destination IP address + private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; + + // Encryption Algorithm + private IpSecAlgorithm mEncryption; + + // Authentication Algorithm + private IpSecAlgorithm mAuthentication; - private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()}; + // Authenticated Encryption Algorithm + private IpSecAlgorithm mAuthenticatedEncryption; // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE @@ -100,36 +70,37 @@ public final class IpSecConfig implements Parcelable { mMode = mode; } - /** Set the local IP address for Tunnel mode */ - public void setLocalAddress(String localAddress) { - mLocalAddress = localAddress; + /** Set the source IP addres for this IPsec transform */ + public void setSourceAddress(String sourceAddress) { + mSourceAddress = sourceAddress; } - /** Set the remote IP address for this IPsec transform */ - public void setRemoteAddress(String remoteAddress) { - mRemoteAddress = remoteAddress; + /** Set the destination IP address for this IPsec transform */ + public void setDestinationAddress(String destinationAddress) { + mDestinationAddress = destinationAddress; } - /** Set the SPI for a given direction by resource ID */ - public void setSpiResourceId(int direction, int resourceId) { - mFlow[direction].mSpiResourceId = resourceId; + /** Set the SPI by resource ID */ + public void setSpiResourceId(int resourceId) { + mSpiResourceId = resourceId; } - /** Set the encryption algorithm for a given direction */ - public void setEncryption(int direction, IpSecAlgorithm encryption) { - mFlow[direction].mEncryption = encryption; + /** Set the encryption algorithm */ + public void setEncryption(IpSecAlgorithm encryption) { + mEncryption = encryption; } - /** Set the authentication algorithm for a given direction */ - public void setAuthentication(int direction, IpSecAlgorithm authentication) { - mFlow[direction].mAuthentication = authentication; + /** Set the authentication algorithm */ + public void setAuthentication(IpSecAlgorithm authentication) { + mAuthentication = authentication; } - /** Set the authenticated encryption algorithm for a given direction */ - public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) { - mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption; + /** Set the authenticated encryption algorithm */ + public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) { + mAuthenticatedEncryption = authenticatedEncryption; } + /** Set the underlying network that will carry traffic for this transform */ public void setNetwork(Network network) { mNetwork = network; } @@ -155,28 +126,28 @@ public final class IpSecConfig implements Parcelable { return mMode; } - public String getLocalAddress() { - return mLocalAddress; + public String getSourceAddress() { + return mSourceAddress; } - public int getSpiResourceId(int direction) { - return mFlow[direction].mSpiResourceId; + public int getSpiResourceId() { + return mSpiResourceId; } - public String getRemoteAddress() { - return mRemoteAddress; + public String getDestinationAddress() { + return mDestinationAddress; } - public IpSecAlgorithm getEncryption(int direction) { - return mFlow[direction].mEncryption; + public IpSecAlgorithm getEncryption() { + return mEncryption; } - public IpSecAlgorithm getAuthentication(int direction) { - return mFlow[direction].mAuthentication; + public IpSecAlgorithm getAuthentication() { + return mAuthentication; } - public IpSecAlgorithm getAuthenticatedEncryption(int direction) { - return mFlow[direction].mAuthenticatedEncryption; + public IpSecAlgorithm getAuthenticatedEncryption() { + return mAuthenticatedEncryption; } public Network getNetwork() { @@ -209,17 +180,13 @@ public final class IpSecConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mMode); - out.writeString(mLocalAddress); - out.writeString(mRemoteAddress); + out.writeString(mSourceAddress); + out.writeString(mDestinationAddress); out.writeParcelable(mNetwork, flags); - out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags); - out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags); + out.writeInt(mSpiResourceId); + out.writeParcelable(mEncryption, flags); + out.writeParcelable(mAuthentication, flags); + out.writeParcelable(mAuthenticatedEncryption, flags); out.writeInt(mEncapType); out.writeInt(mEncapSocketResourceId); out.writeInt(mEncapRemotePort); @@ -231,22 +198,15 @@ public final class IpSecConfig implements Parcelable { private IpSecConfig(Parcel in) { mMode = in.readInt(); - mLocalAddress = in.readString(); - mRemoteAddress = in.readString(); + mSourceAddress = in.readString(); + mDestinationAddress = in.readString(); mNetwork = (Network) in.readParcelable(Network.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt(); - mFlow[IpSecTransform.DIRECTION_IN].mEncryption = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mAuthentication = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt(); - mFlow[IpSecTransform.DIRECTION_OUT].mEncryption = + mSpiResourceId = in.readInt(); + mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication = + mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption = + mAuthenticatedEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mEncapType = in.readInt(); mEncapSocketResourceId = in.readInt(); @@ -260,10 +220,10 @@ public final class IpSecConfig implements Parcelable { strBuilder .append("{mMode=") .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") - .append(", mLocalAddress=") - .append(mLocalAddress) - .append(", mRemoteAddress=") - .append(mRemoteAddress) + .append(", mSourceAddress=") + .append(mSourceAddress) + .append(", mDestinationAddress=") + .append(mDestinationAddress) .append(", mNetwork=") .append(mNetwork) .append(", mEncapType=") @@ -274,10 +234,14 @@ public final class IpSecConfig implements Parcelable { .append(mEncapRemotePort) .append(", mNattKeepaliveInterval=") .append(mNattKeepaliveInterval) - .append(", mFlow[OUT]=") - .append(mFlow[IpSecTransform.DIRECTION_OUT]) - .append(", mFlow[IN]=") - .append(mFlow[IpSecTransform.DIRECTION_IN]) + .append("{mSpiResourceId=") + .append(mSpiResourceId) + .append(", mEncryption=") + .append(mEncryption) + .append(", mAuthentication=") + .append(mAuthentication) + .append(", mAuthenticatedEncryption=") + .append(mAuthenticatedEncryption) .append("}"); return strBuilder.toString(); @@ -299,17 +263,18 @@ public final class IpSecConfig implements Parcelable { public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { if (lhs == null || rhs == null) return (lhs == rhs); return (lhs.mMode == rhs.mMode - && lhs.mLocalAddress.equals(rhs.mLocalAddress) - && lhs.mRemoteAddress.equals(rhs.mRemoteAddress) + && lhs.mSourceAddress.equals(rhs.mSourceAddress) + && lhs.mDestinationAddress.equals(rhs.mDestinationAddress) && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork)) || (lhs.mNetwork == rhs.mNetwork)) && lhs.mEncapType == rhs.mEncapType && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId && lhs.mEncapRemotePort == rhs.mEncapRemotePort && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval - && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT], - rhs.mFlow[IpSecTransform.DIRECTION_OUT]) - && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN], - rhs.mFlow[IpSecTransform.DIRECTION_IN])); + && lhs.mSpiResourceId == rhs.mSpiResourceId + && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) + && IpSecAlgorithm.equals( + lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) + && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); } } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 34cfa9b2153d..2cda58c99a61 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -17,6 +17,7 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemService; import android.annotation.TestApi; @@ -33,6 +34,8 @@ import dalvik.system.CloseGuard; import java.io.FileDescriptor; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; @@ -53,6 +56,23 @@ public final class IpSecManager { private static final String TAG = "IpSecManager"; /** + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic towards the host. + */ + public static final int DIRECTION_IN = 0; + + /** + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic from the host. + */ + public static final int DIRECTION_OUT = 1; + + /** @hide */ + @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) + @Retention(RetentionPolicy.SOURCE) + public @interface PolicyDirection {} + + /** * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. * * <p>No IPsec packet may contain an SPI of 0. @@ -125,7 +145,7 @@ public final class IpSecManager { */ public static final class SecurityParameterIndex implements AutoCloseable { private final IIpSecService mService; - private final InetAddress mRemoteAddress; + private final InetAddress mDestinationAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; private int mResourceId = INVALID_RESOURCE_ID; @@ -164,14 +184,14 @@ public final class IpSecManager { } private SecurityParameterIndex( - @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi) + @NonNull IIpSecService service, InetAddress destinationAddress, int spi) throws ResourceUnavailableException, SpiUnavailableException { mService = service; - mRemoteAddress = remoteAddress; + mDestinationAddress = destinationAddress; try { IpSecSpiResponse result = mService.allocateSecurityParameterIndex( - direction, remoteAddress.getHostAddress(), spi, new Binder()); + destinationAddress.getHostAddress(), spi, new Binder()); if (result == null) { throw new NullPointerException("Received null response from IpSecService"); @@ -216,25 +236,23 @@ public final class IpSecManager { } /** - * Reserve a random SPI for traffic bound to or from the specified remote address. + * Reserve a random SPI for traffic bound to or from the specified destination address. * * <p>If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * - * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress + * @param destinationAddress the destination address for traffic bearing the requested SPI. + * For inbound traffic, the destination should be an address currently assigned on-device. * @return the reserved SecurityParameterIndex - * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated - * for this user - * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved + * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * currently allocated for this user */ - public SecurityParameterIndex allocateSecurityParameterIndex( - int direction, InetAddress remoteAddress) throws ResourceUnavailableException { + public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress) + throws ResourceUnavailableException { try { return new SecurityParameterIndex( mService, - direction, - remoteAddress, + destinationAddress, IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); } catch (SpiUnavailableException unlikely) { throw new ResourceUnavailableException("No SPIs available"); @@ -242,26 +260,27 @@ public final class IpSecManager { } /** - * Reserve the requested SPI for traffic bound to or from the specified remote address. + * Reserve the requested SPI for traffic bound to or from the specified destination address. * * <p>If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * - * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress + * @param destinationAddress the destination address for traffic bearing the requested SPI. + * For inbound traffic, the destination should be an address currently assigned on-device. * @param requestedSpi the requested SPI, or '0' to allocate a random SPI * @return the reserved SecurityParameterIndex - * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated - * for this user - * @throws SpiUnavailableException indicating that the requested SPI could not be reserved + * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * currently allocated for this user + * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be + * reserved */ public SecurityParameterIndex allocateSecurityParameterIndex( - int direction, InetAddress remoteAddress, int requestedSpi) + InetAddress destinationAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); } - return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi); + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); } /** @@ -269,14 +288,14 @@ public final class IpSecManager { * * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * * <p>For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * * <h4>Rekey Procedure</h4> * @@ -287,15 +306,14 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a stream socket + * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied - * @hide */ - public void applyTransportModeTransform(Socket socket, IpSecTransform transform) + public void applyTransportModeTransform( + Socket socket, int direction, IpSecTransform transform) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - applyTransportModeTransform(pfd, transform); - } + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } /** @@ -303,14 +321,14 @@ public final class IpSecManager { * * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * * <p>For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * * <h4>Rekey Procedure</h4> * @@ -321,15 +339,13 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a datagram socket + * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied - * @hide */ - public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) - throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - applyTransportModeTransform(pfd, transform); - } + public void applyTransportModeTransform( + DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } /** @@ -337,14 +353,14 @@ public final class IpSecManager { * * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * * <p>For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * * <h4>Rekey Procedure</h4> * @@ -355,24 +371,17 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a socket file descriptor + * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) + public void applyTransportModeTransform( + FileDescriptor socket, int direction, IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() - // constructor takes control and closes the user's FD when we exit the method - // This is behaviorally the same as the other versions, but the PFD constructor does not - // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). + // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - applyTransportModeTransform(pfd, transform); - } - } - - /* Call down to activate a transform */ - private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { - try { - mService.applyTransportModeTransform(pfd, transform.getResourceId()); + mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -396,75 +405,56 @@ public final class IpSecManager { /** * Remove an IPsec transform from a stream socket. * - * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket - * @hide */ - public void removeTransportModeTransform(Socket socket, IpSecTransform transform) + public void removeTransportModeTransforms(Socket socket) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - removeTransportModeTransform(pfd, transform); - } + removeTransportModeTransforms(socket.getFileDescriptor$()); } /** * Remove an IPsec transform from a datagram socket. * - * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket - * @hide */ - public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) + public void removeTransportModeTransforms(DatagramSocket socket) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - removeTransportModeTransform(pfd, transform); - } + removeTransportModeTransforms(socket.getFileDescriptor$()); } /** * Remove an IPsec transform from a socket. * - * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) + public void removeTransportModeTransforms(FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - removeTransportModeTransform(pfd, transform); - } - } - - /* Call down to remove a transform */ - private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { - try { - mService.removeTransportModeTransform(pfd, transform.getResourceId()); + mService.removeTransportModeTransforms(pfd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 102ba6d94faa..7b9b4830929d 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -38,13 +38,11 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; /** - * This class represents an IPsec transform, which comprises security associations in one or both - * directions. + * This class represents a transform, which roughly corresponds to an IPsec Security Association. * * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform} - * object encapsulates the properties and state of an inbound and outbound IPsec security - * association. That includes, but is not limited to, algorithm choice, key material, and allocated - * system resources. + * object encapsulates the properties and state of an IPsec security association. That includes, + * but is not limited to, algorithm choice, key material, and allocated system resources. * * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the * Internet Protocol</a> @@ -52,23 +50,6 @@ import java.net.InetAddress; public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; - /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic towards the host. - */ - public static final int DIRECTION_IN = 0; - - /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic from the host. - */ - public static final int DIRECTION_OUT = 1; - - /** @hide */ - @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) - @Retention(RetentionPolicy.SOURCE) - public @interface TransformDirection {} - /** @hide */ public static final int MODE_TRANSPORT = 0; @@ -170,7 +151,7 @@ public final class IpSecTransform implements AutoCloseable { * * <p>Deactivating a transform while it is still applied to a socket will result in errors on * that socket. Make sure to remove transforms by calling {@link - * IpSecManager#removeTransportModeTransform}. Note, removing an {@code IpSecTransform} from a + * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a * socket will not deactivate it (because one transform may be applied to multiple sockets). * * <p>It is safe to call this method on a transform that has already been deactivated. @@ -272,85 +253,49 @@ public final class IpSecTransform implements AutoCloseable { private IpSecConfig mConfig; /** - * Set the encryption algorithm for the given direction. - * - * <p>If encryption is set for a direction without also providing an SPI for that direction, - * creation of an {@code IpSecTransform} will fail when attempting to build the transform. + * Set the encryption algorithm. * * <p>Encryption is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ - public IpSecTransform.Builder setEncryption( - @TransformDirection int direction, IpSecAlgorithm algo) { + public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. - mConfig.setEncryption(direction, algo); + Preconditions.checkNotNull(algo); + mConfig.setEncryption(algo); return this; } /** - * Set the authentication (integrity) algorithm for the given direction. - * - * <p>If authentication is set for a direction without also providing an SPI for that - * direction, creation of an {@code IpSecTransform} will fail when attempting to build the - * transform. + * Set the authentication (integrity) algorithm. * * <p>Authentication is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ - public IpSecTransform.Builder setAuthentication( - @TransformDirection int direction, IpSecAlgorithm algo) { + public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. - mConfig.setAuthentication(direction, algo); + Preconditions.checkNotNull(algo); + mConfig.setAuthentication(algo); return this; } /** - * Set the authenticated encryption algorithm for the given direction. - * - * <p>If an authenticated encryption algorithm is set for a given direction without also - * providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when - * attempting to build the transform. + * Set the authenticated encryption algorithm. * - * <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated - * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as - * referred to in <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>). + * <p>The Authenticated Encryption (AE) class of algorithms are also known as + * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode + * algorithms (as referred to in + * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>). * * <p>Authenticated encryption is mutually exclusive with encryption and authentication. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ - public IpSecTransform.Builder setAuthenticatedEncryption( - @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.setAuthenticatedEncryption(direction, algo); - return this; - } - - /** - * Set the SPI for the given direction. - * - * <p>Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies - * packets to a given destination address. To prevent SPI collisions, values should be - * reserved by calling {@link IpSecManager#allocateSecurityParameterIndex}. - * - * <p>If the SPI and algorithms are omitted for one direction, traffic in that direction - * will not be encrypted or authenticated. - * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} - * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed - * traffic - */ - public IpSecTransform.Builder setSpi( - @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { - if (spi.getResourceId() == INVALID_RESOURCE_ID) { - throw new IllegalArgumentException("Invalid SecurityParameterIndex"); - } - mConfig.setSpiResourceId(direction, spi.getResourceId()); + public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { + Preconditions.checkNotNull(algo); + mConfig.setAuthenticatedEncryption(algo); return this; } @@ -363,7 +308,8 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi - public IpSecTransform.Builder setUnderlyingNetwork(Network net) { + public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) { + Preconditions.checkNotNull(net); mConfig.setNetwork(net); return this; } @@ -382,7 +328,8 @@ public final class IpSecTransform implements AutoCloseable { * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ public IpSecTransform.Builder setIpv4Encapsulation( - IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { + @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { + Preconditions.checkNotNull(localSocket); mConfig.setEncapType(ENCAP_ESPINUDP); if (localSocket.getResourceId() == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Invalid UdpEncapsulationSocket"); @@ -419,24 +366,33 @@ public final class IpSecTransform implements AutoCloseable { * will not affect any network traffic until it has been applied to one or more sockets. * * @see IpSecManager#applyTransportModeTransform - * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use - * this transform + * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use + * this transform; this address must belong to the Network used by all sockets that + * utilize this transform; if provided, then only traffic originating from the + * specified source address will be processed. + * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed + * traffic * @throws IllegalArgumentException indicating that a particular combination of transform * properties is invalid - * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are - * active + * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms + * are active * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI * collides with an existing transform * @throws IOException indicating other errors */ - public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) + public IpSecTransform buildTransportModeTransform( + @NonNull InetAddress sourceAddress, + @NonNull IpSecManager.SecurityParameterIndex spi) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { - if (remoteAddress == null) { - throw new IllegalArgumentException("Remote address may not be null or empty!"); + Preconditions.checkNotNull(sourceAddress); + Preconditions.checkNotNull(spi); + if (spi.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } mConfig.setMode(MODE_TRANSPORT); - mConfig.setRemoteAddress(remoteAddress.getHostAddress()); + mConfig.setSourceAddress(sourceAddress.getHostAddress()); + mConfig.setSpiResourceId(spi.getResourceId()); // FIXME: modifying a builder after calling build can change the built transform. return new IpSecTransform(mContext, mConfig).activate(); } @@ -445,26 +401,33 @@ public final class IpSecTransform implements AutoCloseable { * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some * parameters have interdependencies that are checked at build time. * - * @param localAddress the {@link InetAddress} that provides the local endpoint for this + * @param sourceAddress the {@link InetAddress} that provides the source address for this * IPsec tunnel. This is almost certainly an address belonging to the {@link Network} * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}. - * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this - * IPsec tunnel. + * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed + * traffic * @throws IllegalArgumentException indicating that a particular combination of transform * properties is invalid. + * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms + * are active + * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI + * collides with an existing transform + * @throws IOException indicating other errors * @hide */ public IpSecTransform buildTunnelModeTransform( - InetAddress localAddress, InetAddress remoteAddress) { - if (localAddress == null) { - throw new IllegalArgumentException("Local address may not be null or empty!"); - } - if (remoteAddress == null) { - throw new IllegalArgumentException("Remote address may not be null or empty!"); + @NonNull InetAddress sourceAddress, + @NonNull IpSecManager.SecurityParameterIndex spi) + throws IpSecManager.ResourceUnavailableException, + IpSecManager.SpiUnavailableException, IOException { + Preconditions.checkNotNull(sourceAddress); + Preconditions.checkNotNull(spi); + if (spi.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } - mConfig.setLocalAddress(localAddress.getHostAddress()); - mConfig.setRemoteAddress(remoteAddress.getHostAddress()); mConfig.setMode(MODE_TUNNEL); + mConfig.setSourceAddress(sourceAddress.getHostAddress()); + mConfig.setSpiResourceId(spi.getResourceId()); return new IpSecTransform(mContext, mConfig); } diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index d6992aaede5f..287bdc88dd3e 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.IntDef; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -60,7 +61,7 @@ public final class MacAddress implements Parcelable { }) public @interface MacAddressType { } - /** Indicates a MAC address of unknown type. */ + /** @hide Indicates a MAC address of unknown type. */ public static final int TYPE_UNKNOWN = 0; /** Indicates a MAC address is a unicast address. */ public static final int TYPE_UNICAST = 1; @@ -92,7 +93,7 @@ public final class MacAddress implements Parcelable { * * @return the int constant representing the MAC address type of this MacAddress. */ - public @MacAddressType int addressType() { + public @MacAddressType int getAddressType() { if (equals(BROADCAST_ADDRESS)) { return TYPE_BROADCAST; } @@ -120,12 +121,12 @@ public final class MacAddress implements Parcelable { /** * @return a byte array representation of this MacAddress. */ - public byte[] toByteArray() { + public @NonNull byte[] toByteArray() { return byteAddrFromLongAddr(mAddr); } @Override - public String toString() { + public @NonNull String toString() { return stringAddrFromLongAddr(mAddr); } @@ -133,7 +134,7 @@ public final class MacAddress implements Parcelable { * @return a String representation of the OUI part of this MacAddress made of 3 hexadecimal * numbers in [0,ff] joined by ':' characters. */ - public String toOuiString() { + public @NonNull String toOuiString() { return String.format( "%02x:%02x:%02x", (mAddr >> 40) & 0xff, (mAddr >> 32) & 0xff, (mAddr >> 24) & 0xff); } @@ -197,7 +198,7 @@ public final class MacAddress implements Parcelable { if (!isMacAddress(addr)) { return TYPE_UNKNOWN; } - return MacAddress.fromBytes(addr).addressType(); + return MacAddress.fromBytes(addr).getAddressType(); } /** @@ -211,7 +212,7 @@ public final class MacAddress implements Parcelable { * * @hide */ - public static byte[] byteAddrFromStringAddr(String addr) { + public static @NonNull byte[] byteAddrFromStringAddr(String addr) { Preconditions.checkNotNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { @@ -239,7 +240,7 @@ public final class MacAddress implements Parcelable { * * @hide */ - public static String stringAddrFromByteAddr(byte[] addr) { + public static @NonNull String stringAddrFromByteAddr(byte[] addr) { if (!isMacAddress(addr)) { return null; } @@ -291,7 +292,7 @@ public final class MacAddress implements Parcelable { // Internal conversion function equivalent to stringAddrFromByteAddr(byteAddrFromLongAddr(addr)) // that avoids the allocation of an intermediary byte[]. - private static String stringAddrFromLongAddr(long addr) { + private static @NonNull String stringAddrFromLongAddr(long addr) { return String.format("%02x:%02x:%02x:%02x:%02x:%02x", (addr >> 40) & 0xff, (addr >> 32) & 0xff, @@ -310,7 +311,7 @@ public final class MacAddress implements Parcelable { * @return the MacAddress corresponding to the given String representation. * @throws IllegalArgumentException if the given String is not a valid representation. */ - public static MacAddress fromString(String addr) { + public static @NonNull MacAddress fromString(@NonNull String addr) { return new MacAddress(longAddrFromStringAddr(addr)); } @@ -322,7 +323,7 @@ public final class MacAddress implements Parcelable { * @return the MacAddress corresponding to the given byte array representation. * @throws IllegalArgumentException if the given byte array is not a valid representation. */ - public static MacAddress fromBytes(byte[] addr) { + public static @NonNull MacAddress fromBytes(@NonNull byte[] addr) { return new MacAddress(longAddrFromByteAddr(addr)); } @@ -336,7 +337,7 @@ public final class MacAddress implements Parcelable { * * @hide */ - public static MacAddress createRandomUnicastAddress() { + public static @NonNull MacAddress createRandomUnicastAddress() { return createRandomUnicastAddress(BASE_GOOGLE_MAC, new Random()); } @@ -352,7 +353,7 @@ public final class MacAddress implements Parcelable { * * @hide */ - public static MacAddress createRandomUnicastAddress(MacAddress base, Random r) { + public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) { long addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong()); addr = addr | LOCALLY_ASSIGNED_MASK; addr = addr & ~MULTICAST_MASK; diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 903b602b42f8..3683d3450b41 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -356,13 +356,13 @@ public class Network implements Parcelable { // Multiple Provisioning Domains API recommendations, as made by the // IETF mif working group. // - // The HANDLE_MAGIC value MUST be kept in sync with the corresponding + // The handleMagic value MUST be kept in sync with the corresponding // value in the native/android/net.c NDK implementation. if (netId == 0) { return 0L; // make this zero condition obvious for debugging } - final long HANDLE_MAGIC = 0xfacade; - return (((long) netId) << 32) | HANDLE_MAGIC; + final long handleMagic = 0xcafed00dL; + return (((long) netId) << 32) | handleMagic; } // implement the Parcelable interface diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java index 7277ba34534b..bb36536fe2ce 100644 --- a/core/java/android/net/metrics/WakeupStats.java +++ b/core/java/android/net/metrics/WakeupStats.java @@ -80,7 +80,7 @@ public class WakeupStats { break; } - switch (ev.dstHwAddr.addressType()) { + switch (ev.dstHwAddr.getAddressType()) { case MacAddress.TYPE_UNICAST: l2UnicastCount++; break; diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 340f3fb8cd25..12a495bf2821 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -76,8 +76,8 @@ public class VintfObject { /** * @return a list of VNDK snapshots supported by the framework, as * specified in framework manifest. For example, - * [("25.0.5", ["libjpeg.so", "libbase.so"]), - * ("25.1.3", ["libjpeg.so", "libbase.so"])] + * [("27", ["libjpeg.so", "libbase.so"]), + * ("28", ["libjpeg.so", "libbase.so"])] */ public static native Map<String, String[]> getVndkSnapshots(); } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 3ee8b472869b..9167076474ff 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -69,6 +69,9 @@ public final class Zygote { private Zygote() {} + /** Called for some security initialization before any fork. */ + native static void nativeSecurityInit(); + /** * Forks a new VM instance. The current VM must have been started * with the -Xzygote flag. <b>NOTE: new instance keeps all diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 2be6212b9f1e..21f1fb652794 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -30,7 +30,6 @@ import android.os.IInstalld; import android.os.Environment; import android.os.Process; import android.os.RemoteException; -import android.os.Seccomp; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.SystemClock; @@ -572,10 +571,12 @@ public class ZygoteInit { final String seInfo = null; final String classLoaderContext = getSystemServerClassLoaderContext(classPathForElement); + final int targetSdkVersion = 0; // SystemServer targets the system's SDK version try { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, - uuid, classLoaderContext, seInfo, false /* downgrade */); + uuid, classLoaderContext, seInfo, false /* downgrade */, + targetSdkVersion); } catch (RemoteException | ServiceSpecificException e) { // Ignore (but log), we need this on the classpath for fallback mode. Log.w(TAG, "Failed compiling classpath element for system server: " @@ -779,12 +780,11 @@ public class ZygoteInit { // Zygote. Trace.setTracingEnabled(false, 0); + Zygote.nativeSecurityInit(); + // Zygote process unmounts root storage spaces. Zygote.nativeUnmountStorageOnInit(); - // Set seccomp policy - Seccomp.setPolicy(); - ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 551d54ab9053..bc98716ebc9c 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -86,7 +86,6 @@ cc_library_shared { "android_os_MessageQueue.cpp", "android_os_Parcel.cpp", "android_os_SELinux.cpp", - "android_os_seccomp.cpp", "android_os_SharedMemory.cpp", "android_os_SystemClock.cpp", "android_os_SystemProperties.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 047fa8489453..35ab56a1a456 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -163,7 +163,6 @@ extern int register_android_os_Parcel(JNIEnv* env); extern int register_android_os_SELinux(JNIEnv* env); extern int register_android_os_VintfObject(JNIEnv *env); extern int register_android_os_VintfRuntimeInfo(JNIEnv *env); -extern int register_android_os_seccomp(JNIEnv* env); extern int register_android_os_SystemProperties(JNIEnv *env); extern int register_android_os_SystemClock(JNIEnv* env); extern int register_android_os_Trace(JNIEnv* env); @@ -1420,7 +1419,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_GraphicsEnvironment), REG_JNI(register_android_os_MessageQueue), REG_JNI(register_android_os_SELinux), - REG_JNI(register_android_os_seccomp), REG_JNI(register_android_os_Trace), REG_JNI(register_android_os_UEventObserver), REG_JNI(register_android_net_LocalSocketImpl), diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 1eeea517cd78..16591685848e 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -146,8 +146,8 @@ static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) { return nullptr; } jobject jMap = env->NewObject(gHashMapClazz, gHashMapInit); - for (const Vndk &vndk : manifest->vndks()) { - std::string key = to_string(vndk.versionRange()); + for (const auto &vndk : manifest->vendorNdks()) { + std::string key = vndk.version(); env->CallObjectMethod(jMap, gHashMapPut, env->NewStringUTF(key.c_str()), toJavaStringArray(env, vndk.libraries())); } diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp deleted file mode 100644 index 06e2a167de0a..000000000000 --- a/core/jni/android_os_seccomp.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core_jni_helpers.h" -#include <nativehelper/JniConstants.h> -#include "utils/Log.h" -#include <selinux/selinux.h> - -#include "seccomp_policy.h" - -static void Seccomp_setPolicy(JNIEnv* /*env*/) { - if (security_getenforce() == 0) { - ALOGI("seccomp disabled by setenforce 0"); - return; - } - - if (!set_seccomp_filter()) { - ALOGE("Failed to set seccomp policy - killing"); - exit(1); - } -} - -static const JNINativeMethod method_table[] = { - NATIVE_METHOD(Seccomp, setPolicy, "()V"), -}; - -namespace android { - -int register_android_os_seccomp(JNIEnv* env) { - return android::RegisterMethodsOrDie(env, "android/os/Seccomp", - method_table, NELEM(method_table)); -} - -} diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 32ef3dc0aed4..63dba43a5eb3 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -53,6 +53,7 @@ #include <private/android_filesystem_config.h> #include <utils/String8.h> #include <selinux/android.h> +#include <seccomp_policy.h> #include <processgroup/processgroup.h> #include "core_jni_helpers.h" @@ -76,6 +77,8 @@ static const char kZygoteClassName[] = "com/android/internal/os/Zygote"; static jclass gZygoteClass; static jmethodID gCallPostForkChildHooks; +static bool g_is_security_enforced = true; + // Must match values in com.android.internal.os.Zygote. enum MountExternalKind { MOUNT_EXTERNAL_NONE = 0, @@ -229,6 +232,20 @@ static void PreApplicationInit() { mallopt(M_DECAY_TIME, 1); } +static void SetUpSeccompFilter(uid_t uid) { + if (!g_is_security_enforced) { + ALOGI("seccomp disabled by setenforce 0"); + return; + } + + // Apply system or app filter based on uid. + if (getuid() >= AID_APP_START) { + set_app_seccomp_filter(); + } else { + set_system_seccomp_filter(); + } +} + static void EnableKeepCapabilities(JNIEnv* env) { int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); if (rc == -1) { @@ -541,6 +558,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); } + // Must be called when the new process still has CAP_SYS_ADMIN. The other alternative is to + // call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see + // b/71859146). + SetUpSeccompFilter(uid); + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(env); @@ -698,6 +720,12 @@ static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { namespace android { +static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) { + // security_getenforce is not allowed on app process. Initialize and cache the value before + // zygote forks. + g_is_security_enforced = security_getenforce(); +} + static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) { PreApplicationInit(); } @@ -832,6 +860,8 @@ static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* en } static const JNINativeMethod gMethods[] = { + { "nativeSecurityInit", "()V", + (void *) com_android_internal_os_Zygote_nativeSecurityInit }, { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I", (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 7c6046789cdc..e3af65532f85 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -551,18 +551,20 @@ bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) { } // Animate spots that are fading out and being removed. - for (size_t i = 0; i < mLocked.spots.size(); i++) { + for (size_t i = 0; i < mLocked.spots.size();) { Spot* spot = mLocked.spots.itemAt(i); if (spot->id == Spot::INVALID_ID) { spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; if (spot->alpha <= 0) { - mLocked.spots.removeAt(i--); + mLocked.spots.removeAt(i); releaseSpotLocked(spot); + continue; } else { spot->sprite->setAlpha(spot->alpha); keepAnimating = true; } } + ++i; } return keepAnimating; } diff --git a/native/android/net.c b/native/android/net.c index de4b90cc1956..60296a7bd00c 100644 --- a/native/android/net.c +++ b/native/android/net.c @@ -27,7 +27,7 @@ static int getnetidfromhandle(net_handle_t handle, unsigned *netid) { static const uint32_t k32BitMask = 0xffffffff; // This value MUST be kept in sync with the corresponding value in // the android.net.Network#getNetworkHandle() implementation. - static const uint32_t kHandleMagic = 0xfacade; + static const uint32_t kHandleMagic = 0xcafed00d; // Check for minimum acceptable version of the API in the low bits. if (handle != NETWORK_UNSPECIFIED && diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index d9713a517a94..337406d58f9d 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -60,6 +60,7 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import com.android.internal.R; import com.android.internal.util.DumpUtils; import com.android.server.pm.UserRestrictionsUtils; @@ -415,9 +416,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int systemUiUid = -1; try { - systemUiUid = mContext.getPackageManager() - .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, - UserHandle.USER_SYSTEM); + // Check if device is configured with no home screen, which implies no SystemUI. + boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen); + if (!noHome) { + systemUiUid = mContext.getPackageManager() + .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, + UserHandle.USER_SYSTEM); + } + Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid)); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f34730c084fc..ed1e0113b5c3 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -225,7 +225,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>(); + // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by + // a direct call to LockdownVpnTracker.isEnabled(). + @GuardedBy("mVpns") private boolean mLockdownEnabled; + @GuardedBy("mVpns") private LockdownVpnTracker mLockdownTracker; final private Context mContext; @@ -974,9 +978,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } private Network[] getVpnUnderlyingNetworks(int uid) { - if (!mLockdownEnabled) { - int user = UserHandle.getUserId(uid); - synchronized (mVpns) { + synchronized (mVpns) { + if (!mLockdownEnabled) { + int user = UserHandle.getUserId(uid); Vpn vpn = mVpns.get(user); if (vpn != null && vpn.appliesToUid(uid)) { return vpn.getUnderlyingNetworks(); @@ -1064,8 +1068,10 @@ public class ConnectivityService extends IConnectivityManager.Stub if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) { state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); } - if (mLockdownTracker != null) { - mLockdownTracker.augmentNetworkInfo(state.networkInfo); + synchronized (mVpns) { + if (mLockdownTracker != null) { + mLockdownTracker.augmentNetworkInfo(state.networkInfo); + } } } @@ -1230,8 +1236,8 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put(nai.network, nc); } - if (!mLockdownEnabled) { - synchronized (mVpns) { + synchronized (mVpns) { + if (!mLockdownEnabled) { Vpn vpn = mVpns.get(userId); if (vpn != null) { Network[] networks = vpn.getUnderlyingNetworks(); @@ -1557,9 +1563,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } private Intent makeGeneralIntent(NetworkInfo info, String bcastType) { - if (mLockdownTracker != null) { - info = new NetworkInfo(info); - mLockdownTracker.augmentNetworkInfo(info); + synchronized (mVpns) { + if (mLockdownTracker != null) { + info = new NetworkInfo(info); + mLockdownTracker.augmentNetworkInfo(info); + } } Intent intent = new Intent(bcastType); @@ -2472,6 +2480,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) { nri.unlinkDeathRecipient(); mNetworkRequests.remove(nri.request); + synchronized (mUidToNetworkRequestCount) { int requests = mUidToNetworkRequestCount.get(nri.mUid, 0); if (requests < 1) { @@ -2484,6 +2493,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUidToNetworkRequestCount.put(nri.mUid, requests - 1); } } + mNetworkRequestInfoLogs.log("RELEASE " + nri); if (nri.request.isRequest()) { boolean wasKept = false; @@ -3406,9 +3416,9 @@ public class ConnectivityService extends IConnectivityManager.Stub public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, int userId) { enforceCrossUserPermission(userId); - throwIfLockdownEnabled(); synchronized (mVpns) { + throwIfLockdownEnabled(); Vpn vpn = mVpns.get(userId); if (vpn != null) { return vpn.prepare(oldPackage, newPackage); @@ -3452,9 +3462,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public ParcelFileDescriptor establishVpn(VpnConfig config) { - throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { + throwIfLockdownEnabled(); return mVpns.get(user).establish(config); } } @@ -3465,13 +3475,13 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void startLegacyVpn(VpnProfile profile) { - throwIfLockdownEnabled(); + int user = UserHandle.getUserId(Binder.getCallingUid()); final LinkProperties egress = getActiveLinkProperties(); if (egress == null) { throw new IllegalStateException("Missing active network connection"); } - int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { + throwIfLockdownEnabled(); mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress); } } @@ -3497,11 +3507,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public VpnInfo[] getAllVpnInfo() { enforceConnectivityInternalPermission(); - if (mLockdownEnabled) { - return new VpnInfo[0]; - } - synchronized (mVpns) { + if (mLockdownEnabled) { + return new VpnInfo[0]; + } + List<VpnInfo> infoList = new ArrayList<>(); for (int i = 0; i < mVpns.size(); i++) { VpnInfo info = createVpnInfo(mVpns.valueAt(i)); @@ -3566,33 +3576,33 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - // Tear down existing lockdown if profile was removed - mLockdownEnabled = LockdownVpnTracker.isEnabled(); - if (mLockdownEnabled) { - byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN); - if (profileTag == null) { - Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore"); - return false; - } - String profileName = new String(profileTag); - final VpnProfile profile = VpnProfile.decode( - profileName, mKeyStore.get(Credentials.VPN + profileName)); - if (profile == null) { - Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName); - setLockdownTracker(null); - return true; - } - int user = UserHandle.getUserId(Binder.getCallingUid()); - synchronized (mVpns) { + synchronized (mVpns) { + // Tear down existing lockdown if profile was removed + mLockdownEnabled = LockdownVpnTracker.isEnabled(); + if (mLockdownEnabled) { + byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN); + if (profileTag == null) { + Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore"); + return false; + } + String profileName = new String(profileTag); + final VpnProfile profile = VpnProfile.decode( + profileName, mKeyStore.get(Credentials.VPN + profileName)); + if (profile == null) { + Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName); + setLockdownTracker(null); + return true; + } + int user = UserHandle.getUserId(Binder.getCallingUid()); Vpn vpn = mVpns.get(user); if (vpn == null) { Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown"); return false; } setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile)); + } else { + setLockdownTracker(null); } - } else { - setLockdownTracker(null); } return true; @@ -3602,6 +3612,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * Internally set new {@link LockdownVpnTracker}, shutting down any existing * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown. */ + @GuardedBy("mVpns") private void setLockdownTracker(LockdownVpnTracker tracker) { // Shutdown any existing tracker final LockdownVpnTracker existing = mLockdownTracker; @@ -3616,6 +3627,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + @GuardedBy("mVpns") private void throwIfLockdownEnabled() { if (mLockdownEnabled) { throw new IllegalStateException("Unavailable in lockdown mode"); @@ -3663,12 +3675,12 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceConnectivityInternalPermission(); enforceCrossUserPermission(userId); - // Can't set always-on VPN if legacy VPN is already in lockdown mode. - if (LockdownVpnTracker.isEnabled()) { - return false; - } - synchronized (mVpns) { + // Can't set always-on VPN if legacy VPN is already in lockdown mode. + if (LockdownVpnTracker.isEnabled()) { + return false; + } + Vpn vpn = mVpns.get(userId); if (vpn == null) { Slog.w(TAG, "User " + userId + " has no Vpn configuration"); @@ -3844,9 +3856,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId); mVpns.put(userId, userVpn); - } - if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { - updateLockdownVpn(); + if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { + updateLockdownVpn(); + } } } @@ -3883,11 +3895,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void onUserUnlocked(int userId) { - // User present may be sent because of an unlock, which might mean an unlocked keystore. - if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { - updateLockdownVpn(); - } else { - startAlwaysOnVpn(userId); + synchronized (mVpns) { + // User present may be sent because of an unlock, which might mean an unlocked keystore. + if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { + updateLockdownVpn(); + } else { + startAlwaysOnVpn(userId); + } } } @@ -4567,51 +4581,67 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities} - * augmented with any stateful capabilities implied from {@code networkAgent} - * (e.g., validated status and captive portal status). - * - * @param oldScore score of the network before any of the changes that prompted us - * to call this function. - * @param nai the network having its capabilities updated. - * @param networkCapabilities the new network capabilities. + * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are + * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal, + * and foreground status). */ - private void updateCapabilities( - int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) { + private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) { // Once a NetworkAgent is connected, complain if some immutable capabilities are removed. - if (nai.everConnected && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities( - networkCapabilities)) { - // TODO: consider not complaining when a network agent degrade its capabilities if this + if (nai.everConnected && + !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) { + // TODO: consider not complaining when a network agent degrades its capabilities if this // does not cause any request (that is not a listen) currently matching that agent to // stop being matched by the updated agent. - String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities); + String diff = nai.networkCapabilities.describeImmutableDifferences(nc); if (!TextUtils.isEmpty(diff)) { Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff); } } // Don't modify caller's NetworkCapabilities. - networkCapabilities = new NetworkCapabilities(networkCapabilities); + NetworkCapabilities newNc = new NetworkCapabilities(nc); if (nai.lastValidated) { - networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED); + newNc.addCapability(NET_CAPABILITY_VALIDATED); } else { - networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED); + newNc.removeCapability(NET_CAPABILITY_VALIDATED); } if (nai.lastCaptivePortalDetected) { - networkCapabilities.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); + newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); } else { - networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL); + newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL); } if (nai.isBackgroundNetwork()) { - networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND); + newNc.removeCapability(NET_CAPABILITY_FOREGROUND); } else { - networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); + newNc.addCapability(NET_CAPABILITY_FOREGROUND); } - if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return; + return newNc; + } + + /** + * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically: + * + * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the + * capabilities we manage and store in {@code nai}, such as validated status and captive + * portal status) + * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and + * potentially triggers rematches. + * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the + * change.) + * + * @param oldScore score of the network before any of the changes that prompted us + * to call this function. + * @param nai the network having its capabilities updated. + * @param nc the new network capabilities. + */ + private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) { + NetworkCapabilities newNc = mixInCapabilities(nai, nc); + + if (Objects.equals(nai.networkCapabilities, newNc)) return; final String oldPermission = getNetworkPermission(nai.networkCapabilities); - final String newPermission = getNetworkPermission(networkCapabilities); + final String newPermission = getNetworkPermission(newNc); if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) { try { mNetd.setNetworkPermission(nai.network.netId, newPermission); @@ -4623,11 +4653,10 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkCapabilities prevNc; synchronized (nai) { prevNc = nai.networkCapabilities; - nai.networkCapabilities = networkCapabilities; + nai.networkCapabilities = newNc; } - if (nai.getCurrentScore() == oldScore && - networkCapabilities.equalRequestableCapabilities(prevNc)) { + if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) { // If the requestable capabilities haven't changed, and the score hasn't changed, then // the change we're processing can't affect any requests, it can only affect the listens // on this network. We might have been called by rematchNetworkAndRequests when a @@ -4643,15 +4672,15 @@ public class ConnectivityService extends IConnectivityManager.Stub // Report changes that are interesting for network statistics tracking. if (prevNc != null) { final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) != - networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED); + newNc.hasCapability(NET_CAPABILITY_NOT_METERED); final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) != - networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING); + newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); if (meteredChanged || roamingChanged) { notifyIfacesChangedForNetworkStats(); } } - if (!networkCapabilities.hasTransport(TRANSPORT_VPN)) { + if (!newNc.hasTransport(TRANSPORT_VPN)) { // Tell VPNs about updated capabilities, since they may need to // bubble those changes through. synchronized (mVpns) { @@ -5175,11 +5204,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void notifyLockdownVpn(NetworkAgentInfo nai) { - if (mLockdownTracker != null) { - if (nai != null && nai.isVPN()) { - mLockdownTracker.onVpnStateChanged(nai.networkInfo); - } else { - mLockdownTracker.onNetworkInfoChanged(); + synchronized (mVpns) { + if (mLockdownTracker != null) { + if (nai != null && nai.isVPN()) { + mLockdownTracker.onVpnStateChanged(nai.networkInfo); + } else { + mLockdownTracker.onNetworkInfoChanged(); + } } } } @@ -5409,28 +5440,28 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean addVpnAddress(String address, int prefixLength) { - throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { + throwIfLockdownEnabled(); return mVpns.get(user).addAddress(address, prefixLength); } } @Override public boolean removeVpnAddress(String address, int prefixLength) { - throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { + throwIfLockdownEnabled(); return mVpns.get(user).removeAddress(address, prefixLength); } } @Override public boolean setUnderlyingNetworksForVpn(Network[] networks) { - throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); - boolean success; + final boolean success; synchronized (mVpns) { + throwIfLockdownEnabled(); success = mVpns.get(user).setUnderlyingNetworks(networks); } if (success) { @@ -5490,31 +5521,31 @@ public class ConnectivityService extends IConnectivityManager.Stub setAlwaysOnVpnPackage(userId, null, false); setVpnPackageAuthorization(alwaysOnPackage, userId, false); } - } - // Turn Always-on VPN off - if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { - final long ident = Binder.clearCallingIdentity(); - try { - mKeyStore.delete(Credentials.LOCKDOWN_VPN); - mLockdownEnabled = false; - setLockdownTracker(null); - } finally { - Binder.restoreCallingIdentity(ident); + // Turn Always-on VPN off + if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { + final long ident = Binder.clearCallingIdentity(); + try { + mKeyStore.delete(Credentials.LOCKDOWN_VPN); + mLockdownEnabled = false; + setLockdownTracker(null); + } finally { + Binder.restoreCallingIdentity(ident); + } } - } - // Turn VPN off - VpnConfig vpnConfig = getVpnConfig(userId); - if (vpnConfig != null) { - if (vpnConfig.legacy) { - prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); - } else { - // Prevent this app (packagename = vpnConfig.user) from initiating VPN connections - // in the future without user intervention. - setVpnPackageAuthorization(vpnConfig.user, userId, false); + // Turn VPN off + VpnConfig vpnConfig = getVpnConfig(userId); + if (vpnConfig != null) { + if (vpnConfig.legacy) { + prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); + } else { + // Prevent this app (packagename = vpnConfig.user) from initiating + // VPN connections in the future without user intervention. + setVpnPackageAuthorization(vpnConfig.user, userId, false); - prepareVpn(null, VpnConfig.LEGACY_VPN, userId); + prepareVpn(null, VpnConfig.LEGACY_VPN, userId); + } } } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 02cfe3dc75e5..46a35ec800ba 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -25,6 +25,7 @@ import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.content.Context; +import android.net.ConnectivityManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -62,7 +63,6 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; @@ -83,7 +83,7 @@ public class IpSecService extends IIpSecService.Stub { private static final String NETD_SERVICE_NAME = "netd"; private static final int[] DIRECTIONS = - new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}; + new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms private static final int MAX_PORT_BIND_ATTEMPTS = 10; @@ -104,10 +104,10 @@ public class IpSecService extends IIpSecService.Stub { private final Context mContext; /** - * The next non-repeating global ID for tracking resources between users, this service, - * and kernel data structures. Accessing this variable is not thread safe, so it is - * only read or modified within blocks synchronized on IpSecService.this. We want to - * avoid -1 (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it). + * The next non-repeating global ID for tracking resources between users, this service, and + * kernel data structures. Accessing this variable is not thread safe, so it is only read or + * modified within blocks synchronized on IpSecService.this. We want to avoid -1 + * (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it). */ @GuardedBy("IpSecService.this") private int mNextResourceId = 1; @@ -536,14 +536,14 @@ public class IpSecService extends IIpSecService.Stub { private final class TransformRecord extends KernelResourceRecord { private final IpSecConfig mConfig; - private final SpiRecord[] mSpis; + private final SpiRecord mSpi; private final EncapSocketRecord mSocket; TransformRecord( - int resourceId, IpSecConfig config, SpiRecord[] spis, EncapSocketRecord socket) { + int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) { super(resourceId); mConfig = config; - mSpis = spis; + mSpi = spi; mSocket = socket; } @@ -551,29 +551,26 @@ public class IpSecService extends IIpSecService.Stub { return mConfig; } - public SpiRecord getSpiRecord(int direction) { - return mSpis[direction]; + public SpiRecord getSpiRecord() { + return mSpi; } /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { - for (int direction : DIRECTIONS) { - int spi = mSpis[direction].getSpi(); - try { - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityAssociation( - mResourceId, - direction, - mConfig.getLocalAddress(), - mConfig.getRemoteAddress(), - spi); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); - } + int spi = mSpi.getSpi(); + try { + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, + mConfig.getSourceAddress(), + mConfig.getDestinationAddress(), + spi); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (RemoteException e) { + Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); } getResourceTracker().give(); @@ -597,10 +594,8 @@ public class IpSecService extends IIpSecService.Stub { .append(super.toString()) .append(", mSocket=") .append(mSocket) - .append(", mSpis[OUT].mResourceId=") - .append(mSpis[IpSecTransform.DIRECTION_OUT].mResourceId) - .append(", mSpis[IN].mResourceId=") - .append(mSpis[IpSecTransform.DIRECTION_IN].mResourceId) + .append(", mSpi.mResourceId=") + .append(mSpi.mResourceId) .append(", mConfig=") .append(mConfig) .append("}"); @@ -609,23 +604,16 @@ public class IpSecService extends IIpSecService.Stub { } private final class SpiRecord extends KernelResourceRecord { - private final int mDirection; - private final String mLocalAddress; - private final String mRemoteAddress; + private final String mSourceAddress; + private final String mDestinationAddress; private int mSpi; private boolean mOwnedByTransform = false; - SpiRecord( - int resourceId, - int direction, - String localAddress, - String remoteAddress, - int spi) { + SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) { super(resourceId); - mDirection = direction; - mLocalAddress = localAddress; - mRemoteAddress = remoteAddress; + mSourceAddress = sourceAddress; + mDestinationAddress = destinationAddress; mSpi = spi; } @@ -646,7 +634,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi); + mResourceId, mSourceAddress, mDestinationAddress, mSpi); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { @@ -662,6 +650,10 @@ public class IpSecService extends IIpSecService.Stub { return mSpi; } + public String getDestinationAddress() { + return mDestinationAddress; + } + public void setOwnedByTransform() { if (mOwnedByTransform) { // Programming error @@ -689,12 +681,10 @@ public class IpSecService extends IIpSecService.Stub { .append(super.toString()) .append(", mSpi=") .append(mSpi) - .append(", mDirection=") - .append(mDirection) - .append(", mLocalAddress=") - .append(mLocalAddress) - .append(", mRemoteAddress=") - .append(mRemoteAddress) + .append(", mSourceAddress=") + .append(mSourceAddress) + .append(", mDestinationAddress=") + .append(mDestinationAddress) .append(", mOwnedByTransform=") .append(mOwnedByTransform) .append("}"); @@ -772,14 +762,17 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { - this(context, config, (fd, uid) -> { - try{ - TrafficStats.setThreadStatsUid(uid); - TrafficStats.tagFileDescriptor(fd); - } finally { - TrafficStats.clearThreadStatsUid(); - } - }); + this( + context, + config, + (fd, uid) -> { + try { + TrafficStats.setThreadStatsUid(uid); + TrafficStats.tagFileDescriptor(fd); + } finally { + TrafficStats.clearThreadStatsUid(); + } + }); } /** @hide */ @@ -845,8 +838,8 @@ public class IpSecService extends IIpSecService.Stub { */ private static void checkDirection(int direction) { switch (direction) { - case IpSecTransform.DIRECTION_OUT: - case IpSecTransform.DIRECTION_IN: + case IpSecManager.DIRECTION_OUT: + case IpSecManager.DIRECTION_IN: return; } throw new IllegalArgumentException("Invalid Direction: " + direction); @@ -855,10 +848,8 @@ public class IpSecService extends IIpSecService.Stub { /** Get a new SPI and maintain the reservation in the system server */ @Override public synchronized IpSecSpiResponse allocateSecurityParameterIndex( - int direction, String remoteAddress, int requestedSpi, IBinder binder) - throws RemoteException { - checkDirection(direction); - checkInetAddress(remoteAddress); + String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException { + checkInetAddress(destinationAddress); /* requestedSpi can be anything in the int range, so no check is needed. */ checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); @@ -866,28 +857,21 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; - String localAddress = ""; - try { if (!userRecord.mSpiQuotaTracker.isAvailable()) { return new IpSecSpiResponse( IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi); } + spi = mSrvConfig .getNetdInstance() - .ipSecAllocateSpi( - resourceId, - direction, - localAddress, - remoteAddress, - requestedSpi); + .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, new RefcountedResource<SpiRecord>( - new SpiRecord(resourceId, direction, localAddress, remoteAddress, spi), - binder)); + new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { // TODO: Add appropriate checks when other ServiceSpecificException types are supported return new IpSecSpiResponse( @@ -1032,27 +1016,27 @@ public class IpSecService extends IIpSecService.Stub { } @VisibleForTesting - void validateAlgorithms(IpSecConfig config, int direction) throws IllegalArgumentException { - IpSecAlgorithm auth = config.getAuthentication(direction); - IpSecAlgorithm crypt = config.getEncryption(direction); - IpSecAlgorithm aead = config.getAuthenticatedEncryption(direction); - - // Validate the algorithm set - Preconditions.checkArgument( - aead != null || crypt != null || auth != null, - "No Encryption or Authentication algorithms specified"); - Preconditions.checkArgument( - auth == null || auth.isAuthentication(), - "Unsupported algorithm for Authentication"); - Preconditions.checkArgument( + void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException { + IpSecAlgorithm auth = config.getAuthentication(); + IpSecAlgorithm crypt = config.getEncryption(); + IpSecAlgorithm aead = config.getAuthenticatedEncryption(); + + // Validate the algorithm set + Preconditions.checkArgument( + aead != null || crypt != null || auth != null, + "No Encryption or Authentication algorithms specified"); + Preconditions.checkArgument( + auth == null || auth.isAuthentication(), + "Unsupported algorithm for Authentication"); + Preconditions.checkArgument( crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption"); - Preconditions.checkArgument( - aead == null || aead.isAead(), - "Unsupported algorithm for Authenticated Encryption"); - Preconditions.checkArgument( - aead == null || (auth == null && crypt == null), - "Authenticated Encryption is mutually exclusive with other Authentication " - + "or Encryption algorithms"); + Preconditions.checkArgument( + aead == null || aead.isAead(), + "Unsupported algorithm for Authenticated Encryption"); + Preconditions.checkArgument( + aead == null || (auth == null && crypt == null), + "Authenticated Encryption is mutually exclusive with other Authentication " + + "or Encryption algorithms"); } /** @@ -1062,29 +1046,6 @@ public class IpSecService extends IIpSecService.Stub { private void checkIpSecConfig(IpSecConfig config) { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - if (config.getLocalAddress() == null) { - throw new IllegalArgumentException("Invalid null Local InetAddress"); - } - - if (config.getRemoteAddress() == null) { - throw new IllegalArgumentException("Invalid null Remote InetAddress"); - } - - switch (config.getMode()) { - case IpSecTransform.MODE_TRANSPORT: - if (!config.getLocalAddress().isEmpty()) { - throw new IllegalArgumentException("Non-empty Local Address"); - } - // Must be valid, and not a wildcard - checkInetAddress(config.getRemoteAddress()); - break; - case IpSecTransform.MODE_TUNNEL: - break; - default: - throw new IllegalArgumentException( - "Invalid IpSecTransform.mode: " + config.getMode()); - } - switch (config.getEncapType()) { case IpSecTransform.ENCAP_NONE: break; @@ -1103,11 +1064,36 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType()); } - for (int direction : DIRECTIONS) { - validateAlgorithms(config, direction); + validateAlgorithms(config); + + // Retrieve SPI record; will throw IllegalArgumentException if not found + SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId()); + + // If no remote address is supplied, then use one from the SPI. + if (TextUtils.isEmpty(config.getDestinationAddress())) { + config.setDestinationAddress(s.getDestinationAddress()); + } + + // All remote addresses must match + if (!config.getDestinationAddress().equals(s.getDestinationAddress())) { + throw new IllegalArgumentException("Mismatched remote addresseses."); + } + + // This check is technically redundant due to the chain of custody between the SPI and + // the IpSecConfig, but in the future if the dest is allowed to be set explicitly in + // the transform, this will prevent us from messing up. + checkInetAddress(config.getDestinationAddress()); + + // Require a valid source address for all transforms. + checkInetAddress(config.getSourceAddress()); - // Retrieve SPI record; will throw IllegalArgumentException if not found - userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction)); + switch (config.getMode()) { + case IpSecTransform.MODE_TRANSPORT: + case IpSecTransform.MODE_TUNNEL: + break; + default: + throw new IllegalArgumentException( + "Invalid IpSecTransform.mode: " + config.getMode()); } } @@ -1127,13 +1113,12 @@ public class IpSecService extends IIpSecService.Stub { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - // Avoid resizing by creating a dependency array of min-size 3 (1 UDP encap + 2 SPIs) - List<RefcountedResource> dependencies = new ArrayList<>(3); + // Avoid resizing by creating a dependency array of min-size 2 (1 UDP encap + 1 SPI) + List<RefcountedResource> dependencies = new ArrayList<>(2); if (!userRecord.mTransformQuotaTracker.isAvailable()) { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } - SpiRecord[] spis = new SpiRecord[DIRECTIONS.length]; int encapType, encapLocalPort = 0, encapRemotePort = 0; EncapSocketRecord socketRecord = null; @@ -1149,51 +1134,46 @@ public class IpSecService extends IIpSecService.Stub { encapRemotePort = c.getEncapRemotePort(); } - for (int direction : DIRECTIONS) { - IpSecAlgorithm auth = c.getAuthentication(direction); - IpSecAlgorithm crypt = c.getEncryption(direction); - IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction); + IpSecAlgorithm auth = c.getAuthentication(); + IpSecAlgorithm crypt = c.getEncryption(); + IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); - RefcountedResource<SpiRecord> refcountedSpiRecord = - userRecord.mSpiRecords.getRefcountedResourceOrThrow( - c.getSpiResourceId(direction)); - dependencies.add(refcountedSpiRecord); + RefcountedResource<SpiRecord> refcountedSpiRecord = + userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId()); + dependencies.add(refcountedSpiRecord); + SpiRecord spiRecord = refcountedSpiRecord.getResource(); - spis[direction] = refcountedSpiRecord.getResource(); - int spi = spis[direction].getSpi(); - try { - mSrvConfig - .getNetdInstance() - .ipSecAddSecurityAssociation( - resourceId, - c.getMode(), - direction, - c.getLocalAddress(), - c.getRemoteAddress(), - (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0, - spi, - (auth != null) ? auth.getName() : "", - (auth != null) ? auth.getKey() : new byte[] {}, - (auth != null) ? auth.getTruncationLengthBits() : 0, - (crypt != null) ? crypt.getName() : "", - (crypt != null) ? crypt.getKey() : new byte[] {}, - (crypt != null) ? crypt.getTruncationLengthBits() : 0, - (authCrypt != null) ? authCrypt.getName() : "", - (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, - (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, - encapType, - encapLocalPort, - encapRemotePort); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); - } + try { + mSrvConfig + .getNetdInstance() + .ipSecAddSecurityAssociation( + resourceId, + c.getMode(), + c.getSourceAddress(), + c.getDestinationAddress(), + (c.getNetwork() != null) ? c.getNetwork().netId : 0, + spiRecord.getSpi(), + (auth != null) ? auth.getName() : "", + (auth != null) ? auth.getKey() : new byte[] {}, + (auth != null) ? auth.getTruncationLengthBits() : 0, + (crypt != null) ? crypt.getName() : "", + (crypt != null) ? crypt.getKey() : new byte[] {}, + (crypt != null) ? crypt.getTruncationLengthBits() : 0, + (authCrypt != null) ? authCrypt.getName() : "", + (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, + (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, + encapType, + encapLocalPort, + encapRemotePort); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } // Both SAs were created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( resourceId, new RefcountedResource<TransformRecord>( - new TransformRecord(resourceId, c, spis, socketRecord), + new TransformRecord(resourceId, c, spiRecord, socketRecord), binder, dependencies.toArray(new RefcountedResource[dependencies.size()]))); return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId); @@ -1217,9 +1197,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void applyTransportModeTransform( - ParcelFileDescriptor socket, int resourceId) throws RemoteException { + ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - + checkDirection(direction); // Get transform record; if no transform is found, will throw IllegalArgumentException TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); @@ -1230,17 +1210,15 @@ public class IpSecService extends IIpSecService.Stub { IpSecConfig c = info.getConfig(); try { - for (int direction : DIRECTIONS) { - mSrvConfig - .getNetdInstance() - .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), - resourceId, - direction, - c.getLocalAddress(), - c.getRemoteAddress(), - info.getSpiRecord(direction).getSpi()); - } + mSrvConfig + .getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } catch (ServiceSpecificException e) { if (e.errorCode == EINVAL) { throw new IllegalArgumentException(e.toString()); @@ -1251,13 +1229,13 @@ public class IpSecService extends IIpSecService.Stub { } /** - * Remove a transport mode transform from a socket, applying the default (empty) policy. This - * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of - * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not - * used: reserved for future improved input validation. + * Remove transport mode transforms from a socket, applying the default (empty) policy. This + * ensures that NO IPsec policy is applied to the socket (would be the equivalent of applying a + * policy that performs no IPsec). Today the resourceId parameter is passed but not used: + * reserved for future improved input validation. */ @Override - public synchronized void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId) + public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { try { mSrvConfig diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 40e6d2645b69..8f646e75862c 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -2508,12 +2508,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void removeNetwork(int netId) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG); try { - mConnector.execute("network", "destroy", netId); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mNetdService.networkDestroy(netId); + } catch (ServiceSpecificException e) { + Log.w(TAG, "removeNetwork(" + netId + "): ", e); + throw e; + } catch (RemoteException e) { + Log.w(TAG, "removeNetwork(" + netId + "): ", e); + throw e.rethrowAsRuntimeException(); } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 831c9cbc2ef5..6747be340d46 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -147,6 +147,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private int[] mDataActivationState; + private boolean[] mUserMobileDataState; + private SignalStrength[] mSignalStrength; private boolean[] mMessageWaiting; @@ -304,6 +306,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mServiceState = new ServiceState[numPhones]; mVoiceActivationState = new int[numPhones]; mDataActivationState = new int[numPhones]; + mUserMobileDataState = new boolean[numPhones]; mSignalStrength = new SignalStrength[numPhones]; mMessageWaiting = new boolean[numPhones]; mCallForwarding = new boolean[numPhones]; @@ -320,6 +323,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mCallIncomingNumber[i] = ""; mServiceState[i] = new ServiceState(); mSignalStrength[i] = new SignalStrength(); + mUserMobileDataState[i] = false; mMessageWaiting[i] = false; mCallForwarding[i] = false; mCellLocation[i] = new Bundle(); @@ -656,6 +660,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) { + try { + r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -1012,6 +1023,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + public void notifyUserMobileDataStateChangedForPhoneId(int phoneId, int subId, boolean state) { + if (!checkNotifyPermission("notifyUserMobileDataStateChanged()")) { + return; + } + if (VDBG) { + log("notifyUserMobileDataStateChangedForSubscriberPhoneID: subId=" + phoneId + + " state=" + state); + } + synchronized (mRecords) { + if (validatePhoneId(phoneId)) { + mMessageWaiting[phoneId] = state; + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) && + idMatch(r.subId, subId, phoneId)) { + try { + r.callback.onUserMobileDataStateChanged(state); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + public void notifyCallForwardingChanged(boolean cfi) { notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cfi); } @@ -1374,6 +1412,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mServiceState=" + mServiceState[i]); pw.println("mVoiceActivationState= " + mVoiceActivationState[i]); pw.println("mDataActivationState= " + mDataActivationState[i]); + pw.println("mUserMobileDataState= " + mUserMobileDataState[i]); pw.println("mSignalStrength=" + mSignalStrength[i]); pw.println("mMessageWaiting=" + mMessageWaiting[i]); pw.println("mCallForwarding=" + mCallForwarding[i]); @@ -1755,6 +1794,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) { + try { + if (VDBG) { + log("checkPossibleMissNotify: onUserMobileDataStateChanged phoneId=" + + phoneId + " umds=" + mUserMobileDataState[phoneId]); + } + r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { try { if (VDBG) { diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 8d46d1e27235..7ce0f4352203 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -87,6 +87,7 @@ public class Watchdog extends Thread { "/system/bin/sdcard", "/system/bin/surfaceflinger", "media.extractor", // system/bin/mediaextractor + "media.metrics", // system/bin/mediametrics "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service "com.android.bluetooth", // Bluetooth service }; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6cdf0712c7c1..002381a5a3f0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7012,15 +7012,22 @@ public class ActivityManagerService extends IActivityManager.Stub } ProfilerInfo profilerInfo = null; - String agent = null; + String preBindAgent = null; if (mProfileApp != null && mProfileApp.equals(processName)) { mProfileProc = app; - profilerInfo = (mProfilerInfo != null && mProfilerInfo.profileFile != null) ? - new ProfilerInfo(mProfilerInfo) : null; - agent = mProfilerInfo != null ? mProfilerInfo.agent : null; + if (mProfilerInfo != null) { + // Send a profiler info object to the app if either a file is given, or + // an agent should be loaded at bind-time. + boolean needsInfo = mProfilerInfo.profileFile != null + || mProfilerInfo.attachAgentDuringBind; + profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null; + if (!mProfilerInfo.attachAgentDuringBind) { + preBindAgent = mProfilerInfo.agent; + } + } } else if (app.instr != null && app.instr.mProfileFile != null) { profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false, - null); + null, false); } boolean enableTrackAllocation = false; @@ -7087,8 +7094,8 @@ public class ActivityManagerService extends IActivityManager.Stub // If we were asked to attach an agent on startup, do so now, before we're binding // application code. - if (agent != null) { - thread.attachAgent(agent); + if (preBindAgent != null) { + thread.attachAgent(preBindAgent); } checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8488e526eba9..a7ace21607b5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -114,6 +114,7 @@ final class ActivityManagerShellCommand extends ShellCommand { private boolean mAutoStop; private boolean mStreaming; // Streaming the profiling output to a file. private String mAgent; // Agent to attach on startup. + private boolean mAttachAgentDuringBind; // Whether agent should be attached late. private int mDisplayId; private int mStackId; private int mTaskId; @@ -295,7 +296,21 @@ final class ActivityManagerShellCommand extends ShellCommand { } else if (opt.equals("--streaming")) { mStreaming = true; } else if (opt.equals("--attach-agent")) { + if (mAgent != null) { + cmd.getErrPrintWriter().println( + "Multiple --attach-agent(-bind) not supported"); + return false; + } + mAgent = getNextArgRequired(); + mAttachAgentDuringBind = false; + } else if (opt.equals("--attach-agent-bind")) { + if (mAgent != null) { + cmd.getErrPrintWriter().println( + "Multiple --attach-agent(-bind) not supported"); + return false; + } mAgent = getNextArgRequired(); + mAttachAgentDuringBind = true; } else if (opt.equals("-R")) { mRepeat = Integer.parseInt(getNextArgRequired()); } else if (opt.equals("-S")) { @@ -381,7 +396,7 @@ final class ActivityManagerShellCommand extends ShellCommand { } } profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, - mStreaming, mAgent); + mStreaming, mAgent, mAttachAgentDuringBind); } pw.println("Starting: " + intent); @@ -755,7 +770,7 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming, - null); + null, false); } try { @@ -2679,6 +2694,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" (use with --start-profiler)"); pw.println(" -P <FILE>: like above, but profiling stops when app goes idle"); pw.println(" --attach-agent <agent>: attach the given agent before binding"); + pw.println(" --attach-agent-bind <agent>: attach the given agent during binding"); pw.println(" -R: repeat the activity launch <COUNT> times. Prior to each repeat,"); pw.println(" the top activity will be finished."); pw.println(" -S: force stop the target app before starting the activity"); diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index b7b91a76ebf3..625764cea550 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -39,8 +39,10 @@ import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.os.Binder; import android.os.Build; +import android.os.Handler; import android.os.IBinder; import android.os.IInterface; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -82,6 +84,7 @@ abstract public class ManagedServices { protected final String TAG = getClass().getSimpleName(); protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; protected static final String ENABLED_SERVICES_SEPARATOR = ":"; /** @@ -101,12 +104,15 @@ abstract public class ManagedServices { private final IPackageManager mPm; private final UserManager mUm; private final Config mConfig; + private final Handler mHandler = new Handler(Looper.getMainLooper()); // contains connections to all connected services, including app services // and system services private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>(); // things that will be put into mServices as soon as they're ready private final ArrayList<String> mServicesBinding = new ArrayList<>(); + private final ArraySet<String> mServicesRebinding = new ArraySet<>(); + // lists the component names of all enabled (and therefore potentially connected) // app services for current profiles. private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles @@ -823,6 +829,7 @@ abstract public class ManagedServices { final String servicesBindingTag = name.toString() + "/" + userid; if (mServicesBinding.contains(servicesBindingTag)) { + Slog.v(TAG, "Not registering " + name + " as bind is already in progress"); // stop registering this thing already! we're working on it return; } @@ -871,6 +878,7 @@ abstract public class ManagedServices { boolean added = false; ManagedServiceInfo info = null; synchronized (mMutex) { + mServicesRebinding.remove(servicesBindingTag); mServicesBinding.remove(servicesBindingTag); try { mService = asInterface(binder); @@ -892,6 +900,27 @@ abstract public class ManagedServices { mServicesBinding.remove(servicesBindingTag); Slog.v(TAG, getCaption() + " connection lost: " + name); } + + @Override + public void onBindingDied(ComponentName name) { + Slog.w(TAG, getCaption() + " binding died: " + name); + synchronized (mMutex) { + mServicesBinding.remove(servicesBindingTag); + mContext.unbindService(this); + if (!mServicesRebinding.contains(servicesBindingTag)) { + mServicesRebinding.add(servicesBindingTag); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + registerService(name, userid); + } + }, ON_BINDING_DIED_REBIND_DELAY_MS); + } else { + Slog.v(TAG, getCaption() + " not rebinding as " + + "a previous rebind attempt was made: " + name); + } + } + } }; if (!mContext.bindServiceAsUser(intent, serviceConnection, diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 210eb1385035..41cfcbe1af88 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -281,13 +281,14 @@ public class Installer extends SystemService { public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, - @Nullable String seInfo, boolean downgrade) + @Nullable String seInfo, boolean downgrade, int targetSdkVersion) throws InstallerException { assertValidInstructionSet(instructionSet); if (!checkBeforeRemote()) return; try { mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath, - dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade); + dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade, + targetSdkVersion); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 6253857d1aa4..5dbd3caa7b79 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -260,12 +260,13 @@ public class OtaDexoptService extends IOtaDexopt.Stub { public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, - @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade) + @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade, + int targetSdkVersion) throws InstallerException { final StringBuilder builder = new StringBuilder(); - // The version. Right now it's 3. - builder.append("3 "); + // The version. Right now it's 4. + builder.append("4 "); builder.append("dexopt"); @@ -281,6 +282,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { encodeParameter(builder, sharedLibraries); encodeParameter(builder, seInfo); encodeParameter(builder, downgrade); + encodeParameter(builder, targetSdkVersion); commands.add(builder.toString()); } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 300f15fa0925..2cc51599ad16 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -274,7 +274,7 @@ public class PackageDexOptimizer { // primary dex files. mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags, compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo, - false /* downgrade*/); + false /* downgrade*/, pkg.applicationInfo.targetSdkVersion); if (packageStats != null) { long endTime = System.currentTimeMillis(); @@ -395,7 +395,7 @@ public class PackageDexOptimizer { mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0, /*oatDir*/ null, dexoptFlags, compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser, - options.isDowngrade()); + options.isDowngrade(), info.targetSdkVersion); } return DEX_OPT_PERFORMED; diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 20911012e6ba..8c7d6b30ecdc 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -1408,7 +1408,7 @@ public final class Call { * @param extras Bundle containing extra information associated with the event. */ public void sendCallEvent(String event, Bundle extras) { - mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras); + mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras); } /** diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index 4bc2a9b149f2..658685fe2907 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -286,11 +286,12 @@ public final class InCallAdapter { * * @param callId The callId to send the event for. * @param event The event. + * @param targetSdkVer Target sdk version of the app calling this api * @param extras Extras associated with the event. */ - public void sendCallEvent(String callId, String event, Bundle extras) { + public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) { try { - mAdapter.sendCallEvent(callId, event, extras); + mAdapter.sendCallEvent(callId, event, targetSdkVer, extras); } catch (RemoteException ignored) { } } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index a9bbd2421d88..96c6e0a5b743 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -24,6 +24,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -236,6 +237,15 @@ public class TelecomManager { "android.telecom.extra.INCOMING_CALL_EXTRAS"; /** + * Optional extra for {@link #ACTION_INCOMING_CALL} containing a boolean to indicate that the + * call has an externally generated ringer. Used by the HfpClientConnectionService when In Band + * Ringtone is enabled to prevent two ringers from being generated. + * @hide + */ + public static final String EXTRA_CALL_EXTERNAL_RINGER = + "android.telecom.extra.CALL_EXTERNAL_RINGER"; + + /** * Optional extra for {@link android.content.Intent#ACTION_CALL} and * {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle} * which contains metadata about the call. This {@link Bundle} will be saved into @@ -1423,6 +1433,13 @@ public class TelecomManager { public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) { try { if (isServiceConnected()) { + if (extras != null && extras.getBoolean(EXTRA_IS_HANDOVER) && + mContext.getApplicationContext().getApplicationInfo().targetSdkVersion > + Build.VERSION_CODES.O_MR1) { + Log.e("TAG", "addNewIncomingCall failed. Use public api " + + "acceptHandover for API > O-MR1"); + // TODO add "return" after DUO team adds support for new handover API + } getTelecomService().addNewIncomingCall( phoneAccount, extras == null ? new Bundle() : extras); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index 23ac940edfa8..87ccd3ed4369 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -64,7 +64,7 @@ oneway interface IInCallAdapter { void pullExternalCall(String callId); - void sendCallEvent(String callId, String event, in Bundle extras); + void sendCallEvent(String callId, String event, int targetSdkVer, in Bundle extras); void putExtras(String callId, in Bundle extras); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index d0fb9821eefd..0c05a025dd45 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -950,8 +950,9 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool"; /** - * String to identify carrier name in CarrierConfig app. This string is used only if - * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true + * String to identify carrier name in CarrierConfig app. This string overrides SPN if + * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided + * and SPN is unavailable * @hide */ public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string"; diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index c7e51310e106..98ea45158ba1 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -244,6 +244,13 @@ public class PhoneStateListener { */ public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000; + /** + * Listen for changes to the user mobile data state + * + * @see #onUserMobileDataStateChanged + */ + public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000; + /* * Subscription used to listen to the phone state changes * @hide @@ -349,6 +356,9 @@ public class PhoneStateListener { case LISTEN_DATA_ACTIVATION_STATE: PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj); break; + case LISTEN_USER_MOBILE_DATA_STATE: + PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj); + break; case LISTEN_CARRIER_NETWORK_CHANGE: PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj); break; @@ -543,6 +553,14 @@ public class PhoneStateListener { } /** + * Callback invoked when the user mobile data state has changed + * @param enabled indicates whether the current user mobile data state is enabled or disabled. + */ + public void onUserMobileDataStateChanged(boolean enabled) { + // default implementation empty + } + + /** * Callback invoked when telephony has received notice from a carrier * app that a network action that could result in connectivity loss * has been requested by an app using @@ -654,6 +672,10 @@ public class PhoneStateListener { send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState); } + public void onUserMobileDataStateChanged(boolean enabled) { + send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled); + } + public void onCarrierNetworkChange(boolean active) { send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active); } diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java index e0b6f610ab55..e633053800bc 100644 --- a/telephony/java/android/telephony/Telephony.java +++ b/telephony/java/android/telephony/Telephony.java @@ -2564,6 +2564,35 @@ public final class Telephony { public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers"); /** + * The {@code content://} style URL to be called from DevicePolicyManagerService, + * can manage DPC-owned APNs. + * @hide + */ + public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc"); + + /** + * The {@code content://} style URL to be called from Telephony to query APNs. + * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only + * non-DPC-owned APNs are returned. + * @hide + */ + public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered"); + + /** + * The {@code content://} style URL to be called from DevicePolicyManagerService + * or Telephony to manage whether DPC-owned APNs are enforced. + * @hide + */ + public static final Uri ENFORCE_MANAGED_URI = Uri.parse( + "content://telephony/carriers/enforce_managed"); + + /** + * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced. + * @hide + */ + public static final String ENFORCE_KEY = "enforced"; + + /** * The default sort order for this table. */ public static final String DEFAULT_SORT_ORDER = "name ASC"; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index f278d7c22e75..6a683431f0aa 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -54,6 +54,7 @@ import android.util.Log; import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsRcsFeature; +import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.ITelecomService; @@ -957,6 +958,64 @@ public class TelephonyManager { */ public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; + /** + * An unknown carrier id. It could either be subscription unavailable or the subscription + * carrier cannot be recognized. Unrecognized carriers here means + * {@link #getSimOperator() MCC+MNC} cannot be identified. + */ + public static final int UNKNOWN_CARRIER_ID = -1; + + /** + * Broadcast Action: The subscription carrier identity has changed. + * This intent could be sent on the following events: + * <ul> + * <li>Subscription absent. Carrier identity could change from a valid id to + * {@link TelephonyManager#UNKNOWN_CARRIER_ID}.</li> + * <li>Subscription loaded. Carrier identity could change from + * {@link TelephonyManager#UNKNOWN_CARRIER_ID} to a valid id.</li> + * <li>The subscription carrier is recognized after a remote update.</li> + * </ul> + * The intent will have the following extra values: + * <ul> + * <li>{@link #EXTRA_CARRIER_ID} The up-to-date carrier id of the current subscription id. + * </li> + * <li>{@link #EXTRA_CARRIER_NAME} The up-to-date carrier name of the current subscription. + * </li> + * <li>{@link #EXTRA_SUBSCRIPTION_ID} The subscription id associated with the changed carrier + * identity. + * </li> + * </ul> + * <p class="note">This is a protected intent that can only be sent by the system. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = + "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED"; + + /** + * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which indicates + * the updated carrier id {@link TelephonyManager#getSubscriptionCarrierId()} of the current + * subscription. + * <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or + * the carrier cannot be identified. + */ + public static final String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID"; + + /** + * An string extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which + * indicates the updated carrier name of the current subscription. + * {@see TelephonyManager#getSubscriptionCarrierName()} + * <p>Carrier name is a user-facing name of the carrier id {@link #EXTRA_CARRIER_ID}, + * usually the brand name of the subsidiary (e.g. T-Mobile). + */ + public static final String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME"; + + /** + * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} to indicate the + * subscription which has changed. + */ + public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID"; + + // // // Device Info @@ -4720,6 +4779,25 @@ public class TelephonyManager { } /** + * @return the {@IImsRegistration} interface that corresponds with the slot index and feature. + * @param slotIndex The SIM slot corresponding to the ImsService ImsRegistration is active for. + * @param feature An integer indicating the feature that we wish to get the ImsRegistration for. + * Corresponds to features defined in ImsFeature. + * @hide + */ + public @Nullable IImsRegistration getImsRegistration(int slotIndex, int feature) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getImsRegistration(slotIndex, feature); + } + } catch (RemoteException e) { + Rlog.e(TAG, "getImsRegistration, RemoteException: " + e.getMessage()); + } + return null; + } + + /** * Set IMS registration state * * @param Registration state @@ -6548,6 +6626,55 @@ public class TelephonyManager { } /** + * Returns carrier id of the current subscription. + * <p>To recognize a carrier (including MVNO) as a first class identity, assign each carrier + * with a canonical integer a.k.a carrier id. + * + * @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the + * subscription is unavailable or the carrier cannot be identified. + * @throws IllegalStateException if telephony service is unavailable. + */ + public int getSubscriptionCarrierId() { + try { + ITelephony service = getITelephony(); + return service.getSubscriptionCarrierId(getSubId()); + } catch (RemoteException ex) { + // This could happen if binder process crashes. + ex.rethrowAsRuntimeException(); + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing. + throw new IllegalStateException("Telephony service unavailable"); + } + return UNKNOWN_CARRIER_ID; + } + + /** + * Returns carrier name of the current subscription. + * <p>Carrier name is a user-facing name of carrier id {@link #getSubscriptionCarrierId()}, + * usually the brand name of the subsidiary (e.g. T-Mobile). Each carrier could configure + * multiple {@link #getSimOperatorName() SPN} but should have a single carrier name. + * Carrier name is not a canonical identity, use {@link #getSubscriptionCarrierId()} instead. + * <p>The returned carrier name is unlocalized. + * + * @return Carrier name of the current subscription. Return {@code null} if the subscription is + * unavailable or the carrier cannot be identified. + * @throws IllegalStateException if telephony service is unavailable. + */ + public String getSubscriptionCarrierName() { + try { + ITelephony service = getITelephony(); + return service.getSubscriptionCarrierName(getSubId()); + } catch (RemoteException ex) { + // This could happen if binder process crashes. + ex.rethrowAsRuntimeException(); + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing. + throw new IllegalStateException("Telephony service unavailable"); + } + return null; + } + + /** * Return the application ID for the app type like {@link APPTYPE_CSIM}. * * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index da51c86151d2..ef3a183f7800 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -20,6 +20,7 @@ package android.telephony.data; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.net.LinkAddress; import android.os.Parcel; import android.os.Parcelable; @@ -40,7 +41,7 @@ public final class DataCallResponse implements Parcelable { private final int mActive; private final String mType; private final String mIfname; - private final List<InterfaceAddress> mAddresses; + private final List<LinkAddress> mAddresses; private final List<InetAddress> mDnses; private final List<InetAddress> mGateways; private final List<String> mPcscfs; @@ -71,7 +72,7 @@ public final class DataCallResponse implements Parcelable { */ public DataCallResponse(int status, int suggestedRetryTime, int cid, int active, @Nullable String type, @Nullable String ifname, - @Nullable List<InterfaceAddress> addresses, + @Nullable List<LinkAddress> addresses, @Nullable List<InetAddress> dnses, @Nullable List<InetAddress> gateways, @Nullable List<String> pcscfs, int mtu) { @@ -96,7 +97,7 @@ public final class DataCallResponse implements Parcelable { mType = source.readString(); mIfname = source.readString(); mAddresses = new ArrayList<>(); - source.readList(mAddresses, InterfaceAddress.class.getClassLoader()); + source.readList(mAddresses, LinkAddress.class.getClassLoader()); mDnses = new ArrayList<>(); source.readList(mDnses, InetAddress.class.getClassLoader()); mGateways = new ArrayList<>(); @@ -140,10 +141,10 @@ public final class DataCallResponse implements Parcelable { public String getIfname() { return mIfname; } /** - * @return A list of {@link InterfaceAddress} + * @return A list of {@link LinkAddress} */ @NonNull - public List<InterfaceAddress> getAddresses() { return mAddresses; } + public List<LinkAddress> getAddresses() { return mAddresses; } /** * @return A list of DNS server addresses, e.g., "192.0.1.3" or diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java new file mode 100644 index 000000000000..ea0817551369 --- /dev/null +++ b/telephony/java/android/telephony/data/DataService.java @@ -0,0 +1,540 @@ +/* + * Copyright 2017 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.telephony.data; + +import android.annotation.CallSuper; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.Intent; +import android.net.LinkProperties; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.AccessNetworkConstants; +import android.telephony.Rlog; +import android.telephony.SubscriptionManager; +import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; + +/** + * Base class of data service. Services that extend DataService must register the service in + * their AndroidManifest to be detected by the framework. They must be protected by the permission + * "android.permission.BIND_DATA_SERVICE". The data service definition in the manifest must follow + * the following format: + * ... + * <service android:name=".xxxDataService" + * android:permission="android.permission.BIND_DATA_SERVICE" > + * <intent-filter> + * <action android:name="android.telephony.data.DataService" /> + * </intent-filter> + * </service> + * @hide + */ +@SystemApi +public abstract class DataService extends Service { + private static final String TAG = DataService.class.getSimpleName(); + + public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService"; + public static final String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID"; + + private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE = 1; + private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 2; + private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 3; + private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 4; + private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 5; + private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 6; + private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 7; + private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 8; + private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 9; + + private final HandlerThread mHandlerThread; + + private final DataServiceHandler mHandler; + + private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>(); + + private final SparseArray<IDataServiceWrapper> mBinderMap = new SparseArray<>(); + + /** + * The abstract class of the actual data service implementation. The data service provider + * must extend this class to support data connection. Note that each instance of data service + * provider is associated with one physical SIM slot. + */ + public class DataServiceProvider { + + private final int mSlotId; + + private final List<IDataServiceCallback> mDataCallListChangedCallbacks = new ArrayList<>(); + + /** + * Constructor + * @param slotId SIM slot id the data service provider associated with. + */ + public DataServiceProvider(int slotId) { + mSlotId = slotId; + } + + /** + * @return SIM slot id the data service provider associated with. + */ + public final int getSlotId() { + return mSlotId; + } + + /** + * Setup a data connection. The data service provider must implement this method to support + * establishing a packet data connection. When completed or error, the service must invoke + * the provided callback to notify the platform. + * + * @param accessNetworkType Access network type that the data call will be established on. + * Must be one of {@link AccessNetworkConstants.AccessNetworkType}. + * @param dataProfile Data profile used for data call setup. See {@link DataProfile} + * @param isRoaming True if the device is data roaming. + * @param allowRoaming True if data roaming is allowed by the user. + * @param isHandover True if the request is for IWLAN handover. + * @param linkProperties If {@code isHandover} is true, this is the link properties of the + * existing data connection, otherwise null. + * @param callback The result callback for this request. + */ + public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, + boolean allowRoaming, boolean isHandover, + LinkProperties linkProperties, DataServiceCallback callback) { + // The default implementation is to return unsupported. + callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null); + } + + /** + * Deactivate a data connection. The data service provider must implement this method to + * support data connection tear down. When completed or error, the service must invoke the + * provided callback to notify the platform. + * + * @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall( + * int, DataProfile, boolean, boolean, boolean, LinkProperties, DataServiceCallback)}. + * @param reasonRadioShutDown True if the deactivate request reason is device shut down. + * @param isHandover True if the request is for IWLAN handover. + * @param callback The result callback for this request. + */ + public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover, + DataServiceCallback callback) { + // The default implementation is to return unsupported. + callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); + } + + /** + * Set an APN to initial attach network. + * + * @param dataProfile Data profile used for data call setup. See {@link DataProfile}. + * @param isRoaming True if the device is data roaming. + * @param callback The result callback for this request. + */ + public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, + DataServiceCallback callback) { + // The default implementation is to return unsupported. + callback.onSetInitialAttachApnComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); + } + + /** + * Send current carrier's data profiles to the data service for data call setup. This is + * only for CDMA carrier that can change the profile through OTA. The data service should + * always uses the latest data profile sent by the framework. + * + * @param dps A list of data profiles. + * @param isRoaming True if the device is data roaming. + * @param callback The result callback for this request. + */ + public void setDataProfile(List<DataProfile> dps, boolean isRoaming, + DataServiceCallback callback) { + // The default implementation is to return unsupported. + callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); + } + + /** + * Get the active data call list. + * + * @param callback The result callback for this request. + */ + public void getDataCallList(DataServiceCallback callback) { + // The default implementation is to return unsupported. + callback.onGetDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null); + } + + private void registerForDataCallListChanged(IDataServiceCallback callback) { + synchronized (mDataCallListChangedCallbacks) { + mDataCallListChangedCallbacks.add(callback); + } + } + + private void unregisterForDataCallListChanged(IDataServiceCallback callback) { + synchronized (mDataCallListChangedCallbacks) { + mDataCallListChangedCallbacks.remove(callback); + } + } + + /** + * Notify the system that current data call list changed. Data service must invoke this + * method whenever there is any data call status changed. + * + * @param dataCallList List of the current active data call. + */ + public final void notifyDataCallListChanged(List<DataCallResponse> dataCallList) { + synchronized (mDataCallListChangedCallbacks) { + for (IDataServiceCallback callback : mDataCallListChangedCallbacks) { + mHandler.obtainMessage(DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED, mSlotId, + 0, new DataCallListChangedIndication(dataCallList, callback)) + .sendToTarget(); + } + } + } + + /** + * Called when the instance of data service is destroyed (e.g. got unbind or binder died). + */ + @CallSuper + protected void onDestroy() { + mDataCallListChangedCallbacks.clear(); + } + } + + private static final class SetupDataCallRequest { + public final int accessNetworkType; + public final DataProfile dataProfile; + public final boolean isRoaming; + public final boolean allowRoaming; + public final boolean isHandover; + public final LinkProperties linkProperties; + public final IDataServiceCallback callback; + SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, + boolean allowRoaming, boolean isHandover, + LinkProperties linkProperties, IDataServiceCallback callback) { + this.accessNetworkType = accessNetworkType; + this.dataProfile = dataProfile; + this.isRoaming = isRoaming; + this.allowRoaming = allowRoaming; + this.linkProperties = linkProperties; + this.isHandover = isHandover; + this.callback = callback; + } + } + + private static final class DeactivateDataCallRequest { + public final int cid; + public final boolean reasonRadioShutDown; + public final boolean isHandover; + public final IDataServiceCallback callback; + DeactivateDataCallRequest(int cid, boolean reasonRadioShutDown, boolean isHandover, + IDataServiceCallback callback) { + this.cid = cid; + this.reasonRadioShutDown = reasonRadioShutDown; + this.isHandover = isHandover; + this.callback = callback; + } + } + + private static final class SetInitialAttachApnRequest { + public final DataProfile dataProfile; + public final boolean isRoaming; + public final IDataServiceCallback callback; + SetInitialAttachApnRequest(DataProfile dataProfile, boolean isRoaming, + IDataServiceCallback callback) { + this.dataProfile = dataProfile; + this.isRoaming = isRoaming; + this.callback = callback; + } + } + + private static final class SetDataProfileRequest { + public final List<DataProfile> dps; + public final boolean isRoaming; + public final IDataServiceCallback callback; + SetDataProfileRequest(List<DataProfile> dps, boolean isRoaming, + IDataServiceCallback callback) { + this.dps = dps; + this.isRoaming = isRoaming; + this.callback = callback; + } + } + + private static final class DataCallListChangedIndication { + public final List<DataCallResponse> dataCallList; + public final IDataServiceCallback callback; + DataCallListChangedIndication(List<DataCallResponse> dataCallList, + IDataServiceCallback callback) { + this.dataCallList = dataCallList; + this.callback = callback; + } + } + + private class DataServiceHandler extends Handler { + + DataServiceHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message message) { + IDataServiceCallback callback; + final int slotId = message.arg1; + DataServiceProvider service; + + synchronized (mServiceMap) { + service = mServiceMap.get(slotId); + } + + switch (message.what) { + case DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE: + service = createDataServiceProvider(message.arg1); + if (service != null) { + mServiceMap.put(slotId, service); + } + break; + case DATA_SERVICE_REQUEST_SETUP_DATA_CALL: + if (service == null) break; + SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj; + service.setupDataCall(setupDataCallRequest.accessNetworkType, + setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming, + setupDataCallRequest.allowRoaming, setupDataCallRequest.isHandover, + setupDataCallRequest.linkProperties, + new DataServiceCallback(setupDataCallRequest.callback)); + + break; + case DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL: + if (service == null) break; + DeactivateDataCallRequest deactivateDataCallRequest = + (DeactivateDataCallRequest) message.obj; + service.deactivateDataCall(deactivateDataCallRequest.cid, + deactivateDataCallRequest.reasonRadioShutDown, + deactivateDataCallRequest.isHandover, + new DataServiceCallback(deactivateDataCallRequest.callback)); + break; + case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN: + if (service == null) break; + SetInitialAttachApnRequest setInitialAttachApnRequest = + (SetInitialAttachApnRequest) message.obj; + service.setInitialAttachApn(setInitialAttachApnRequest.dataProfile, + setInitialAttachApnRequest.isRoaming, + new DataServiceCallback(setInitialAttachApnRequest.callback)); + break; + case DATA_SERVICE_REQUEST_SET_DATA_PROFILE: + if (service == null) break; + SetDataProfileRequest setDataProfileRequest = + (SetDataProfileRequest) message.obj; + service.setDataProfile(setDataProfileRequest.dps, + setDataProfileRequest.isRoaming, + new DataServiceCallback(setDataProfileRequest.callback)); + break; + case DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST: + if (service == null) break; + + service.getDataCallList(new DataServiceCallback( + (IDataServiceCallback) message.obj)); + break; + case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED: + if (service == null) break; + service.registerForDataCallListChanged((IDataServiceCallback) message.obj); + break; + case DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED: + if (service == null) break; + callback = (IDataServiceCallback) message.obj; + service.unregisterForDataCallListChanged(callback); + break; + case DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED: + if (service == null) break; + DataCallListChangedIndication indication = + (DataCallListChangedIndication) message.obj; + try { + indication.callback.onDataCallListChanged(indication.dataCallList); + } catch (RemoteException e) { + loge("Failed to call onDataCallListChanged. " + e); + } + break; + } + } + } + + private DataService() { + mHandlerThread = new HandlerThread(TAG); + mHandlerThread.start(); + + mHandler = new DataServiceHandler(mHandlerThread.getLooper()); + log("Data service created"); + } + + /** + * Create the instance of {@link DataServiceProvider}. Data service provider must override + * this method to facilitate the creation of {@link DataServiceProvider} instances. The system + * will call this method after binding the data service for each active SIM slot id. + * + * @param slotId SIM slot id the data service associated with. + * @return Data service object + */ + public abstract DataServiceProvider createDataServiceProvider(int slotId); + + /** @hide */ + @Override + public IBinder onBind(Intent intent) { + if (intent == null || !DATA_SERVICE_INTERFACE.equals(intent.getAction())) { + loge("Unexpected intent " + intent); + return null; + } + + int slotId = intent.getIntExtra( + DATA_SERVICE_EXTRA_SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX); + + if (!SubscriptionManager.isValidSlotIndex(slotId)) { + loge("Invalid slot id " + slotId); + return null; + } + + log("onBind: slot id=" + slotId); + + IDataServiceWrapper binder = mBinderMap.get(slotId); + if (binder == null) { + Message msg = mHandler.obtainMessage(DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE); + msg.arg1 = slotId; + msg.sendToTarget(); + + binder = new IDataServiceWrapper(slotId); + mBinderMap.put(slotId, binder); + } + + return binder; + } + + /** @hide */ + @Override + public boolean onUnbind(Intent intent) { + int slotId = intent.getIntExtra(DATA_SERVICE_EXTRA_SLOT_ID, + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + if (mBinderMap.get(slotId) != null) { + DataServiceProvider serviceImpl; + synchronized (mServiceMap) { + serviceImpl = mServiceMap.get(slotId); + } + if (serviceImpl != null) { + serviceImpl.onDestroy(); + } + mBinderMap.remove(slotId); + } + + // If all clients unbinds, quit the handler thread + if (mBinderMap.size() == 0) { + mHandlerThread.quit(); + } + + return false; + } + + /** @hide */ + @Override + public void onDestroy() { + synchronized (mServiceMap) { + for (int i = 0; i < mServiceMap.size(); i++) { + DataServiceProvider serviceImpl = mServiceMap.get(i); + if (serviceImpl != null) { + serviceImpl.onDestroy(); + } + } + mServiceMap.clear(); + } + + mHandlerThread.quit(); + } + + /** + * A wrapper around IDataService that forwards calls to implementations of {@link DataService}. + */ + private class IDataServiceWrapper extends IDataService.Stub { + + private final int mSlotId; + + IDataServiceWrapper(int slotId) { + mSlotId = slotId; + } + + @Override + public void setupDataCall(int accessNetworkType, DataProfile dataProfile, + boolean isRoaming, boolean allowRoaming, boolean isHandover, + LinkProperties linkProperties, IDataServiceCallback callback) { + mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0, + new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming, + allowRoaming, isHandover, linkProperties, callback)) + .sendToTarget(); + } + + @Override + public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover, + IDataServiceCallback callback) { + mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0, + new DeactivateDataCallRequest(cid, reasonRadioShutDown, isHandover, callback)) + .sendToTarget(); + } + + @Override + public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, + IDataServiceCallback callback) { + mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, mSlotId, 0, + new SetInitialAttachApnRequest(dataProfile, isRoaming, callback)) + .sendToTarget(); + } + + @Override + public void setDataProfile(List<DataProfile> dps, boolean isRoaming, + IDataServiceCallback callback) { + mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, mSlotId, 0, + new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget(); + } + + @Override + public void getDataCallList(IDataServiceCallback callback) { + mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, mSlotId, 0, + callback).sendToTarget(); + } + + @Override + public void registerForDataCallListChanged(IDataServiceCallback callback) { + if (callback == null) { + loge("Callback is null"); + return; + } + mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, mSlotId, + 0, callback).sendToTarget(); + } + + @Override + public void unregisterForDataCallListChanged(IDataServiceCallback callback) { + if (callback == null) { + loge("Callback is null"); + return; + } + mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, mSlotId, + 0, callback).sendToTarget(); + } + } + + private void log(String s) { + Rlog.d(TAG, s); + } + + private void loge(String s) { + Rlog.e(TAG, s); + } +} diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java new file mode 100644 index 000000000000..b6a81f94028b --- /dev/null +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -0,0 +1,172 @@ +/* + * Copyright 2017 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.telephony.data; + +import android.annotation.IntDef; +import android.annotation.SystemApi; +import android.os.RemoteException; +import android.telephony.Rlog; +import android.telephony.data.DataService.DataServiceProvider; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; +import java.util.List; + +/** + * Data service callback, which is for bound data service to invoke for solicited and unsolicited + * response. The caller is responsible to create a callback object for each single asynchronous + * request. + * + * @hide + */ +@SystemApi +public class DataServiceCallback { + + private static final String mTag = DataServiceCallback.class.getSimpleName(); + + /** + * Result of data requests + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({RESULT_SUCCESS, RESULT_ERROR_UNSUPPORTED, RESULT_ERROR_INVALID_ARG, RESULT_ERROR_BUSY, + RESULT_ERROR_ILLEGAL_STATE}) + public @interface Result {} + + /** Request is completed successfully */ + public static final int RESULT_SUCCESS = 0; + /** Request is not support */ + public static final int RESULT_ERROR_UNSUPPORTED = 1; + /** Request contains invalid arguments */ + public static final int RESULT_ERROR_INVALID_ARG = 2; + /** Service is busy */ + public static final int RESULT_ERROR_BUSY = 3; + /** Request sent in illegal state */ + public static final int RESULT_ERROR_ILLEGAL_STATE = 4; + + private final WeakReference<IDataServiceCallback> mCallback; + + /** @hide */ + public DataServiceCallback(IDataServiceCallback callback) { + mCallback = new WeakReference<>(callback); + } + + /** + * Called to indicate result for the request {@link DataServiceProvider#setupDataCall(int, + * DataProfile, boolean, boolean, boolean, DataServiceCallback)}. + * + * @param result The result code. Must be one of the {@link Result}. + * @param response Setup data call response. + */ + public void onSetupDataCallComplete(@Result int result, DataCallResponse response) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onSetupDataCallComplete(result, response); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onSetupDataCallComplete on the remote"); + } + } + } + + /** + * Called to indicate result for the request {@link DataServiceProvider#deactivateDataCall(int, + * boolean, boolean, DataServiceCallback)}. + * + * @param result The result code. Must be one of the {@link Result}. + */ + public void onDeactivateDataCallComplete(@Result int result) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onDeactivateDataCallComplete(result); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onDeactivateDataCallComplete on the remote"); + } + } + } + + /** + * Called to indicate result for the request {@link DataServiceProvider#setInitialAttachApn( + * DataProfile, boolean, DataServiceCallback)}. + * + * @param result The result code. Must be one of the {@link Result}. + */ + public void onSetInitialAttachApnComplete(@Result int result) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onSetInitialAttachApnComplete(result); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onSetInitialAttachApnComplete on the remote"); + } + } + } + + /** + * Called to indicate result for the request {@link DataServiceProvider#setDataProfile(List, + * boolean, DataServiceCallback)}. + * + * @param result The result code. Must be one of the {@link Result}. + */ + @SystemApi + public void onSetDataProfileComplete(@Result int result) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onSetDataProfileComplete(result); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onSetDataProfileComplete on the remote"); + } + } + } + + /** + * Called to indicate result for the request {@link DataServiceProvider#getDataCallList( + * DataServiceCallback)}. + * + * @param result The result code. Must be one of the {@link Result}. + * @param dataCallList List of the current active data connection. + */ + public void onGetDataCallListComplete(@Result int result, List<DataCallResponse> dataCallList) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onGetDataCallListComplete(result, dataCallList); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onGetDataCallListComplete on the remote"); + } + } + } + + /** + * Called to indicate that data connection list changed. + * + * @param dataCallList List of the current active data connection. + */ + public void onDataCallListChanged(List<DataCallResponse> dataCallList) { + IDataServiceCallback callback = mCallback.get(); + if (callback != null) { + try { + callback.onDataCallListChanged(dataCallList); + } catch (RemoteException e) { + Rlog.e(mTag, "Failed to onDataCallListChanged on the remote"); + } + } + } +} diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl new file mode 100644 index 000000000000..4eaaa252da02 --- /dev/null +++ b/telephony/java/android/telephony/data/IDataService.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2017 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.telephony.data; + +import android.net.LinkProperties; +import android.telephony.data.DataProfile; +import android.telephony.data.IDataServiceCallback; + +/** + * {@hide} + */ +oneway interface IDataService +{ + void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming, + boolean allowRoaming, boolean isHandover, in LinkProperties linkProperties, + IDataServiceCallback callback); + void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover, + IDataServiceCallback callback); + void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming, + IDataServiceCallback callback); + void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback); + void getDataCallList(IDataServiceCallback callback); + void registerForDataCallListChanged(IDataServiceCallback callback); + void unregisterForDataCallListChanged(IDataServiceCallback callback); +} diff --git a/telephony/java/android/telephony/data/IDataServiceCallback.aidl b/telephony/java/android/telephony/data/IDataServiceCallback.aidl new file mode 100644 index 000000000000..856185b2974f --- /dev/null +++ b/telephony/java/android/telephony/data/IDataServiceCallback.aidl @@ -0,0 +1,33 @@ +/* + * Copyright 2017 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.telephony.data; + +import android.telephony.data.DataCallResponse; + +/** + * The call back interface + * @hide + */ +oneway interface IDataServiceCallback +{ + void onSetupDataCallComplete(int result, in DataCallResponse dataCallResponse); + void onDeactivateDataCallComplete(int result); + void onSetInitialAttachApnComplete(int result); + void onSetDataProfileComplete(int result); + void onGetDataCallListComplete(int result, in List<DataCallResponse> dataCallList); + void onDataCallListChanged(in List<DataCallResponse> dataCallList); +} diff --git a/telephony/java/android/telephony/data/InterfaceAddress.java b/telephony/java/android/telephony/data/InterfaceAddress.java deleted file mode 100644 index 00d212a54c6f..000000000000 --- a/telephony/java/android/telephony/data/InterfaceAddress.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2017 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.telephony.data; - -import android.annotation.SystemApi; -import android.net.NetworkUtils; -import android.os.Parcel; -import android.os.Parcelable; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * This class represents a Network Interface address. In short it's an IP address, a subnet mask - * when the address is an IPv4 one. An IP address and a network prefix length in the case of IPv6 - * address. - * - * @hide - */ -@SystemApi -public final class InterfaceAddress implements Parcelable { - - private final InetAddress mInetAddress; - - private final int mPrefixLength; - - /** - * @param inetAddress A {@link InetAddress} of the address - * @param prefixLength The network prefix length for this address. - */ - public InterfaceAddress(InetAddress inetAddress, int prefixLength) { - mInetAddress = inetAddress; - mPrefixLength = prefixLength; - } - - /** - * @param address The address in string format - * @param prefixLength The network prefix length for this address. - * @throws UnknownHostException - */ - public InterfaceAddress(String address, int prefixLength) throws UnknownHostException { - InetAddress ia; - try { - ia = NetworkUtils.numericToInetAddress(address); - } catch (IllegalArgumentException e) { - throw new UnknownHostException("Non-numeric ip addr=" + address); - } - mInetAddress = ia; - mPrefixLength = prefixLength; - } - - public InterfaceAddress(Parcel source) { - mInetAddress = (InetAddress) source.readSerializable(); - mPrefixLength = source.readInt(); - } - - /** - * @return an InetAddress for this address. - */ - public InetAddress getAddress() { return mInetAddress; } - - /** - * @return The network prefix length for this address. - */ - public int getNetworkPrefixLength() { return mPrefixLength; } - - @Override - public boolean equals (Object o) { - if (this == o) return true; - - if (o == null || !(o instanceof InterfaceAddress)) { - return false; - } - - InterfaceAddress other = (InterfaceAddress) o; - return this.mInetAddress.equals(other.mInetAddress) - && this.mPrefixLength == other.mPrefixLength; - } - - @Override - public int hashCode() { - return mInetAddress.hashCode() * 31 + mPrefixLength * 37; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public String toString() { - return mInetAddress + "/" + mPrefixLength; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeSerializable(mInetAddress); - dest.writeInt(mPrefixLength); - } - - public static final Parcelable.Creator<InterfaceAddress> CREATOR = - new Parcelable.Creator<InterfaceAddress>() { - @Override - public InterfaceAddress createFromParcel(Parcel source) { - return new InterfaceAddress(source); - } - - @Override - public InterfaceAddress[] newArray(int size) { - return new InterfaceAddress[size]; - } - }; -} diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java index 29849c1f9ccd..6975354c8af1 100644 --- a/telephony/java/android/telephony/euicc/EuiccCardManager.java +++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java @@ -15,14 +15,31 @@ */ package android.telephony.euicc; +import android.annotation.IntDef; +import android.annotation.Nullable; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.service.euicc.EuiccProfileInfo; import android.util.Log; +import com.android.internal.telephony.euicc.IAuthenticateServerCallback; +import com.android.internal.telephony.euicc.ICancelSessionCallback; import com.android.internal.telephony.euicc.IEuiccCardController; import com.android.internal.telephony.euicc.IGetAllProfilesCallback; +import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback; +import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback; +import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback; +import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback; +import com.android.internal.telephony.euicc.IListNotificationsCallback; +import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback; +import com.android.internal.telephony.euicc.IPrepareDownloadCallback; +import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback; +import com.android.internal.telephony.euicc.IRetrieveNotificationCallback; +import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * EuiccCardManager is the application interface to an eSIM card. @@ -34,6 +51,35 @@ import com.android.internal.telephony.euicc.IGetAllProfilesCallback; public class EuiccCardManager { private static final String TAG = "EuiccCardManager"; + /** Reason for canceling a profile download session */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "CANCEL_REASON_" }, value = { + CANCEL_REASON_END_USER_REJECTED, + CANCEL_REASON_POSTPONED, + CANCEL_REASON_TIMEOUT, + CANCEL_REASON_PPR_NOT_ALLOWED + }) + public @interface CancelReason {} + + /** + * The end user has rejected the download. The profile will be put into the error state and + * cannot be downloaded again without the operator's change. + */ + public static final int CANCEL_REASON_END_USER_REJECTED = 0; + + /** The download has been postponed and can be restarted later. */ + public static final int CANCEL_REASON_POSTPONED = 1; + + /** The download has been timed out and can be restarted later. */ + public static final int CANCEL_REASON_TIMEOUT = 2; + + /** + * The profile to be downloaded cannot be installed due to its policy rule is not allowed by + * the RAT (Rules Authorisation Table) on the eUICC or by other installed profiles. The + * download can be restarted later. + */ + public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; + /** Result code of execution with no error. */ public static final int RESULT_OK = 0; @@ -85,4 +131,298 @@ public class EuiccCardManager { throw e.rethrowFromSystemServer(); } } + + /** + * Gets Rules Authorisation Table. + * + * @param callback the callback to get the result code and the rule authorisation table. + */ + public void getRulesAuthTable(ResultCallback<EuiccRulesAuthTable> callback) { + try { + getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), + new IGetRulesAuthTableCallback.Stub() { + @Override + public void onComplete(int resultCode, EuiccRulesAuthTable rat) { + callback.onComplete(resultCode, rat); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling getRulesAuthTable", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the eUICC challenge for new profile downloading. + * + * @param callback the callback to get the result code and the challenge. + */ + public void getEuiccChallenge(ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), + new IGetEuiccChallengeCallback.Stub() { + @Override + public void onComplete(int resultCode, byte[] challenge) { + callback.onComplete(resultCode, challenge); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling getEuiccChallenge", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading. + * + * @param callback the callback to get the result code and the info1. + */ + public void getEuiccInfo1(ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), + new IGetEuiccInfo1Callback.Stub() { + @Override + public void onComplete(int resultCode, byte[] info) { + callback.onComplete(resultCode, info); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling getEuiccInfo1", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading. + * + * @param callback the callback to get the result code and the info2. + */ + public void getEuiccInfo2(ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), + new IGetEuiccInfo2Callback.Stub() { + @Override + public void onComplete(int resultCode, byte[] info) { + callback.onComplete(resultCode, info); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling getEuiccInfo2", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Authenticates the SM-DP+ server by the eUICC. + * + * @param matchingId the activation code token defined in GSMA RSP v2.0+ or empty when it is not + * required. + * @param serverSigned1 ASN.1 data in byte array signed and returned by the SM-DP+ server. + * @param serverSignature1 ASN.1 data in byte array indicating a SM-DP+ signature which is + * returned by SM-DP+ server. + * @param euiccCiPkIdToBeUsed ASN.1 data in byte array indicating CI Public Key Identifier to be + * used by the eUICC for signature which is returned by SM-DP+ server. This is defined in + * GSMA RSP v2.0+. + * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by + * SM-DP+ server. + * @param callback the callback to get the result code and a byte array which represents a + * {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+. + */ + public void authenticateServer(String matchingId, byte[] serverSigned1, + byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate, + ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().authenticateServer( + mContext.getOpPackageName(), + matchingId, + serverSigned1, + serverSignature1, + euiccCiPkIdToBeUsed, + serverCertificate, + new IAuthenticateServerCallback.Stub() { + @Override + public void onComplete(int resultCode, byte[] response) { + callback.onComplete(resultCode, response); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling authenticateServer", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Prepares the profile download request sent to SM-DP+. + * + * @param hashCc the hash of confirmation code. It can be null if there is no confirmation code + * required. + * @param smdpSigned2 ASN.1 data in byte array indicating the data to be signed by the SM-DP+ + * returned by SM-DP+ server. + * @param smdpSignature2 ASN.1 data in byte array indicating the SM-DP+ signature returned by + * SM-DP+ server. + * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned + * by SM-DP+ server. + * @param callback the callback to get the result code and a byte array which represents a + * {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+ + */ + public void prepareDownload(@Nullable byte[] hashCc, byte[] smdpSigned2, + byte[] smdpSignature2, byte[] smdpCertificate, ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().prepareDownload( + mContext.getOpPackageName(), + hashCc, + smdpSigned2, + smdpSignature2, + smdpCertificate, + new IPrepareDownloadCallback.Stub() { + @Override + public void onComplete(int resultCode, byte[] response) { + callback.onComplete(resultCode, response); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling prepareDownload", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Loads a downloaded bound profile package onto the eUICC. + * + * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server. + * @param callback the callback to get the result code and a byte array which represents a + * {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+. + */ + public void loadBoundProfilePackage(byte[] boundProfilePackage, + ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().loadBoundProfilePackage( + mContext.getOpPackageName(), + boundProfilePackage, + new ILoadBoundProfilePackageCallback.Stub() { + @Override + public void onComplete(int resultCode, byte[] response) { + callback.onComplete(resultCode, response); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling loadBoundProfilePackage", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Cancels the current profile download session. + * + * @param transactionId the transaction ID returned by SM-DP+ server. + * @param reason the cancel reason. + * @param callback the callback to get the result code and an byte[] which represents a + * {@code CancelSessionResponse} defined in GSMA RSP v2.0+. + */ + public void cancelSession(byte[] transactionId, @CancelReason int reason, + ResultCallback<byte[]> callback) { + try { + getIEuiccCardController().cancelSession( + mContext.getOpPackageName(), + transactionId, + reason, + new ICancelSessionCallback.Stub() { + @Override + public void onComplete(int resultCode, byte[] response) { + callback.onComplete(resultCode, response); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling cancelSession", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Lists all notifications of the given {@code notificationEvents}. + * + * @param events bits of the event types ({@link EuiccNotification.Event}) to list. + * @param callback the callback to get the result code and the list of notifications. + */ + public void listNotifications(@EuiccNotification.Event int events, + ResultCallback<EuiccNotification[]> callback) { + try { + getIEuiccCardController().listNotifications(mContext.getOpPackageName(), events, + new IListNotificationsCallback.Stub() { + @Override + public void onComplete(int resultCode, EuiccNotification[] notifications) { + callback.onComplete(resultCode, notifications); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling listNotifications", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves contents of all notification of the given {@code events}. + * + * @param events bits of the event types ({@link EuiccNotification.Event}) to list. + * @param callback the callback to get the result code and the list of notifications. + */ + public void retrieveNotificationList(@EuiccNotification.Event int events, + ResultCallback<EuiccNotification[]> callback) { + try { + getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), events, + new IRetrieveNotificationListCallback.Stub() { + @Override + public void onComplete(int resultCode, EuiccNotification[] notifications) { + callback.onComplete(resultCode, notifications); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling retrieveNotificationList", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves the content of a notification of the given {@code seqNumber}. + * + * @param seqNumber the sequence number of the notification. + * @param callback the callback to get the result code and the notification. + */ + public void retrieveNotification(int seqNumber, ResultCallback<EuiccNotification> callback) { + try { + getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), seqNumber, + new IRetrieveNotificationCallback.Stub() { + @Override + public void onComplete(int resultCode, EuiccNotification notification) { + callback.onComplete(resultCode, notification); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling retrieveNotification", e); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Removes a notification from eUICC. + * + * @param seqNumber the sequence number of the notification. + * @param callback the callback to get the result code. + */ + public void removeNotificationFromList(int seqNumber, ResultCallback<Void> callback) { + try { + getIEuiccCardController().removeNotificationFromList( + mContext.getOpPackageName(), + seqNumber, + new IRemoveNotificationFromListCallback.Stub() { + @Override + public void onComplete(int resultCode) { + callback.onComplete(resultCode, null); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Error calling removeNotificationFromList", e); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/android/telephony/euicc/EuiccNotification.aidl index d750363b9cd2..dad770da260d 100644 --- a/telephony/java/android/telephony/data/InterfaceAddress.aidl +++ b/telephony/java/android/telephony/euicc/EuiccNotification.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * limitations under the License. */ -/** @hide */ -package android.telephony.data; +package android.telephony.euicc; -parcelable InterfaceAddress; +parcelable EuiccNotification; diff --git a/core/java/android/os/Seccomp.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl index f14e93fe9403..9785a4533c5b 100644 --- a/core/java/android/os/Seccomp.java +++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl @@ -14,11 +14,6 @@ * limitations under the License. */ -package android.os; +package android.telephony.euicc; -/** - * @hide - */ -public final class Seccomp { - public static final native void setPolicy(); -} +parcelable EuiccRulesAuthTable;
\ No newline at end of file diff --git a/telephony/java/android/telephony/euicc/EuiccRat.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java index 6a56503ac380..7efe04364280 100644 --- a/telephony/java/android/telephony/euicc/EuiccRat.java +++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java @@ -35,7 +35,7 @@ import java.util.Arrays; * * TODO(b/35851809): Make this a @SystemApi. */ -public final class EuiccRat implements Parcelable { +public final class EuiccRulesAuthTable implements Parcelable { /** Profile policy rule flags */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = { @@ -50,7 +50,7 @@ public final class EuiccRat implements Parcelable { private final CarrierIdentifier[][] mCarrierIds; private final int[] mPolicyRuleFlags; - /** This is used to build new {@link EuiccRat} instance. */ + /** This is used to build new {@link EuiccRulesAuthTable} instance. */ public static final class Builder { private int[] mPolicyRules; private CarrierIdentifier[][] mCarrierIds; @@ -72,7 +72,7 @@ public final class EuiccRat implements Parcelable { * Builds the RAT instance. This builder should not be used anymore after this method is * called, otherwise {@link NullPointerException} will be thrown. */ - public EuiccRat build() { + public EuiccRulesAuthTable build() { if (mPosition != mPolicyRules.length) { throw new IllegalStateException( "Not enough rules are added, expected: " @@ -80,7 +80,7 @@ public final class EuiccRat implements Parcelable { + ", added: " + mPosition); } - return new EuiccRat(mPolicyRules, mCarrierIds, mPolicyRuleFlags); + return new EuiccRulesAuthTable(mPolicyRules, mCarrierIds, mPolicyRuleFlags); } /** @@ -125,7 +125,8 @@ public final class EuiccRat implements Parcelable { return true; } - private EuiccRat(int[] policyRules, CarrierIdentifier[][] carrierIds, int[] policyRuleFlags) { + private EuiccRulesAuthTable(int[] policyRules, CarrierIdentifier[][] carrierIds, + int[] policyRuleFlags) { mPolicyRules = policyRules; mCarrierIds = carrierIds; mPolicyRuleFlags = policyRuleFlags; @@ -207,7 +208,7 @@ public final class EuiccRat implements Parcelable { return false; } - EuiccRat that = (EuiccRat) obj; + EuiccRulesAuthTable that = (EuiccRulesAuthTable) obj; if (mCarrierIds.length != that.mCarrierIds.length) { return false; } @@ -234,7 +235,7 @@ public final class EuiccRat implements Parcelable { && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags); } - private EuiccRat(Parcel source) { + private EuiccRulesAuthTable(Parcel source) { mPolicyRules = source.createIntArray(); int len = mPolicyRules.length; mCarrierIds = new CarrierIdentifier[len][]; @@ -244,16 +245,16 @@ public final class EuiccRat implements Parcelable { mPolicyRuleFlags = source.createIntArray(); } - public static final Creator<EuiccRat> CREATOR = - new Creator<EuiccRat>() { + public static final Creator<EuiccRulesAuthTable> CREATOR = + new Creator<EuiccRulesAuthTable>() { @Override - public EuiccRat createFromParcel(Parcel source) { - return new EuiccRat(source); + public EuiccRulesAuthTable createFromParcel(Parcel source) { + return new EuiccRulesAuthTable(source); } @Override - public EuiccRat[] newArray(int size) { - return new EuiccRat[size]; + public EuiccRulesAuthTable[] newArray(int size) { + return new EuiccRulesAuthTable[size]; } }; } diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 8230eafc2e4d..aaa0f08594d1 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -26,12 +26,14 @@ import android.telephony.CarrierConfigManager; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MMTelFeature; import android.telephony.ims.feature.RcsFeature; +import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; import android.util.SparseArray; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsRcsFeature; +import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsServiceController; import com.android.internal.annotations.VisibleForTesting; @@ -113,6 +115,12 @@ public class ImsService extends Service { throws RemoteException { ImsService.this.removeImsFeature(slotId, featureType, c); } + + @Override + public IImsRegistration getRegistration(int slotId) throws RemoteException { + ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId); + return r != null ? r.getBinder() : null; + } }; /** @@ -174,6 +182,8 @@ public class ImsService extends Service { f.setSlotId(slotId); f.addImsFeatureStatusCallback(c); addImsFeature(slotId, featureType, f); + // TODO: Remove once new onFeatureReady AIDL is merged in. + f.onFeatureReady(); } private void addImsFeature(int slotId, int featureType, ImsFeature f) { @@ -236,4 +246,13 @@ public class ImsService extends Service { public @Nullable RcsFeature onCreateRcsFeature(int slotId) { return null; } + + /** + * @param slotId The slot that is associated with the IMS Registration. + * @return the ImsRegistration implementation associated with the slot. + * @hide + */ + public ImsRegistrationImplBase getRegistration(int slotId) { + return new ImsRegistrationImplBase(); + } } diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index ca4a210e30cc..d47cea3097f3 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -96,7 +96,7 @@ public abstract class ImsFeature { new WeakHashMap<IImsFeatureStatusCallback, Boolean>()); private @ImsState int mState = STATE_NOT_AVAILABLE; private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; - private Context mContext; + protected Context mContext; public void setContext(Context context) { mContext = context; diff --git a/telephony/java/android/telephony/ims/internal/ImsService.java b/telephony/java/android/telephony/ims/internal/ImsService.java index b7c8ca0f9799..afaf33294d8a 100644 --- a/telephony/java/android/telephony/ims/internal/ImsService.java +++ b/telephony/java/android/telephony/ims/internal/ImsService.java @@ -24,7 +24,6 @@ import android.telephony.CarrierConfigManager; import android.telephony.ims.internal.aidl.IImsConfig; import android.telephony.ims.internal.aidl.IImsMmTelFeature; import android.telephony.ims.internal.aidl.IImsRcsFeature; -import android.telephony.ims.internal.aidl.IImsRegistration; import android.telephony.ims.internal.aidl.IImsServiceController; import android.telephony.ims.internal.aidl.IImsServiceControllerListener; import android.telephony.ims.internal.feature.ImsFeature; @@ -32,11 +31,12 @@ import android.telephony.ims.internal.feature.MmTelFeature; import android.telephony.ims.internal.feature.RcsFeature; import android.telephony.ims.internal.stub.ImsConfigImplBase; import android.telephony.ims.internal.stub.ImsFeatureConfiguration; -import android.telephony.ims.internal.stub.ImsRegistrationImplBase; +import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; import android.util.SparseArray; import com.android.ims.internal.IImsFeatureStatusCallback; +import com.android.ims.internal.IImsRegistration; import com.android.internal.annotations.VisibleForTesting; /** diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl b/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl index 8332bc024e37..43f5098af3ca 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl +++ b/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl @@ -24,4 +24,5 @@ import com.android.ims.internal.IImsCallSession; */ oneway interface IImsMmTelListener { void onIncomingCall(IImsCallSession c); + void onVoiceMessageCountUpdate(int count); }
\ No newline at end of file diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl index 8afb95588b01..82a85254bbca 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl @@ -18,12 +18,12 @@ package android.telephony.ims.internal.aidl; import android.telephony.ims.internal.aidl.IImsMmTelFeature; import android.telephony.ims.internal.aidl.IImsRcsFeature; -import android.telephony.ims.internal.aidl.IImsRegistration; import android.telephony.ims.internal.aidl.IImsConfig; import android.telephony.ims.internal.aidl.IImsServiceControllerListener; import android.telephony.ims.internal.stub.ImsFeatureConfiguration; import com.android.ims.internal.IImsFeatureStatusCallback; +import com.android.ims.internal.IImsRegistration; /** * See ImsService and MmTelFeature for more information. diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java index 4d188734c10e..5dbf077ee7c5 100644 --- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java @@ -18,7 +18,7 @@ package android.telephony.ims.internal.feature; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.ims.internal.stub.ImsRegistrationImplBase; +import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.ArraySet; import java.util.ArrayList; diff --git a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java index 2f350c86a6f6..057c9a86d04e 100644 --- a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java @@ -28,8 +28,8 @@ import android.telephony.ims.internal.aidl.IImsCallSessionListener; import android.telephony.ims.internal.aidl.IImsCapabilityCallback; import android.telephony.ims.internal.aidl.IImsMmTelFeature; import android.telephony.ims.internal.aidl.IImsMmTelListener; -import android.telephony.ims.internal.stub.ImsRegistrationImplBase; import android.telephony.ims.internal.aidl.IImsSmsListener; +import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.ims.stub.ImsEcbmImplBase; import android.telephony.ims.stub.ImsMultiEndpointImplBase; import android.telephony.ims.stub.ImsUtImplBase; @@ -261,6 +261,15 @@ public class MmTelFeature extends ImsFeature { } /** + * Updates the Listener when the voice message count for IMS has changed. + * @param count an integer representing the new message count. + */ + @Override + public void onVoiceMessageCountUpdate(int count) { + + } + + /** * Called when the IMS provider receives an incoming call. * @param c The {@link ImsCallSession} associated with the new call. */ diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 558b009ab4c2..42af08365f61 100644 --- a/telephony/java/android/telephony/ims/internal/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -14,16 +14,19 @@ * limitations under the License */ -package android.telephony.ims.internal.stub; +package android.telephony.ims.stub; import android.annotation.IntDef; +import android.net.Uri; +import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.telephony.ims.internal.aidl.IImsRegistration; -import android.telephony.ims.internal.aidl.IImsRegistrationCallback; import android.util.Log; import com.android.ims.ImsReasonInfo; +import com.android.ims.internal.IImsRegistration; +import com.android.ims.internal.IImsRegistrationCallback; +import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -62,23 +65,25 @@ public class ImsRegistrationImplBase { // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current // state. + // The unknown state is set as the initialization state. This is so that we do not call back + // with NOT_REGISTERED in the case where the ImsService has not updated the registration state + // yet. + private static final int REGISTRATION_STATE_UNKNOWN = -1; private static final int REGISTRATION_STATE_NOT_REGISTERED = 0; private static final int REGISTRATION_STATE_REGISTERING = 1; private static final int REGISTRATION_STATE_REGISTERED = 2; - /** * Callback class for receiving Registration callback events. + * @hide */ - public static class Callback extends IImsRegistrationCallback.Stub { - + public static class Callback { /** * Notifies the framework when the IMS Provider is connected to the IMS network. * * @param imsRadioTech the radio access technology. Valid values are defined in * {@link ImsRegistrationTech}. */ - @Override public void onRegistered(@ImsRegistrationTech int imsRadioTech) { } @@ -88,7 +93,6 @@ public class ImsRegistrationImplBase { * @param imsRadioTech the radio access technology. Valid values are defined in * {@link ImsRegistrationTech}. */ - @Override public void onRegistering(@ImsRegistrationTech int imsRadioTech) { } @@ -97,7 +101,6 @@ public class ImsRegistrationImplBase { * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. */ - @Override public void onDeregistered(ImsReasonInfo info) { } @@ -108,10 +111,19 @@ public class ImsRegistrationImplBase { * @param imsRadioTech The {@link ImsRegistrationTech} type that has failed * @param info A {@link ImsReasonInfo} that identifies the reason for failure. */ - @Override public void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { } + + /** + * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when + * it changes. + * @param uris new array of subscriber {@link Uri}s that are associated with this IMS + * subscription. + */ + public void onSubscriberAssociatedUriChanged(Uri[] uris) { + + } } private final IImsRegistration mBinder = new IImsRegistration.Stub() { @@ -139,9 +151,9 @@ public class ImsRegistrationImplBase { private @ImsRegistrationTech int mConnectionType = REGISTRATION_TECH_NONE; // Locked on mLock - private int mRegistrationState = REGISTRATION_STATE_NOT_REGISTERED; - // Locked on mLock - private ImsReasonInfo mLastDisconnectCause; + private int mRegistrationState = REGISTRATION_STATE_UNKNOWN; + // Locked on mLock, create unspecified disconnect cause. + private ImsReasonInfo mLastDisconnectCause = new ImsReasonInfo(); public final IImsRegistration getBinder() { return mBinder; @@ -221,6 +233,17 @@ public class ImsRegistrationImplBase { }); } + public final void onSubscriberAssociatedUriChanged(Uri[] uris) { + mCallbacks.broadcast((c) -> { + try { + c.onSubscriberAssociatedUriChanged(uris); + } catch (RemoteException e) { + Log.w(LOG_TAG, e + " " + "onSubscriberAssociatedUriChanged() - Skipping " + + "callback."); + } + }); + } + private void updateToState(@ImsRegistrationTech int connType, int newState) { synchronized (mLock) { mConnectionType = connType; @@ -241,7 +264,8 @@ public class ImsRegistrationImplBase { } } - private @ImsRegistrationTech int getConnectionType() { + @VisibleForTesting + public final @ImsRegistrationTech int getConnectionType() { synchronized (mLock) { return mConnectionType; } @@ -271,6 +295,10 @@ public class ImsRegistrationImplBase { c.onRegistered(getConnectionType()); break; } + case REGISTRATION_STATE_UNKNOWN: { + // Do not callback if the state has not been updated yet by the ImsService. + break; + } } } } diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java index 489c208a0d46..693aaff8ce0f 100644 --- a/telephony/java/com/android/ims/ImsCallProfile.java +++ b/telephony/java/com/android/ims/ImsCallProfile.java @@ -351,7 +351,7 @@ public class ImsCallProfile implements Parcelable { mServiceType = in.readInt(); mCallType = in.readInt(); mCallExtras = in.readBundle(); - mMediaProfile = in.readParcelable(null); + mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader()); } public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() { diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRegistration.aidl b/telephony/java/com/android/ims/internal/IImsRegistration.aidl index 687b7ca408d5..6de264ec90fb 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsRegistration.aidl +++ b/telephony/java/com/android/ims/internal/IImsRegistration.aidl @@ -15,10 +15,9 @@ */ -package android.telephony.ims.internal.aidl; +package com.android.ims.internal; -import android.telephony.ims.internal.aidl.IImsRegistrationCallback; -import android.telephony.ims.internal.stub.ImsFeatureConfiguration; +import com.android.ims.internal.IImsRegistrationCallback; /** * See ImsRegistration for more information. diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRegistrationCallback.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl index a50575b96865..5f21167422dc 100644 --- a/telephony/java/android/telephony/ims/internal/aidl/IImsRegistrationCallback.aidl +++ b/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl @@ -15,8 +15,9 @@ */ -package android.telephony.ims.internal.aidl; +package com.android.ims.internal; +import android.net.Uri; import android.telephony.ims.internal.stub.ImsFeatureConfiguration; import com.android.ims.ImsReasonInfo; @@ -31,4 +32,5 @@ oneway interface IImsRegistrationCallback { void onRegistering(int imsRadioTech); void onDeregistered(in ImsReasonInfo info); void onTechnologyChangeFailed(int imsRadioTech, in ImsReasonInfo info); + void onSubscriberAssociatedUriChanged(in Uri[] uris); }
\ No newline at end of file diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl index 857089fac33a..7ac25ac13fbe 100644 --- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl +++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl @@ -18,6 +18,7 @@ package com.android.ims.internal; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsMMTelFeature; +import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsRcsFeature; /** @@ -29,4 +30,5 @@ interface IImsServiceController { IImsMMTelFeature createMMTelFeature(int slotId, in IImsFeatureStatusCallback c); IImsRcsFeature createRcsFeature(int slotId, in IImsFeatureStatusCallback c); void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c); + IImsRegistration getRegistration(int slotId); } diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl index ac161397af04..8e3f4c070d2e 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -46,5 +46,6 @@ oneway interface IPhoneStateListener { void onVoiceActivationStateChanged(int activationState); void onDataActivationStateChanged(int activationState); void onCarrierNetworkChange(in boolean active); + void onUserMobileDataStateChanged(in boolean enabled); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index b0af9a84553b..fba82ee17f77 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -40,6 +40,7 @@ import android.telephony.TelephonyHistogram; import android.telephony.VisualVoicemailSmsFilterSettings; import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsRcsFeature; +import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.OperatorInfo; @@ -808,6 +809,11 @@ interface ITelephony { IImsRcsFeature getRcsFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback); /** + * Returns the IImsRegistration associated with the slot and feature specified. + */ + IImsRegistration getImsRegistration(int slotId, int feature); + + /** * Set the network selection mode to automatic. * * @param subId the id of the subscription to update. @@ -1317,6 +1323,34 @@ interface ITelephony { */ List<CarrierIdentifier> getAllowedCarriers(int slotIndex); + /** + * Returns carrier id of the given subscription. + * <p>To recognize carrier as a first class identity, assign each carrier with a canonical + * integer a.k.a carrier id. + * + * @param subId The subscription id + * @return Carrier id of given subscription id. return {@link #UNKNOWN_CARRIER_ID} if + * subscription is unavailable or carrier cannot be identified. + * @throws IllegalStateException if telephony service is unavailable. + * @hide + */ + int getSubscriptionCarrierId(int subId); + + /** + * Returns carrier name of the given subscription. + * <p>Carrier name is a user-facing name of carrier id {@link #getSubscriptionCarrierId(int)}, + * usually the brand name of the subsidiary (e.g. T-Mobile). Each carrier could configure + * multiple {@link #getSimOperatorName() SPN} but should have a single carrier name. + * Carrier name is not canonical identity, use {@link #getSubscriptionCarrierId(int)} instead. + * <p>Returned carrier name is unlocalized. + * + * @return Carrier name of given subscription id. return {@code null} if subscription is + * unavailable or carrier cannot be identified. + * @throws IllegalStateException if telephony service is unavailable. + * @hide + */ + String getSubscriptionCarrierName(int subId); + /** * Action set from carrier signalling broadcast receivers to enable/disable metered apns * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 75d8f3fcb9b6..188167cc14f6 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -69,4 +69,5 @@ interface ITelephonyRegistry { int activationState, int activationType); void notifySubscriptionInfoChanged(); void notifyCarrierNetworkChange(in boolean active); + void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state); } diff --git a/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl new file mode 100644 index 000000000000..8a77bf127f9e --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface IAuthenticateServerCallback { + void onComplete(int resultCode, in byte[] response); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl new file mode 100644 index 000000000000..f6b99e2b9801 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface ICancelSessionCallback { + void onComplete(int resultCode, in byte[] response); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl index 2846a1ad1f9f..ba9b05e2654f 100644 --- a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl @@ -17,8 +17,41 @@ package com.android.internal.telephony.euicc; import com.android.internal.telephony.euicc.IGetAllProfilesCallback; +import com.android.internal.telephony.euicc.IAuthenticateServerCallback; +import com.android.internal.telephony.euicc.ICancelSessionCallback; +import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback; +import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback; +import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback; +import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback; +import com.android.internal.telephony.euicc.IListNotificationsCallback; +import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback; +import com.android.internal.telephony.euicc.IPrepareDownloadCallback; +import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback; +import com.android.internal.telephony.euicc.IRetrieveNotificationCallback; +import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback; /** @hide */ interface IEuiccCardController { oneway void getAllProfiles(String callingPackage, in IGetAllProfilesCallback callback); + oneway void getRulesAuthTable(String callingPackage, in IGetRulesAuthTableCallback callback); + oneway void getEuiccChallenge(String callingPackage, in IGetEuiccChallengeCallback callback); + oneway void getEuiccInfo1(String callingPackage, in IGetEuiccInfo1Callback callback); + oneway void getEuiccInfo2(String callingPackage, in IGetEuiccInfo2Callback callback); + oneway void authenticateServer(String callingPackage, String matchingId, + in byte[] serverSigned1, in byte[] serverSignature1, in byte[] euiccCiPkIdToBeUsed, + in byte[] serverCertificatein, in IAuthenticateServerCallback callback); + oneway void prepareDownload(String callingPackage, in byte[] hashCc, in byte[] smdpSigned2, + in byte[] smdpSignature2, in byte[] smdpCertificate, in IPrepareDownloadCallback callback); + oneway void loadBoundProfilePackage(String callingPackage, in byte[] boundProfilePackage, + in ILoadBoundProfilePackageCallback callback); + oneway void cancelSession(String callingPackage, in byte[] transactionId, int reason, + in ICancelSessionCallback callback); + oneway void listNotifications(String callingPackage, int events, + in IListNotificationsCallback callback); + oneway void retrieveNotificationList(String callingPackage, int events, + in IRetrieveNotificationListCallback callback); + oneway void retrieveNotification(String callingPackage, int seqNumber, + in IRetrieveNotificationCallback callback); + oneway void removeNotificationFromList(String callingPackage, int seqNumber, + in IRemoveNotificationFromListCallback callback); } diff --git a/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl new file mode 100644 index 000000000000..5ffb3400912a --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface IGetEuiccChallengeCallback { + void onComplete(int resultCode, in byte[] challenge); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl new file mode 100644 index 000000000000..9592acb6d330 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface IGetEuiccInfo1Callback { + void onComplete(int resultCode, in byte[] info); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl new file mode 100644 index 000000000000..5256b35c7516 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface IGetEuiccInfo2Callback { + void onComplete(int resultCode, in byte[] info); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl new file mode 100644 index 000000000000..58f0bde65b86 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +import android.telephony.euicc.EuiccRulesAuthTable; + +/** @hide */ +oneway interface IGetRulesAuthTableCallback { + void onComplete(int resultCode, in EuiccRulesAuthTable rat); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl new file mode 100644 index 000000000000..65aa302a6a64 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +import android.telephony.euicc.EuiccNotification; + +/** @hide */ +oneway interface IListNotificationsCallback { + void onComplete(int resultCode, in EuiccNotification[] notifications); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl new file mode 100644 index 000000000000..4ad7081c2e67 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface ILoadBoundProfilePackageCallback { + void onComplete(int resultCode, in byte[] response); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl new file mode 100644 index 000000000000..c0351841084e --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +/** @hide */ +oneway interface IPrepareDownloadCallback { + void onComplete(int resultCode, in byte[] response); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl new file mode 100644 index 000000000000..b22d0da5dc5f --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +import android.telephony.euicc.EuiccNotification; + +/** @hide */ +oneway interface IRemoveNotificationFromListCallback { + void onComplete(int resultCode); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl new file mode 100644 index 000000000000..dd8889a94143 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +import android.telephony.euicc.EuiccNotification; + +/** @hide */ +oneway interface IRetrieveNotificationCallback { + void onComplete(int resultCode, in EuiccNotification notification); +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl new file mode 100644 index 000000000000..bc4e451329af --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.telephony.euicc; + +import android.telephony.euicc.EuiccNotification; + +/** @hide */ +oneway interface IRetrieveNotificationListCallback { + void onComplete(int resultCode, in EuiccNotification[] notifications); +} diff --git a/legacy-test/Android.bp b/test-base/Android.bp index 1173bc6e656b..a42dc5a10ec9 100644 --- a/legacy-test/Android.bp +++ b/test-base/Android.bp @@ -14,30 +14,52 @@ // limitations under the License. // -// Build the legacy-test library -// ============================= +// Build the android.test.base library +// =================================== // This contains the junit.framework and android.test classes that were in // Android API level 25 excluding those from android.test.runner. // Also contains the com.android.internal.util.Predicate[s] classes. java_library { - name: "legacy-test", + name: "android.test.base", srcs: ["src/**/*.java"], no_framework_libs: true, + hostdex: true, libs: [ "framework", ], } -// Build the repackaged-legacy-test library -// ======================================== -// This contains repackaged versions of the classes from legacy-test. +// Build the legacy-test library +// ============================= +// This contains the junit.framework and android.test classes that were in +// Android API level 25 excluding those from android.test.runner. +// Also contains the com.android.internal.util.Predicate[s] classes. +java_library { + name: "legacy-test", + static_libs: ["android.test.base"], + + no_framework_libs: true, + libs: [ + "framework", + ], +} + +// Build the repackaged.android.test.base library +// ============================================== +// This contains repackaged versions of the classes from +// android.test.base. java_library_static { - name: "repackaged-legacy-test", + name: "repackaged.android.test.base", - static_libs: ["legacy-test"], + static_libs: ["android.test.base"], + + no_framework_libs: true, + libs: [ + "framework", + ], jarjar_rules: "jarjar-rules.txt", } @@ -56,7 +78,7 @@ java_library_static { ], static_libs: [ - "android.test.runner", + "android.test.runner-minus-junit", "android.test.mock", ], diff --git a/legacy-test/Android.mk b/test-base/Android.mk index 793bbe859eda..25c3d7646df6 100644 --- a/legacy-test/Android.mk +++ b/test-base/Android.mk @@ -31,79 +31,81 @@ LOCAL_JAVA_LIBRARIES := \ LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src -LEGACY_TEST_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/api.txt -LEGACY_TEST_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/removed.txt +ANDROID_TEST_BASE_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/api.txt +ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/removed.txt -LEGACY_TEST_API_FILE := $(LOCAL_PATH)/api/legacy-test-current.txt -LEGACY_TEST_REMOVED_API_FILE := $(LOCAL_PATH)/api/legacy-test-removed.txt +ANDROID_TEST_BASE_API_FILE := $(LOCAL_PATH)/api/android-test-base-current.txt +ANDROID_TEST_BASE_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-base-removed.txt LOCAL_DROIDDOC_OPTIONS:= \ -stubpackages android.test:android.test.suitebuilder.annotation:com.android.internal.util:junit.framework \ -stubsourceonly \ - -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/src \ + -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/src \ -nodocs \ - -api $(LEGACY_TEST_OUTPUT_API_FILE) \ - -removedApi $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE) \ + -api $(ANDROID_TEST_BASE_OUTPUT_API_FILE) \ + -removedApi $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) \ LOCAL_UNINSTALLABLE_MODULE := true -LOCAL_MODULE := legacy-test-api-stubs-gen +LOCAL_MODULE := android-test-base-api-stubs-gen include $(BUILD_DROIDDOC) # Remember the target that will trigger the code generation. -legacy_test_api_gen_stamp := $(full_target) +android_test_base_gen_stamp := $(full_target) # Add some additional dependencies -$(LEGACY_TEST_OUTPUT_API_FILE): $(full_target) -$(LEGACY_TEST_OUTPUT_REMOVED_API_FILE): $(full_target) +$(ANDROID_TEST_BASE_OUTPUT_API_FILE): $(full_target) +$(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE): $(full_target) -# Build the legacy.test.stubs library -# =================================== +# Build the android.test.base.stubs library +# ========================================= include $(CLEAR_VARS) -LOCAL_MODULE := legacy.test.stubs +LOCAL_MODULE := android.test.base.stubs LOCAL_SOURCE_FILES_ALL_GENERATED := true +LOCAL_SDK_VERSION := current # Make sure to run droiddoc first to generate the stub source files. -LOCAL_ADDITIONAL_DEPENDENCIES := $(legacy_test_api_gen_stamp) +LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_base_gen_stamp) +android_test_base_gen_stamp := include $(BUILD_STATIC_JAVA_LIBRARY) # Archive a copy of the classes.jar in SDK build. -$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):legacy.test.stubs.jar) +$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.base.stubs.jar) -# Check that the legacy.test.stubs library has not changed -# ======================================================== +# Check that the android.test.base.stubs library has not changed +# ============================================================== # Check that the API we're building hasn't changed from the not-yet-released # SDK version. $(eval $(call check-api, \ - check-legacy-test-api-current, \ - $(LEGACY_TEST_API_FILE), \ - $(LEGACY_TEST_OUTPUT_API_FILE), \ - $(LEGACY_TEST_REMOVED_API_FILE), \ - $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE), \ + check-android-test-base-api-current, \ + $(ANDROID_TEST_BASE_API_FILE), \ + $(ANDROID_TEST_BASE_OUTPUT_API_FILE), \ + $(ANDROID_TEST_BASE_REMOVED_API_FILE), \ + $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE), \ -error 2 -error 3 -error 4 -error 5 -error 6 \ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -error 25 -error 26 -error 27, \ - cat $(LOCAL_PATH)/api/apicheck_msg_legacy_test.txt, \ - check-legacy-test-api, \ - $(call doc-timestamp-for,legacy-test-api-stubs-gen) \ + cat $(LOCAL_PATH)/api/apicheck_msg_android_test_base.txt, \ + check-android-test-base-api, \ + $(call doc-timestamp-for,android-test-base-api-stubs-gen) \ )) -.PHONY: check-legacy-test-api -checkapi: check-legacy-test-api +.PHONY: check-android-test-base-api +checkapi: check-android-test-base-api -.PHONY: update-legacy-test-api -update-api: update-legacy-test-api +.PHONY: update-android-test-base-api +update-api: update-android-test-base-api -update-legacy-test-api: $(LEGACY_TEST_OUTPUT_API_FILE) | $(ACP) +update-android-test-base-api: $(ANDROID_TEST_BASE_OUTPUT_API_FILE) | $(ACP) @echo Copying current.txt - $(hide) $(ACP) $(LEGACY_TEST_OUTPUT_API_FILE) $(LEGACY_TEST_API_FILE) + $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_API_FILE) $(ANDROID_TEST_BASE_API_FILE) @echo Copying removed.txt - $(hide) $(ACP) $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE) $(LEGACY_TEST_REMOVED_API_FILE) + $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE) ifeq ($(HOST_OS),linux) # Build the legacy-performance-test-hostdex library diff --git a/legacy-test/api/legacy-test-current.txt b/test-base/api/android-test-base-current.txt index 7ebd6aa8a4a2..7ebd6aa8a4a2 100644 --- a/legacy-test/api/legacy-test-current.txt +++ b/test-base/api/android-test-base-current.txt diff --git a/legacy-test/api/legacy-test-removed.txt b/test-base/api/android-test-base-removed.txt index e69de29bb2d1..e69de29bb2d1 100644 --- a/legacy-test/api/legacy-test-removed.txt +++ b/test-base/api/android-test-base-removed.txt diff --git a/legacy-test/api/apicheck_msg_legacy_test.txt b/test-base/api/apicheck_msg_android_test_base.txt index ad5f2359b8b1..144aecc21bce 100644 --- a/legacy-test/api/apicheck_msg_legacy_test.txt +++ b/test-base/api/apicheck_msg_android_test_base.txt @@ -6,10 +6,10 @@ To make these errors go away, you have two choices: 1) You can add "@hide" javadoc comments to the methods, etc. listed in the errors above. - 2) You can update legacy-test-current.txt by executing the following command: - make update-legacy-test-api + 2) You can update android-test-base-current.txt by executing the following command: + make update-android-test-base-api - To submit the revised legacy-test-current.txt to the main Android repository, + To submit the revised android-test-base-current.txt to the main Android repository, you will need approval. ****************************** diff --git a/legacy-test/jarjar-rules.txt b/test-base/jarjar-rules.txt index fd8555c8931c..fd8555c8931c 100644 --- a/legacy-test/jarjar-rules.txt +++ b/test-base/jarjar-rules.txt diff --git a/legacy-test/src/android/test/AndroidTestCase.java b/test-base/src/android/test/AndroidTestCase.java index 1e6bd9c14fd9..1e6bd9c14fd9 100644 --- a/legacy-test/src/android/test/AndroidTestCase.java +++ b/test-base/src/android/test/AndroidTestCase.java diff --git a/legacy-test/src/android/test/FlakyTest.java b/test-base/src/android/test/FlakyTest.java index 4e5c4e35a8c6..4e5c4e35a8c6 100644 --- a/legacy-test/src/android/test/FlakyTest.java +++ b/test-base/src/android/test/FlakyTest.java diff --git a/legacy-test/src/android/test/InstrumentationTestCase.java b/test-base/src/android/test/InstrumentationTestCase.java index 6b79314a4385..6b79314a4385 100644 --- a/legacy-test/src/android/test/InstrumentationTestCase.java +++ b/test-base/src/android/test/InstrumentationTestCase.java diff --git a/legacy-test/src/android/test/InstrumentationTestSuite.java b/test-base/src/android/test/InstrumentationTestSuite.java index a53fa267f1e1..a53fa267f1e1 100644 --- a/legacy-test/src/android/test/InstrumentationTestSuite.java +++ b/test-base/src/android/test/InstrumentationTestSuite.java diff --git a/legacy-test/src/android/test/PerformanceTestCase.java b/test-base/src/android/test/PerformanceTestCase.java index 65bd4a48f7f5..65bd4a48f7f5 100644 --- a/legacy-test/src/android/test/PerformanceTestCase.java +++ b/test-base/src/android/test/PerformanceTestCase.java diff --git a/legacy-test/src/android/test/RepetitiveTest.java b/test-base/src/android/test/RepetitiveTest.java index 6a7130e68e61..6a7130e68e61 100644 --- a/legacy-test/src/android/test/RepetitiveTest.java +++ b/test-base/src/android/test/RepetitiveTest.java diff --git a/legacy-test/src/android/test/UiThreadTest.java b/test-base/src/android/test/UiThreadTest.java index cd06ab890074..cd06ab890074 100644 --- a/legacy-test/src/android/test/UiThreadTest.java +++ b/test-base/src/android/test/UiThreadTest.java diff --git a/legacy-test/src/android/test/package.html b/test-base/src/android/test/package.html index 5be51359630e..5be51359630e 100644 --- a/legacy-test/src/android/test/package.html +++ b/test-base/src/android/test/package.html diff --git a/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java b/test-base/src/android/test/suitebuilder/annotation/LargeTest.java index dc77ee6b2739..dc77ee6b2739 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java +++ b/test-base/src/android/test/suitebuilder/annotation/LargeTest.java diff --git a/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java b/test-base/src/android/test/suitebuilder/annotation/MediumTest.java index b941da03ac9a..b941da03ac9a 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java +++ b/test-base/src/android/test/suitebuilder/annotation/MediumTest.java diff --git a/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java b/test-base/src/android/test/suitebuilder/annotation/SmallTest.java index d3c74f019b53..d3c74f019b53 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java +++ b/test-base/src/android/test/suitebuilder/annotation/SmallTest.java diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java b/test-base/src/android/test/suitebuilder/annotation/Smoke.java index aac293796be1..aac293796be1 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java +++ b/test-base/src/android/test/suitebuilder/annotation/Smoke.java diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java b/test-base/src/android/test/suitebuilder/annotation/Suppress.java index 629a3cf4a2cd..629a3cf4a2cd 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java +++ b/test-base/src/android/test/suitebuilder/annotation/Suppress.java diff --git a/legacy-test/src/android/test/suitebuilder/annotation/package.html b/test-base/src/android/test/suitebuilder/annotation/package.html index ffba2e9bf980..ffba2e9bf980 100644 --- a/legacy-test/src/android/test/suitebuilder/annotation/package.html +++ b/test-base/src/android/test/suitebuilder/annotation/package.html diff --git a/legacy-test/src/com/android/internal/util/Predicate.java b/test-base/src/com/android/internal/util/Predicate.java index e87f489f4670..e87f489f4670 100644 --- a/legacy-test/src/com/android/internal/util/Predicate.java +++ b/test-base/src/com/android/internal/util/Predicate.java diff --git a/legacy-test/src/junit/MODULE_LICENSE_CPL b/test-base/src/junit/MODULE_LICENSE_CPL index e69de29bb2d1..e69de29bb2d1 100644 --- a/legacy-test/src/junit/MODULE_LICENSE_CPL +++ b/test-base/src/junit/MODULE_LICENSE_CPL diff --git a/legacy-test/src/junit/README.android b/test-base/src/junit/README.android index 1384a1fedda2..1384a1fedda2 100644 --- a/legacy-test/src/junit/README.android +++ b/test-base/src/junit/README.android diff --git a/legacy-test/src/junit/cpl-v10.html b/test-base/src/junit/cpl-v10.html index 36aa208d4a29..36aa208d4a29 100644 --- a/legacy-test/src/junit/cpl-v10.html +++ b/test-base/src/junit/cpl-v10.html diff --git a/legacy-test/src/junit/framework/Assert.java b/test-base/src/junit/framework/Assert.java index 3dcc23d71c19..3dcc23d71c19 100644 --- a/legacy-test/src/junit/framework/Assert.java +++ b/test-base/src/junit/framework/Assert.java diff --git a/legacy-test/src/junit/framework/AssertionFailedError.java b/test-base/src/junit/framework/AssertionFailedError.java index 0d7802c431c6..0d7802c431c6 100644 --- a/legacy-test/src/junit/framework/AssertionFailedError.java +++ b/test-base/src/junit/framework/AssertionFailedError.java diff --git a/legacy-test/src/junit/framework/ComparisonCompactor.java b/test-base/src/junit/framework/ComparisonCompactor.java index e540f03b87d3..e540f03b87d3 100644 --- a/legacy-test/src/junit/framework/ComparisonCompactor.java +++ b/test-base/src/junit/framework/ComparisonCompactor.java diff --git a/legacy-test/src/junit/framework/ComparisonFailure.java b/test-base/src/junit/framework/ComparisonFailure.java index 507799328a44..507799328a44 100644 --- a/legacy-test/src/junit/framework/ComparisonFailure.java +++ b/test-base/src/junit/framework/ComparisonFailure.java diff --git a/legacy-test/src/junit/framework/Protectable.java b/test-base/src/junit/framework/Protectable.java index e1432370cfaf..e1432370cfaf 100644 --- a/legacy-test/src/junit/framework/Protectable.java +++ b/test-base/src/junit/framework/Protectable.java diff --git a/legacy-test/src/junit/framework/Test.java b/test-base/src/junit/framework/Test.java index a016ee8308f1..a016ee8308f1 100644 --- a/legacy-test/src/junit/framework/Test.java +++ b/test-base/src/junit/framework/Test.java diff --git a/legacy-test/src/junit/framework/TestCase.java b/test-base/src/junit/framework/TestCase.java index b047ec9e1afc..b047ec9e1afc 100644 --- a/legacy-test/src/junit/framework/TestCase.java +++ b/test-base/src/junit/framework/TestCase.java diff --git a/legacy-test/src/junit/framework/TestFailure.java b/test-base/src/junit/framework/TestFailure.java index 6662b1fab1b2..6662b1fab1b2 100644 --- a/legacy-test/src/junit/framework/TestFailure.java +++ b/test-base/src/junit/framework/TestFailure.java diff --git a/legacy-test/src/junit/framework/TestListener.java b/test-base/src/junit/framework/TestListener.java index 9b6944361b9d..9b6944361b9d 100644 --- a/legacy-test/src/junit/framework/TestListener.java +++ b/test-base/src/junit/framework/TestListener.java diff --git a/legacy-test/src/junit/framework/TestResult.java b/test-base/src/junit/framework/TestResult.java index 3052e94074fd..3052e94074fd 100644 --- a/legacy-test/src/junit/framework/TestResult.java +++ b/test-base/src/junit/framework/TestResult.java diff --git a/legacy-test/src/junit/framework/TestSuite.java b/test-base/src/junit/framework/TestSuite.java index 336efd1800d7..336efd1800d7 100644 --- a/legacy-test/src/junit/framework/TestSuite.java +++ b/test-base/src/junit/framework/TestSuite.java diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 8eddec48611b..b1ae40e17b9d 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -24,7 +24,6 @@ java_library { no_framework_libs: true, libs: [ "framework", - "legacy-test", ], } diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt index b0e4beaf5a4c..f6f79139d511 120000 --- a/test-mock/jarjar-rules.txt +++ b/test-mock/jarjar-rules.txt @@ -1 +1 @@ -../legacy-test/jarjar-rules.txt
\ No newline at end of file +../test-base/jarjar-rules.txt
\ No newline at end of file diff --git a/test-runner/Android.bp b/test-runner/Android.bp index 104ae8236368..dfaeed5e271e 100644 --- a/test-runner/Android.bp +++ b/test-runner/Android.bp @@ -24,11 +24,28 @@ java_library { no_framework_libs: true, libs: [ "framework", - "legacy-test", + "android.test.base", "android.test.mock", ], } +// Build the android.test.runner-minus-junit library +// ================================================= +// This is provided solely for use by the legacy-android-test module. +java_library { + name: "android.test.runner-minus-junit", + + srcs: ["src/android/**/*.java"], + + no_framework_libs: true, + libs: [ + "framework", + "android.test.base", + "android.test.mock", + "junit", + ], +} + // Build the repackaged.android.test.runner library // ================================================ java_library_static { diff --git a/test-runner/Android.mk b/test-runner/Android.mk index 6cf2d5646ffb..cdc7756d5754 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -26,7 +26,7 @@ LOCAL_JAVA_LIBRARIES := \ core-oj \ core-libart \ framework \ - legacy-test \ + android.test.base \ android.test.mock \ LOCAL_MODULE_CLASS := JAVA_LIBRARIES @@ -65,7 +65,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := android.test.runner.stubs LOCAL_JAVA_LIBRARIES := \ - legacy.test.stubs \ + android.test.base.stubs \ android.test.mock.stubs \ LOCAL_SOURCE_FILES_ALL_GENERATED := true diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt index b0e4beaf5a4c..f6f79139d511 120000 --- a/test-runner/jarjar-rules.txt +++ b/test-runner/jarjar-rules.txt @@ -1 +1 @@ -../legacy-test/jarjar-rules.txt
\ No newline at end of file +../test-base/jarjar-rules.txt
\ No newline at end of file diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java index efc01f2ace6f..f6c5532363e8 100644 --- a/tests/net/java/android/net/IpSecConfigTest.java +++ b/tests/net/java/android/net/IpSecConfigTest.java @@ -36,19 +36,16 @@ public class IpSecConfigTest { public void testDefaults() throws Exception { IpSecConfig c = new IpSecConfig(); assertEquals(IpSecTransform.MODE_TRANSPORT, c.getMode()); - assertEquals("", c.getLocalAddress()); - assertEquals("", c.getRemoteAddress()); + assertEquals("", c.getSourceAddress()); + assertEquals("", c.getDestinationAddress()); assertNull(c.getNetwork()); assertEquals(IpSecTransform.ENCAP_NONE, c.getEncapType()); assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getEncapSocketResourceId()); assertEquals(0, c.getEncapRemotePort()); assertEquals(0, c.getNattKeepaliveInterval()); - for (int direction : - new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}) { - assertNull(c.getEncryption(direction)); - assertNull(c.getAuthentication(direction)); - assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId(direction)); - } + assertNull(c.getEncryption()); + assertNull(c.getAuthentication()); + assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId()); } @Test @@ -57,34 +54,21 @@ public class IpSecConfigTest { IpSecConfig c = new IpSecConfig(); c.setMode(IpSecTransform.MODE_TUNNEL); - c.setLocalAddress("0.0.0.0"); - c.setRemoteAddress("1.2.3.4"); + c.setSourceAddress("0.0.0.0"); + c.setDestinationAddress("1.2.3.4"); c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP); c.setEncapSocketResourceId(7); c.setEncapRemotePort(22); c.setNattKeepaliveInterval(42); c.setEncryption( - IpSecTransform.DIRECTION_OUT, new IpSecAlgorithm( IpSecAlgorithm.CRYPT_AES_CBC, new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF})); c.setAuthentication( - IpSecTransform.DIRECTION_OUT, new IpSecAlgorithm( IpSecAlgorithm.AUTH_HMAC_MD5, new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0})); - c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984); - c.setEncryption( - IpSecTransform.DIRECTION_IN, - new IpSecAlgorithm( - IpSecAlgorithm.CRYPT_AES_CBC, - new byte[] {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF})); - c.setAuthentication( - IpSecTransform.DIRECTION_IN, - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_MD5, - new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1})); - c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99); + c.setSpiResourceId(1984); assertParcelingIsLossless(c); } diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java index 0f40b4562b0d..cc3366fbc832 100644 --- a/tests/net/java/android/net/IpSecManagerTest.java +++ b/tests/net/java/android/net/IpSecManagerTest.java @@ -81,15 +81,13 @@ public class IpSecManagerTest { IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( - eq(IpSecTransform.DIRECTION_IN), eq(GOOGLE_DNS_4.getHostAddress()), eq(DROID_SPI), anyObject())) .thenReturn(spiResp); IpSecManager.SecurityParameterIndex droidSpi = - mIpSecManager.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_IN, GOOGLE_DNS_4, DROID_SPI); + mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI); assertEquals(DROID_SPI, droidSpi.getSpi()); droidSpi.close(); @@ -103,15 +101,13 @@ public class IpSecManagerTest { IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( - eq(IpSecTransform.DIRECTION_OUT), eq(GOOGLE_DNS_4.getHostAddress()), eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX), anyObject())) .thenReturn(spiResp); IpSecManager.SecurityParameterIndex randomSpi = - mIpSecManager.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4); + mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); assertEquals(DROID_SPI, randomSpi.getSpi()); @@ -124,16 +120,15 @@ public class IpSecManagerTest { * Throws resource unavailable exception */ @Test - public void testAllocSpiResUnavaiableExeption() throws Exception { + public void testAllocSpiResUnavailableException() throws Exception { IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0); when(mMockIpSecService.allocateSecurityParameterIndex( - anyInt(), anyString(), anyInt(), anyObject())) + anyString(), anyInt(), anyObject())) .thenReturn(spiResp); try { - mIpSecManager.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4); + mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); fail("ResourceUnavailableException was not thrown"); } catch (IpSecManager.ResourceUnavailableException e) { } @@ -143,15 +138,14 @@ public class IpSecManagerTest { * Throws spi unavailable exception */ @Test - public void testAllocSpiSpiUnavaiableExeption() throws Exception { + public void testAllocSpiSpiUnavailableException() throws Exception { IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0); when(mMockIpSecService.allocateSecurityParameterIndex( - anyInt(), anyString(), anyInt(), anyObject())) + anyString(), anyInt(), anyObject())) .thenReturn(spiResp); try { - mIpSecManager.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4); + mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); fail("ResourceUnavailableException was not thrown"); } catch (IpSecManager.ResourceUnavailableException e) { } @@ -163,8 +157,7 @@ public class IpSecManagerTest { @Test public void testRequestAllocInvalidSpi() throws Exception { try { - mIpSecManager.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4, 0); + mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0); fail("Able to allocate invalid spi"); } catch (IllegalArgumentException e) { } diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java index 473dc538f09d..9aad413c354b 100644 --- a/tests/net/java/android/net/MacAddressTest.java +++ b/tests/net/java/android/net/MacAddressTest.java @@ -67,7 +67,7 @@ public class MacAddressTest { assertEquals(msg, t.expectedType, got); if (got != MacAddress.TYPE_UNKNOWN) { - assertEquals(got, MacAddress.fromBytes(t.addr).addressType()); + assertEquals(got, MacAddress.fromBytes(t.addr).getAddressType()); } } } @@ -191,7 +191,7 @@ public class MacAddressTest { assertTrue(stringRepr + " expected to be a locally assigned address", mac.isLocallyAssigned()); - assertEquals(MacAddress.TYPE_UNICAST, mac.addressType()); + assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType()); assertTrue(stringRepr + " expected to begin with " + expectedLocalOui, stringRepr.startsWith(expectedLocalOui)); } diff --git a/tests/net/java/android/net/NetworkTest.java b/tests/net/java/android/net/NetworkTest.java index bacf986b3627..94d01e91d03b 100644 --- a/tests/net/java/android/net/NetworkTest.java +++ b/tests/net/java/android/net/NetworkTest.java @@ -147,9 +147,9 @@ public class NetworkTest { // Adjust as necessary to test an implementation's specific constants. // When running with runtest, "adb logcat -s TestRunner" can be useful. - assertEquals(4311403230L, one.getNetworkHandle()); - assertEquals(8606370526L, two.getNetworkHandle()); - assertEquals(12901337822L, three.getNetworkHandle()); + assertEquals(7700664333L, one.getNetworkHandle()); + assertEquals(11995631629L, two.getNetworkHandle()); + assertEquals(16290598925L, three.getNetworkHandle()); } private static <T> void assertNotEqual(T t1, T t2) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2b0349c6fa83..b8e37f3a10ea 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1392,39 +1392,75 @@ public class ConnectivityServiceTest { return null; } - void expectAvailableCallbacks( - MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) { + // Expects onAvailable and the callbacks that follow it. These are: + // - onSuspended, iff the network was suspended when the callbacks fire. + // - onCapabilitiesChanged. + // - onLinkPropertiesChanged. + // + // @param agent the network to expect the callbacks on. + // @param expectSuspended whether to expect a SUSPENDED callback. + // @param expectValidated the expected value of the VALIDATED capability in the + // onCapabilitiesChanged callback. + // @param timeoutMs how long to wait for the callbacks. + void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, + boolean expectValidated, int timeoutMs) { expectCallback(CallbackState.AVAILABLE, agent, timeoutMs); if (expectSuspended) { expectCallback(CallbackState.SUSPENDED, agent, timeoutMs); } - expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs); + if (expectValidated) { + expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); + } else { + expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent); + } expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs); } - void expectAvailableCallbacks(MockNetworkAgent agent) { - expectAvailableCallbacks(agent, false, TIMEOUT_MS); + // Expects the available callbacks (validated), plus onSuspended. + void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) { + expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS); + } + + void expectAvailableCallbacksValidated(MockNetworkAgent agent) { + expectAvailableCallbacks(agent, false, true, TIMEOUT_MS); + } + + void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) { + expectAvailableCallbacks(agent, false, false, TIMEOUT_MS); } - void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) { - expectAvailableCallbacks(agent, true, TIMEOUT_MS); + // Expects the available callbacks (where the onCapabilitiesChanged must contain the + // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the + // one we just sent. + // TODO: this is likely a bug. Fix it and remove this method. + void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) { + expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS); + NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); + expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS); + NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); + assertEquals(nc1, nc2); } - void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) { - expectAvailableCallbacks(agent, false, TIMEOUT_MS); + // Expects the available callbacks where the onCapabilitiesChanged must not have validated, + // then expects another onCapabilitiesChanged that has the validated bit set. This is used + // when a network connects and satisfies a callback, and then immediately validates. + void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) { + expectAvailableCallbacksUnvalidated(agent); expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); } - void expectCapabilitiesWith(int capability, MockNetworkAgent agent) { + NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) { CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; assertTrue(nc.hasCapability(capability)); + return nc; } - void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) { + NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) { CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; assertFalse(nc.hasCapability(capability)); + return nc; } void assertNoCallback() { @@ -1461,8 +1497,8 @@ public class ConnectivityServiceTest { ConditionVariable cv = waitForConnectivityBroadcasts(1); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(false); - genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); - cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); + genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); waitFor(cv); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); @@ -1476,8 +1512,8 @@ public class ConnectivityServiceTest { cv = waitForConnectivityBroadcasts(2); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); - wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); waitFor(cv); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); @@ -1500,8 +1536,8 @@ public class ConnectivityServiceTest { // Test validated networks mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); @@ -1513,10 +1549,10 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); @@ -1552,32 +1588,32 @@ public class ConnectivityServiceTest { mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); mCellNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); mWiFiNetworkAgent.connect(true); // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. // We then get LOSING when wifi validates and cell is outscored. - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); mEthernetNetworkAgent.connect(true); - callback.expectAvailableCallbacks(mEthernetNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); mEthernetNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); for (int i = 0; i < 4; i++) { MockNetworkAgent oldNetwork, newNetwork; @@ -1594,7 +1630,7 @@ public class ConnectivityServiceTest { callback.expectCallback(CallbackState.LOSING, oldNetwork); // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no // longer lingering? - defaultCallback.expectAvailableCallbacks(newNetwork); + defaultCallback.expectAvailableCallbacksValidated(newNetwork); assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); } assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); @@ -1614,7 +1650,7 @@ public class ConnectivityServiceTest { // Disconnect our test networks. mWiFiNetworkAgent.disconnect(); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); mCellNetworkAgent.disconnect(); defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); @@ -1630,22 +1666,22 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(false); // Score: 10 - callback.expectAvailableCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); // Bring up wifi with a score of 20. // Cell stays up because it would satisfy the default request if it validated. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); // Score: 20 - callback.expectAvailableCallbacks(mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); // Bring up wifi with a score of 70. @@ -1653,33 +1689,33 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.adjustScore(50); mWiFiNetworkAgent.connect(false); // Score: 70 - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); // Tear down wifi. mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but // it's arguably correct to linger it, since it was the default network before it validated. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); mCellNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); @@ -1687,12 +1723,12 @@ public class ConnectivityServiceTest { // If a network is lingering, and we add and remove a request from it, resume lingering. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); @@ -1711,7 +1747,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); // Cell is now the default network. Pin it with a cell-specific request. noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 @@ -1720,8 +1756,8 @@ public class ConnectivityServiceTest { // Now connect wifi, and expect it to become the default network. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); // The default request is lingering on cell, but nothing happens to cell, and we send no // callbacks for it, because it's kept up by cellRequest. callback.assertNoCallback(); @@ -1737,14 +1773,14 @@ public class ConnectivityServiceTest { // Register a TRACK_DEFAULT request and check that it does not affect lingering. TestNetworkCallback trackDefaultCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(trackDefaultCallback); - trackDefaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); mEthernetNetworkAgent.connect(true); - callback.expectAvailableCallbacks(mEthernetNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); - trackDefaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); + trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); // Let linger run its course. callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs); @@ -1771,13 +1807,13 @@ public class ConnectivityServiceTest { // Bring up validated cell. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); // Bring up unvalidated wifi with explicitlySelected=true. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.explicitlySelected(false); mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // Cell Remains the default. assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); @@ -1800,7 +1836,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.explicitlySelected(false); mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the // network to disconnect. @@ -1811,7 +1847,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.explicitlySelected(false); mWiFiNetworkAgent.connect(true); - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); @@ -1820,7 +1856,7 @@ public class ConnectivityServiceTest { // TODO: fix this. mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); mEthernetNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); callback.assertNoCallback(); @@ -1993,7 +2029,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); mCellNetworkAgent.connectWithoutInternet(); - networkCallback.expectAvailableCallbacks(mCellNetworkAgent); + networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); verifyActiveNetwork(TRANSPORT_WIFI); // Test releasing NetworkRequest disconnects cellular with MMS @@ -2022,7 +2058,7 @@ public class ConnectivityServiceTest { MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); mmsNetworkAgent.connectWithoutInternet(); - networkCallback.expectAvailableCallbacks(mmsNetworkAgent); + networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent @@ -2049,7 +2085,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); String firstRedirectUrl = "http://example.com/firstPath"; mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); - captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); // Take down network. @@ -2062,7 +2098,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); String secondRedirectUrl = "http://example.com/secondPath"; mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); - captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); // Make captive portal disappear then revalidate. @@ -2072,9 +2108,7 @@ public class ConnectivityServiceTest { captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); // Expect NET_CAPABILITY_VALIDATED onAvailable callback. - validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); - // TODO: Investigate only sending available callbacks. - validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); // Break network connectivity. // Expect NET_CAPABILITY_VALIDATED onLost callback. @@ -2098,7 +2132,7 @@ public class ConnectivityServiceTest { // Bring up wifi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); // Check that calling startCaptivePortalApp does nothing. @@ -2109,7 +2143,7 @@ public class ConnectivityServiceTest { // Turn into a captive portal. mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302; mCm.reportNetworkConnectivity(wifiNetwork, false); - captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); // Check that startCaptivePortalApp sends the expected intent. @@ -2122,7 +2156,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); c.reportCaptivePortalDismissed(); - validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); mCm.unregisterNetworkCallback(validatedCallback); @@ -2165,7 +2199,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); // Expect NET_CAPABILITY_VALIDATED onAvailable callback. - validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); // But there should be no CaptivePortal callback. captivePortalCallback.assertNoCallback(); } @@ -2203,14 +2237,14 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent); - cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent); - cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent); - cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent); + cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertNoCallbacks(cFoo, cBar); mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); - cFoo.expectAvailableCallbacks(mWiFiNetworkAgent); + cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } @@ -2219,7 +2253,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - cBar.expectAvailableCallbacks(mWiFiNetworkAgent); + cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } @@ -2348,14 +2382,14 @@ public class ConnectivityServiceTest { // Bring up cell and expect CALLBACK_AVAILABLE. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); // Bring up wifi and expect CALLBACK_AVAILABLE. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); cellNetworkCallback.assertNoCallback(); - defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); + defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); // Bring down cell. Expect no default network callback, since it wasn't the default. mCellNetworkAgent.disconnect(); @@ -2365,7 +2399,7 @@ public class ConnectivityServiceTest { // Bring up cell. Expect no default network callback, since it won't be the default. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); defaultNetworkCallback.assertNoCallback(); // Bring down wifi. Expect the default network callback to notified of LOST wifi @@ -2373,7 +2407,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.disconnect(); cellNetworkCallback.assertNoCallback(); defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); mCellNetworkAgent.disconnect(); cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); @@ -2394,7 +2428,7 @@ public class ConnectivityServiceTest { // We should get onAvailable(), onCapabilitiesChanged(), and // onLinkPropertiesChanged() in rapid succession. Additionally, we // should get onCapabilitiesChanged() when the mobile network validates. - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); cellNetworkCallback.assertNoCallback(); // Update LinkProperties. @@ -2415,7 +2449,7 @@ public class ConnectivityServiceTest { mCm.registerDefaultNetworkCallback(dfltNetworkCallback); // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(), // as well as onNetworkSuspended() in rapid succession. - dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent); + dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true); dfltNetworkCallback.assertNoCallback(); mCm.unregisterNetworkCallback(dfltNetworkCallback); @@ -2455,18 +2489,18 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); assertTrue(isForegroundNetwork(mCellNetworkAgent)); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); // When wifi connects, cell lingers. - callback.expectAvailableCallbacks(mWiFiNetworkAgent); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); assertTrue(isForegroundNetwork(mCellNetworkAgent)); @@ -2490,8 +2524,8 @@ public class ConnectivityServiceTest { // is currently delivered before the onAvailable() callbacks. // TODO: Fix this. cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); - cellCallback.expectAvailableCallbacks(mCellNetworkAgent); - fgCallback.expectAvailableCallbacks(mCellNetworkAgent); + cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); // Expect a network capabilities update with FOREGROUND, because the most recent // request causes its state to change. callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); @@ -2511,7 +2545,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.disconnect(); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - fgCallback.expectAvailableCallbacks(mCellNetworkAgent); + fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertTrue(isForegroundNetwork(mCellNetworkAgent)); mCm.unregisterNetworkCallback(callback); @@ -2651,7 +2685,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); testFactory.expectAddRequests(2); // Because the cell request changes score twice. mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); testFactory.waitForNetworkRequests(2); assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. @@ -2742,16 +2776,15 @@ public class ConnectivityServiceTest { // Bring up validated cell. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); + cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); Network cellNetwork = mCellNetworkAgent.getNetwork(); // Bring up validated wifi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); // Fail validation on wifi. @@ -2772,18 +2805,18 @@ public class ConnectivityServiceTest { // that we switch back to cell. tracker.configRestrictsAvoidBadWifi = false; tracker.reevaluate(); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertEquals(mCm.getActiveNetwork(), cellNetwork); // Switch back to a restrictive carrier. tracker.configRestrictsAvoidBadWifi = true; tracker.reevaluate(); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mCm.getActiveNetwork(), wifiNetwork); // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. mCm.setAvoidUnvalidated(wifiNetwork); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( NET_CAPABILITY_VALIDATED)); assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( @@ -2794,9 +2827,8 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); wifiNetwork = mWiFiNetworkAgent.getNetwork(); // Fail validation on wifi and expect the dialog to appear. @@ -2810,7 +2842,7 @@ public class ConnectivityServiceTest { tracker.reevaluate(); // We now switch to cell. - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( NET_CAPABILITY_VALIDATED)); assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( @@ -2821,17 +2853,17 @@ public class ConnectivityServiceTest { // We switch to wifi and then to cell. Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); tracker.reevaluate(); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mCm.getActiveNetwork(), wifiNetwork); Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); tracker.reevaluate(); - defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); + defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertEquals(mCm.getActiveNetwork(), cellNetwork); // If cell goes down, we switch to wifi. mCellNetworkAgent.disconnect(); defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); validatedWifiCallback.assertNoCallback(); mCm.unregisterNetworkCallback(cellNetworkCallback); @@ -2873,7 +2905,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs); + networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs); // pass timeout and validate that UNAVAILABLE is not called networkCallback.assertNoCallback(); @@ -2894,7 +2926,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); final int assertTimeoutMs = 100; - networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs); + networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs); mWiFiNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); @@ -3381,7 +3413,7 @@ public class ConnectivityServiceTest { // Bring up wifi aware network. wifiAware.connect(false, false); - callback.expectAvailableCallbacks(wifiAware); + callback.expectAvailableCallbacksUnvalidated(wifiAware); assertNull(mCm.getActiveNetworkInfo()); assertNull(mCm.getActiveNetwork()); diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 2282c1319a9a..4fbb228e6e53 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -32,7 +32,6 @@ import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecSpiResponse; -import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.NetworkUtils; import android.os.Binder; @@ -54,14 +53,14 @@ import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public class IpSecServiceParameterizedTest { - private static final int TEST_SPI_OUT = 0xD1201D; - private static final int TEST_SPI_IN = TEST_SPI_OUT + 1; + private static final int TEST_SPI = 0xD1201D; - private final String mRemoteAddr; + private final String mDestinationAddr; + private final String mSourceAddr; @Parameterized.Parameters public static Collection ipSecConfigs() { - return Arrays.asList(new Object[][] {{"8.8.4.4"}, {"2601::10"}}); + return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}}); } private static final byte[] AEAD_KEY = { @@ -96,11 +95,9 @@ public class IpSecServiceParameterizedTest { private static final IpSecAlgorithm AEAD_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - private static final int[] DIRECTIONS = - new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT}; - - public IpSecServiceParameterizedTest(String remoteAddr) { - mRemoteAddr = remoteAddr; + public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) { + mSourceAddr = sourceAddr; + mDestinationAddr = destAddr; } @Before @@ -116,44 +113,30 @@ public class IpSecServiceParameterizedTest { @Test public void testIpSecServiceReserveSpi() throws Exception { - when(mMockNetd.ipSecAllocateSpi( - anyInt(), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - eq(mRemoteAddr), - eq(TEST_SPI_OUT))) - .thenReturn(TEST_SPI_OUT); + when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) + .thenReturn(TEST_SPI); IpSecSpiResponse spiResp = mIpSecService.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder()); + mDestinationAddr, TEST_SPI, new Binder()); assertEquals(IpSecManager.Status.OK, spiResp.status); - assertEquals(TEST_SPI_OUT, spiResp.spi); + assertEquals(TEST_SPI, spiResp.spi); } @Test public void testReleaseSecurityParameterIndex() throws Exception { - when(mMockNetd.ipSecAllocateSpi( - anyInt(), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - eq(mRemoteAddr), - eq(TEST_SPI_OUT))) - .thenReturn(TEST_SPI_OUT); + when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) + .thenReturn(TEST_SPI); IpSecSpiResponse spiResp = mIpSecService.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder()); + mDestinationAddr, TEST_SPI, new Binder()); mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId); verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(spiResp.resourceId), - anyInt(), - anyString(), - anyString(), - eq(TEST_SPI_OUT)); + eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); // Verify quota and RefcountedResource objects cleaned up IpSecService.UserRecord userRecord = @@ -169,17 +152,12 @@ public class IpSecServiceParameterizedTest { @Test public void testSecurityParameterIndexBinderDeath() throws Exception { - when(mMockNetd.ipSecAllocateSpi( - anyInt(), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - eq(mRemoteAddr), - eq(TEST_SPI_OUT))) - .thenReturn(TEST_SPI_OUT); + when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) + .thenReturn(TEST_SPI); IpSecSpiResponse spiResp = mIpSecService.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder()); + mDestinationAddr, TEST_SPI, new Binder()); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); @@ -190,11 +168,7 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(spiResp.resourceId), - anyInt(), - anyString(), - anyString(), - eq(TEST_SPI_OUT)); + eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); @@ -206,14 +180,12 @@ public class IpSecServiceParameterizedTest { } } - private int getNewSpiResourceId(int direction, String remoteAddress, int returnSpi) - throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt())) + private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception { + when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt())) .thenReturn(returnSpi); IpSecSpiResponse spi = mIpSecService.allocateSecurityParameterIndex( - direction, NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(), IpSecManager.INVALID_SECURITY_PARAMETER_INDEX, new Binder()); @@ -221,20 +193,14 @@ public class IpSecServiceParameterizedTest { } private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception { - config.setSpiResourceId( - IpSecTransform.DIRECTION_OUT, - getNewSpiResourceId(IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT)); - config.setSpiResourceId( - IpSecTransform.DIRECTION_IN, - getNewSpiResourceId(IpSecTransform.DIRECTION_IN, mRemoteAddr, TEST_SPI_IN)); - config.setRemoteAddress(mRemoteAddr); + config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI)); + config.setSourceAddress(mSourceAddr); + config.setDestinationAddress(mDestinationAddr); } private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception { - for (int direction : DIRECTIONS) { - config.setEncryption(direction, CRYPT_ALGO); - config.setAuthentication(direction, AUTH_ALGO); - } + config.setEncryption(CRYPT_ALGO); + config.setAuthentication(AUTH_ALGO); } @Test @@ -251,32 +217,10 @@ public class IpSecServiceParameterizedTest { .ipSecAddSecurityAssociation( eq(createTransformResp.resourceId), anyInt(), - eq(IpSecTransform.DIRECTION_OUT), anyString(), anyString(), anyLong(), - eq(TEST_SPI_OUT), - eq(IpSecAlgorithm.AUTH_HMAC_SHA256), - eq(AUTH_KEY), - anyInt(), - eq(IpSecAlgorithm.CRYPT_AES_CBC), - eq(CRYPT_KEY), - anyInt(), - eq(""), - eq(new byte[] {}), - eq(0), - anyInt(), - anyInt(), - anyInt()); - verify(mMockNetd) - .ipSecAddSecurityAssociation( - eq(createTransformResp.resourceId), - anyInt(), - eq(IpSecTransform.DIRECTION_IN), - anyString(), - anyString(), - anyLong(), - eq(TEST_SPI_IN), + eq(TEST_SPI), eq(IpSecAlgorithm.AUTH_HMAC_SHA256), eq(AUTH_KEY), anyInt(), @@ -296,8 +240,7 @@ public class IpSecServiceParameterizedTest { IpSecConfig ipSecConfig = new IpSecConfig(); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_OUT, AEAD_ALGO); - ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO); + ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); IpSecTransformResponse createTransformResp = mIpSecService.createTransportModeTransform(ipSecConfig, new Binder()); @@ -307,32 +250,10 @@ public class IpSecServiceParameterizedTest { .ipSecAddSecurityAssociation( eq(createTransformResp.resourceId), anyInt(), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - anyString(), - anyLong(), - eq(TEST_SPI_OUT), - eq(""), - eq(new byte[] {}), - eq(0), - eq(""), - eq(new byte[] {}), - eq(0), - eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM), - eq(AEAD_KEY), - anyInt(), - anyInt(), - anyInt(), - anyInt()); - verify(mMockNetd) - .ipSecAddSecurityAssociation( - eq(createTransformResp.resourceId), - anyInt(), - eq(IpSecTransform.DIRECTION_IN), anyString(), anyString(), anyLong(), - eq(TEST_SPI_IN), + eq(TEST_SPI), eq(""), eq(new byte[] {}), eq(0), @@ -359,18 +280,7 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI_OUT)); - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), - eq(IpSecTransform.DIRECTION_IN), - anyString(), - anyString(), - eq(TEST_SPI_IN)); + eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); // Verify quota and RefcountedResource objects cleaned up IpSecService.UserRecord userRecord = @@ -404,18 +314,7 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI_OUT)); - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), - eq(IpSecTransform.DIRECTION_IN), - anyString(), - anyString(), - eq(TEST_SPI_IN)); + eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); @@ -439,30 +338,22 @@ public class IpSecServiceParameterizedTest { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); int resourceId = createTransformResp.resourceId; - mIpSecService.applyTransportModeTransform(pfd, resourceId); + mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); verify(mMockNetd) .ipSecApplyTransportModeTransform( eq(pfd.getFileDescriptor()), eq(resourceId), - eq(IpSecTransform.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI_OUT)); - verify(mMockNetd) - .ipSecApplyTransportModeTransform( - eq(pfd.getFileDescriptor()), - eq(resourceId), - eq(IpSecTransform.DIRECTION_IN), + eq(IpSecManager.DIRECTION_OUT), anyString(), anyString(), - eq(TEST_SPI_IN)); + eq(TEST_SPI)); } @Test public void testRemoveTransportModeTransform() throws Exception { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); - mIpSecService.removeTransportModeTransform(pfd, 1); + mIpSecService.removeTransportModeTransforms(pfd); verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); } diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 0467989d8984..3eba881df427 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -105,9 +105,6 @@ public class IpSecServiceTest { private static final IpSecAlgorithm AEAD_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - private static final int[] DIRECTIONS = - new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT}; - static { try { INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0}); @@ -303,83 +300,75 @@ public class IpSecServiceTest { @Test public void testValidateAlgorithmsAuth() { - for (int direction : DIRECTIONS) { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthentication(direction, AUTH_ALGO); - mIpSecService.validateAlgorithms(config, direction); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) { - try { - config = new IpSecConfig(); - config.setAuthentication(direction, algo); - mIpSecService.validateAlgorithms(config, direction); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } + // Validate that correct algorithm type succeeds + IpSecConfig config = new IpSecConfig(); + config.setAuthentication(AUTH_ALGO); + mIpSecService.validateAlgorithms(config); + + // Validate that incorrect algorithm types fails + for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) { + try { + config = new IpSecConfig(); + config.setAuthentication(algo); + mIpSecService.validateAlgorithms(config); + fail("Did not throw exception on invalid algorithm type"); + } catch (IllegalArgumentException expected) { } } } @Test public void testValidateAlgorithmsCrypt() { - for (int direction : DIRECTIONS) { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setEncryption(direction, CRYPT_ALGO); - mIpSecService.validateAlgorithms(config, direction); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) { - try { - config = new IpSecConfig(); - config.setEncryption(direction, algo); - mIpSecService.validateAlgorithms(config, direction); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } + // Validate that correct algorithm type succeeds + IpSecConfig config = new IpSecConfig(); + config.setEncryption(CRYPT_ALGO); + mIpSecService.validateAlgorithms(config); + + // Validate that incorrect algorithm types fails + for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) { + try { + config = new IpSecConfig(); + config.setEncryption(algo); + mIpSecService.validateAlgorithms(config); + fail("Did not throw exception on invalid algorithm type"); + } catch (IllegalArgumentException expected) { } } } @Test public void testValidateAlgorithmsAead() { - for (int direction : DIRECTIONS) { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(direction, AEAD_ALGO); - mIpSecService.validateAlgorithms(config, direction); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) { - try { - config = new IpSecConfig(); - config.setAuthenticatedEncryption(direction, algo); - mIpSecService.validateAlgorithms(config, direction); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } + // Validate that correct algorithm type succeeds + IpSecConfig config = new IpSecConfig(); + config.setAuthenticatedEncryption(AEAD_ALGO); + mIpSecService.validateAlgorithms(config); + + // Validate that incorrect algorithm types fails + for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) { + try { + config = new IpSecConfig(); + config.setAuthenticatedEncryption(algo); + mIpSecService.validateAlgorithms(config); + fail("Did not throw exception on invalid algorithm type"); + } catch (IllegalArgumentException expected) { } } } @Test public void testValidateAlgorithmsAuthCrypt() { - for (int direction : DIRECTIONS) { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthentication(direction, AUTH_ALGO); - config.setEncryption(direction, CRYPT_ALGO); - mIpSecService.validateAlgorithms(config, direction); - } + // Validate that correct algorithm type succeeds + IpSecConfig config = new IpSecConfig(); + config.setAuthentication(AUTH_ALGO); + config.setEncryption(CRYPT_ALGO); + mIpSecService.validateAlgorithms(config); } @Test public void testValidateAlgorithmsNoAlgorithms() { IpSecConfig config = new IpSecConfig(); try { - mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN); + mIpSecService.validateAlgorithms(config); fail("Expected exception; no algorithms specified"); } catch (IllegalArgumentException expected) { } @@ -388,10 +377,10 @@ public class IpSecServiceTest { @Test public void testValidateAlgorithmsAeadWithAuth() { IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO); - config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO); + config.setAuthenticatedEncryption(AEAD_ALGO); + config.setAuthentication(AUTH_ALGO); try { - mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN); + mIpSecService.validateAlgorithms(config); fail("Expected exception; both AEAD and auth algorithm specified"); } catch (IllegalArgumentException expected) { } @@ -400,10 +389,10 @@ public class IpSecServiceTest { @Test public void testValidateAlgorithmsAeadWithCrypt() { IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO); - config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO); + config.setAuthenticatedEncryption(AEAD_ALGO); + config.setEncryption(CRYPT_ALGO); try { - mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN); + mIpSecService.validateAlgorithms(config); fail("Expected exception; both AEAD and crypt algorithm specified"); } catch (IllegalArgumentException expected) { } @@ -412,11 +401,11 @@ public class IpSecServiceTest { @Test public void testValidateAlgorithmsAeadWithAuthAndCrypt() { IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO); - config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO); - config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO); + config.setAuthenticatedEncryption(AEAD_ALGO); + config.setAuthentication(AUTH_ALGO); + config.setEncryption(CRYPT_ALGO); try { - mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN); + mIpSecService.validateAlgorithms(config); fail("Expected exception; AEAD, auth and crypt algorithm specified"); } catch (IllegalArgumentException expected) { } @@ -434,7 +423,7 @@ public class IpSecServiceTest { @Test public void testRemoveTransportModeTransform() throws Exception { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); - mIpSecService.removeTransportModeTransform(pfd, 1); + mIpSecService.removeTransportModeTransforms(pfd); verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); } @@ -447,7 +436,7 @@ public class IpSecServiceTest { try { IpSecSpiResponse spiResp = mIpSecService.allocateSecurityParameterIndex( - IpSecTransform.DIRECTION_OUT, address, DROID_SPI, new Binder()); + address, DROID_SPI, new Binder()); fail("Invalid address was passed through IpSecService validation: " + address); } catch (IllegalArgumentException e) { } catch (Exception e) { @@ -519,7 +508,6 @@ public class IpSecServiceTest { // tracks the resource ID. when(mMockNetd.ipSecAllocateSpi( anyInt(), - eq(IpSecTransform.DIRECTION_OUT), anyString(), eq(InetAddress.getLoopbackAddress().getHostAddress()), anyInt())) @@ -528,7 +516,6 @@ public class IpSecServiceTest { for (int i = 0; i < MAX_NUM_SPIS; i++) { IpSecSpiResponse newSpi = mIpSecService.allocateSecurityParameterIndex( - 0x1, InetAddress.getLoopbackAddress().getHostAddress(), DROID_SPI + i, new Binder()); @@ -544,7 +531,6 @@ public class IpSecServiceTest { // Try to reserve one more SPI, and should fail. IpSecSpiResponse extraSpi = mIpSecService.allocateSecurityParameterIndex( - 0x1, InetAddress.getLoopbackAddress().getHostAddress(), DROID_SPI + MAX_NUM_SPIS, new Binder()); @@ -558,7 +544,6 @@ public class IpSecServiceTest { // Should successfully reserve one more spi. extraSpi = mIpSecService.allocateSecurityParameterIndex( - 0x1, InetAddress.getLoopbackAddress().getHostAddress(), DROID_SPI + MAX_NUM_SPIS, new Binder()); |