Merge "Readability improvements to the Vpn class with no logic changes"
diff --git a/Android.bp b/Android.bp
index eb5240e..facc741 100644
--- a/Android.bp
+++ b/Android.bp
@@ -247,6 +247,8 @@
"core/java/android/service/euicc/IGetEidCallback.aidl",
"core/java/android/service/euicc/IGetEuiccInfoCallback.aidl",
"core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl",
+ "core/java/android/service/euicc/IGetOtaStatusCallback.aidl",
+ "core/java/android/service/euicc/IOtaStatusChangedCallback.aidl",
"core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl",
"core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
"core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
@@ -508,7 +510,9 @@
"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/IEuiccCardController.aidl",
"telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl",
+ "telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl",
"wifi/java/android/net/wifi/IWifiManager.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl",
@@ -594,6 +598,7 @@
"android.hardware.vibrator-V1.0-java-constants",
"android.hardware.vibrator-V1.1-java-constants",
"android.hardware.wifi-V1.0-java-constants",
+ "android.hardware.radio-V1.0-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
diff --git a/Android.mk b/Android.mk
index 83cdd73..2d74249 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,224 +32,26 @@
# ============================================================
include $(CLEAR_VARS)
-aidl_files := \
- frameworks/base/telephony/java/android/telephony/mbms/DownloadRequest.aidl \
- frameworks/base/telephony/java/android/telephony/mbms/FileInfo.aidl \
- frameworks/base/telephony/java/android/telephony/mbms/FileServiceInfo.aidl \
- frameworks/base/telephony/java/android/telephony/mbms/ServiceInfo.aidl \
- frameworks/base/telephony/java/android/telephony/mbms/StreamingServiceInfo.aidl \
- frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
- frameworks/base/telephony/java/android/telephony/SubscriptionInfo.aidl \
- frameworks/base/telephony/java/android/telephony/CellInfo.aidl \
- frameworks/base/telephony/java/android/telephony/SignalStrength.aidl \
- frameworks/base/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl \
- frameworks/base/telephony/java/android/telephony/NeighboringCellInfo.aidl \
- frameworks/base/telephony/java/android/telephony/ModemActivityInfo.aidl \
- frameworks/base/telephony/java/android/telephony/UiccAccessRule.aidl \
- frameworks/base/telephony/java/android/telephony/data/DataCallResponse.aidl \
- frameworks/base/telephony/java/android/telephony/data/DataProfile.aidl \
- frameworks/base/telephony/java/android/telephony/euicc/DownloadableSubscription.aidl \
- frameworks/base/telephony/java/android/telephony/euicc/EuiccInfo.aidl \
- frameworks/base/location/java/android/location/Location.aidl \
- frameworks/base/location/java/android/location/Address.aidl \
- frameworks/base/location/java/android/location/Criteria.aidl \
- frameworks/base/media/java/android/media/MediaMetadata.aidl \
- frameworks/base/media/java/android/media/MediaDescription.aidl \
- frameworks/base/media/java/android/media/Rating.aidl \
- frameworks/base/media/java/android/media/AudioAttributes.aidl \
- frameworks/base/media/java/android/media/AudioFocusInfo.aidl \
- frameworks/base/media/java/android/media/session/PlaybackState.aidl \
- frameworks/base/media/java/android/media/session/MediaSession.aidl \
- frameworks/base/media/java/android/media/tv/TvInputInfo.aidl \
- frameworks/base/media/java/android/media/tv/TvTrackInfo.aidl \
- frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \
- frameworks/base/wifi/java/android/net/wifi/ScanSettings.aidl \
- frameworks/base/wifi/java/android/net/wifi/aware/ConfigRequest.aidl \
- frameworks/base/wifi/java/android/net/wifi/aware/PublishConfig.aidl \
- frameworks/base/wifi/java/android/net/wifi/aware/SubscribeConfig.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl \
- frameworks/base/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl \
- frameworks/base/wifi/java/android/net/wifi/WpsInfo.aidl \
- frameworks/base/wifi/java/android/net/wifi/ScanResult.aidl \
- frameworks/base/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl \
- frameworks/base/wifi/java/android/net/wifi/WifiEnterpriseConfig.aidl \
- frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.aidl \
- frameworks/base/wifi/java/android/net/wifi/WifiInfo.aidl \
- frameworks/base/graphics/java/android/graphics/Region.aidl \
- frameworks/base/graphics/java/android/graphics/Bitmap.aidl \
- frameworks/base/graphics/java/android/graphics/Point.aidl \
- frameworks/base/graphics/java/android/graphics/PointF.aidl \
- frameworks/base/graphics/java/android/graphics/RectF.aidl \
- frameworks/base/graphics/java/android/graphics/Rect.aidl \
- frameworks/base/graphics/java/android/graphics/drawable/Icon.aidl \
- frameworks/base/core/java/android/accounts/AuthenticatorDescription.aidl \
- frameworks/base/core/java/android/accounts/Account.aidl \
- frameworks/base/core/java/android/app/admin/ConnectEvent.aidl \
- frameworks/base/core/java/android/app/admin/DnsEvent.aidl \
- frameworks/base/core/java/android/app/admin/NetworkEvent.aidl \
- frameworks/base/core/java/android/app/admin/SystemUpdatePolicy.aidl \
- frameworks/base/core/java/android/app/admin/PasswordMetrics.aidl \
- frameworks/base/core/java/android/print/PrintDocumentInfo.aidl \
- frameworks/base/core/java/android/print/PageRange.aidl \
- frameworks/base/core/java/android/print/PrintAttributes.aidl \
- frameworks/base/core/java/android/print/PrinterCapabilitiesInfo.aidl \
- frameworks/base/core/java/android/print/PrinterId.aidl \
- frameworks/base/core/java/android/print/PrintJobInfo.aidl \
- frameworks/base/core/java/android/print/PrinterInfo.aidl \
- frameworks/base/core/java/android/print/PrintJobId.aidl \
- frameworks/base/core/java/android/printservice/recommendation/RecommendationInfo.aidl \
- frameworks/base/core/java/android/hardware/radio/ProgramSelector.aidl \
- frameworks/base/core/java/android/hardware/radio/RadioManager.aidl \
- frameworks/base/core/java/android/hardware/radio/RadioMetadata.aidl \
- frameworks/base/core/java/android/hardware/usb/UsbDevice.aidl \
- frameworks/base/core/java/android/hardware/usb/UsbInterface.aidl \
- frameworks/base/core/java/android/hardware/usb/UsbEndpoint.aidl \
- frameworks/base/core/java/android/hardware/usb/UsbAccessory.aidl \
- frameworks/base/core/java/android/os/Messenger.aidl \
- frameworks/base/core/java/android/os/PatternMatcher.aidl \
- frameworks/base/core/java/android/os/Message.aidl \
- frameworks/base/core/java/android/os/UserHandle.aidl \
- frameworks/base/core/java/android/os/ParcelUuid.aidl \
- frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \
- frameworks/base/core/java/android/os/ResultReceiver.aidl \
- frameworks/base/core/java/android/os/WorkSource.aidl \
- frameworks/base/core/java/android/os/DropBoxManager.aidl \
- frameworks/base/core/java/android/os/Bundle.aidl \
- frameworks/base/core/java/android/os/Debug.aidl \
- frameworks/base/core/java/android/os/SharedMemory.aidl \
- frameworks/base/core/java/android/os/StrictMode.aidl \
- frameworks/base/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl \
- frameworks/base/core/java/android/net/Network.aidl \
- frameworks/base/core/java/android/net/RouteInfo.aidl \
- frameworks/base/core/java/android/net/NetworkInfo.aidl \
- frameworks/base/core/java/android/net/IpPrefix.aidl \
- frameworks/base/core/java/android/net/NetworkCapabilities.aidl \
- frameworks/base/core/java/android/net/DhcpInfo.aidl \
- frameworks/base/core/java/android/net/ProxyInfo.aidl \
- frameworks/base/core/java/android/net/LinkProperties.aidl \
- frameworks/base/core/java/android/net/Uri.aidl \
- frameworks/base/core/java/android/net/NetworkRequest.aidl \
- frameworks/base/core/java/android/net/LinkAddress.aidl \
- frameworks/base/core/java/android/util/MemoryIntArray.aidl \
- frameworks/base/core/java/android/view/Display.aidl \
- frameworks/base/core/java/android/view/InputDevice.aidl \
- frameworks/base/core/java/android/view/InputEvent.aidl \
- frameworks/native/aidl/gui/android/view/Surface.aidl \
- frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
- frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \
- frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \
- frameworks/base/core/java/android/view/inputmethod/CompletionInfo.aidl \
- frameworks/base/core/java/android/view/inputmethod/ExtractedText.aidl \
- frameworks/base/core/java/android/view/inputmethod/EditorInfo.aidl \
- frameworks/base/core/java/android/view/inputmethod/InputMethodInfo.aidl \
- frameworks/base/core/java/android/view/inputmethod/CorrectionInfo.aidl \
- frameworks/base/core/java/android/view/inputmethod/InputBinding.aidl \
- frameworks/base/core/java/android/view/inputmethod/ExtractedTextRequest.aidl \
- frameworks/base/core/java/android/view/DragEvent.aidl \
- frameworks/base/core/java/android/view/KeyEvent.aidl \
- frameworks/base/core/java/android/view/WindowManager.aidl \
- frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \
- frameworks/base/core/java/android/view/MotionEvent.aidl \
- frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl \
- frameworks/base/core/java/android/view/accessibility/AccessibilityRecord.aidl \
- frameworks/base/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl \
- frameworks/base/core/java/android/view/accessibility/AccessibilityEvent.aidl \
- frameworks/base/core/java/android/view/textservice/SpellCheckerSubtype.aidl \
- frameworks/base/core/java/android/view/textservice/TextInfo.aidl \
- frameworks/base/core/java/android/view/textservice/SpellCheckerInfo.aidl \
- frameworks/base/core/java/android/view/textservice/SentenceSuggestionsInfo.aidl \
- frameworks/base/core/java/android/view/textservice/SuggestionsInfo.aidl \
- frameworks/base/core/java/android/service/carrier/CarrierIdentifier.aidl \
- frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \
- frameworks/base/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.aidl \
- frameworks/base/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl \
- frameworks/base/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl \
- frameworks/base/core/java/android/service/notification/Adjustment.aidl \
- frameworks/base/core/java/android/service/notification/Condition.aidl \
- frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
- frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
- frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
- frameworks/base/core/java/android/service/resolver/ResolverTarget.aidl \
- frameworks/base/core/java/android/speech/tts/Voice.aidl \
- frameworks/base/core/java/android/app/usage/CacheQuotaHint.aidl \
- frameworks/base/core/java/android/app/usage/ExternalStorageStats.aidl \
- frameworks/base/core/java/android/app/usage/StorageStats.aidl \
- frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
- frameworks/base/core/java/android/app/Notification.aidl \
- frameworks/base/core/java/android/app/NotificationManager.aidl \
- frameworks/base/core/java/android/app/WallpaperInfo.aidl \
- frameworks/base/core/java/android/app/AppOpsManager.aidl \
- frameworks/base/core/java/android/app/ActivityManager.aidl \
- frameworks/base/core/java/android/app/PendingIntent.aidl \
- frameworks/base/core/java/android/app/AlarmManager.aidl \
- frameworks/base/core/java/android/app/SearchableInfo.aidl \
- frameworks/base/core/java/android/app/VoiceInteractor.aidl \
- frameworks/base/core/java/android/app/assist/AssistContent.aidl \
- frameworks/base/core/java/android/app/assist/AssistStructure.aidl \
- frameworks/base/core/java/android/app/job/JobParameters.aidl \
- frameworks/base/core/java/android/app/job/JobInfo.aidl \
- frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
- frameworks/base/core/java/android/content/ClipDescription.aidl \
- frameworks/base/core/java/android/content/IntentFilter.aidl \
- frameworks/base/core/java/android/content/Intent.aidl \
- frameworks/base/core/java/android/content/res/Configuration.aidl \
- frameworks/base/core/java/android/content/res/ObbInfo.aidl \
- frameworks/base/core/java/android/content/RestrictionEntry.aidl \
- frameworks/base/core/java/android/content/ClipData.aidl \
- frameworks/base/core/java/android/content/SyncAdapterType.aidl \
- frameworks/base/core/java/android/content/SyncRequest.aidl \
- frameworks/base/core/java/android/content/PeriodicSync.aidl \
- frameworks/base/core/java/android/content/SyncResult.aidl \
- frameworks/base/core/java/android/content/pm/FeatureInfo.aidl \
- frameworks/base/core/java/android/content/pm/InstrumentationInfo.aidl \
- frameworks/base/core/java/android/content/pm/PackageInstaller.aidl \
- frameworks/base/core/java/android/content/pm/ServiceInfo.aidl \
- frameworks/base/core/java/android/content/pm/Signature.aidl \
- frameworks/base/core/java/android/content/pm/ApplicationInfo.aidl \
- frameworks/base/core/java/android/content/pm/PermissionInfo.aidl \
- frameworks/base/core/java/android/content/pm/ActivityInfo.aidl \
- frameworks/base/core/java/android/content/pm/ConfigurationInfo.aidl \
- frameworks/base/core/java/android/content/pm/PackageInfo.aidl \
- frameworks/base/core/java/android/content/pm/ResolveInfo.aidl \
- frameworks/base/core/java/android/content/pm/ProviderInfo.aidl \
- frameworks/base/core/java/android/content/pm/PackageStats.aidl \
- frameworks/base/core/java/android/content/pm/PermissionGroupInfo.aidl \
- frameworks/base/core/java/android/content/pm/ShortcutInfo.aidl \
- frameworks/base/core/java/android/content/pm/LabeledIntent.aidl \
- frameworks/base/core/java/android/content/ComponentName.aidl \
- frameworks/base/core/java/android/content/SyncStats.aidl \
- frameworks/base/core/java/android/content/ContentValues.aidl \
- frameworks/base/core/java/android/content/SyncInfo.aidl \
- frameworks/base/core/java/android/content/IntentSender.aidl \
- frameworks/base/core/java/android/widget/RemoteViews.aidl \
- frameworks/base/core/java/android/text/style/SuggestionSpan.aidl \
- frameworks/base/core/java/android/nfc/Tag.aidl \
- frameworks/base/core/java/android/nfc/NdefRecord.aidl \
- frameworks/base/core/java/android/nfc/NdefMessage.aidl \
- frameworks/base/core/java/android/database/CursorWindow.aidl \
- frameworks/base/core/java/android/service/quicksettings/Tile.aidl \
- frameworks/native/aidl/binder/android/os/PersistableBundle.aidl \
- system/bt/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl \
- system/bt/binder/android/bluetooth/le/AdvertiseSettings.aidl \
- system/bt/binder/android/bluetooth/le/ScanSettings.aidl \
- system/bt/binder/android/bluetooth/le/AdvertiseData.aidl \
- system/bt/binder/android/bluetooth/le/ScanFilter.aidl \
- system/bt/binder/android/bluetooth/le/ScanResult.aidl \
- system/bt/binder/android/bluetooth/BluetoothDevice.aidl \
- system/netd/server/binder/android/net/UidRange.aidl \
- frameworks/base/telephony/java/android/telephony/PcoData.aidl \
+aidl_parcelables :=
+define stubs-to-aidl-parcelables
+ gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/$1.aidl
+ aidl_parcelables += $$(gen)
+ $$(gen): $(call java-lib-header-files,$1) | $(HOST_OUT_EXECUTABLES)/sdkparcelables
+ @echo Extract SDK parcelables: $$@
+ rm -f $$@
+ $(HOST_OUT_EXECUTABLES)/sdkparcelables $$< $$@
+endef
+
+$(foreach stubs,android_stubs_current android_test_stubs_current android_system_stubs_current,\
+ $(eval $(call stubs-to-aidl-parcelables,$(stubs))))
gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl
-$(gen): PRIVATE_SRC_FILES := $(aidl_files)
-ALL_SDK_FILES += $(gen)
-$(gen): $(aidl_files) | $(AIDL)
- @echo Aidl Preprocess: $@
- $(hide) $(AIDL) --preprocess $@ $(PRIVATE_SRC_FILES)
+.KATI_RESTAT: $(gen)
+$(gen): $(aidl_parcelables)
+ @echo Combining SDK parcelables: $@
+ rm -f $@.tmp
+ cat $^ | sort -u > $@.tmp
+ $(call commit-change-for-toc,$@)
# the documentation
# ============================================================
@@ -487,8 +289,6 @@
include $(BUILD_DROIDDOC)
-# $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(gen)
$(INTERNAL_PLATFORM_API_FILE): $(full_target)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
@@ -524,8 +324,6 @@
include $(BUILD_DROIDDOC)
-# $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(gen)
$(INTERNAL_PLATFORM_SYSTEM_API_FILE): $(full_target)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
@@ -562,8 +360,6 @@
include $(BUILD_DROIDDOC)
-# $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(gen)
$(INTERNAL_PLATFORM_TEST_API_FILE): $(full_target)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
@@ -593,9 +389,6 @@
include $(BUILD_DROIDDOC)
-# $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(gen)
-
# Run this for checkbuild
checkbuild: doc-comment-check-docs
# Check comment when you are updating the API
@@ -905,4 +698,4 @@
include $(call first-makefiles-under,$(LOCAL_PATH))
endif
-endif # ANDROID_BUILD_EMBEDDED
+endif # ANDROID_BUILD_EMBEDDED
\ No newline at end of file
diff --git a/api/current.txt b/api/current.txt
index e8d0ee2..392f4db 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35516,7 +35516,7 @@
public static final class Telephony.Carriers implements android.provider.BaseColumns {
field public static final java.lang.String APN = "apn";
field public static final java.lang.String AUTH_TYPE = "authtype";
- field public static final java.lang.String BEARER = "bearer";
+ field public static final deprecated java.lang.String BEARER = "bearer";
field public static final java.lang.String CARRIER_ENABLED = "carrier_enabled";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String CURRENT = "current";
@@ -35529,6 +35529,7 @@
field public static final java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
field public static final java.lang.String MVNO_TYPE = "mvno_type";
field public static final java.lang.String NAME = "name";
+ field public static final java.lang.String NETWORK_TYPE_BITMASK = "network_type_bitmask";
field public static final java.lang.String NUMERIC = "numeric";
field public static final java.lang.String PASSWORD = "password";
field public static final java.lang.String PORT = "port";
@@ -37410,6 +37411,7 @@
public class CarrierIdentifier implements android.os.Parcelable {
ctor public CarrierIdentifier(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ ctor public CarrierIdentifier(byte[], java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String getGid1();
method public java.lang.String getGid2();
@@ -39428,12 +39430,15 @@
method public final void addConference(android.telecom.Conference);
method public final void addExistingConnection(android.telecom.PhoneAccountHandle, android.telecom.Connection);
method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
+ method public final void connectionServiceFocusReleased();
method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final java.util.Collection<android.telecom.Conference> getAllConferences();
method public final java.util.Collection<android.telecom.Connection> getAllConnections();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConference(android.telecom.Connection, android.telecom.Connection);
+ method public void onConnectionServiceFocusGained();
+ method public void onConnectionServiceFocusLost();
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
@@ -39833,6 +39838,113 @@
package android.telephony {
+ public final class AccessNetworkConstants {
+ ctor public AccessNetworkConstants();
+ }
+
+ public static final class AccessNetworkConstants.AccessNetworkType {
+ ctor public AccessNetworkConstants.AccessNetworkType();
+ field public static final int CDMA2000 = 4; // 0x4
+ field public static final int EUTRAN = 3; // 0x3
+ field public static final int GERAN = 1; // 0x1
+ field public static final int IWLAN = 5; // 0x5
+ field public static final int UTRAN = 2; // 0x2
+ }
+
+ public static final class AccessNetworkConstants.EutranBand {
+ ctor public AccessNetworkConstants.EutranBand();
+ field public static final int BAND_1 = 1; // 0x1
+ field public static final int BAND_10 = 10; // 0xa
+ field public static final int BAND_11 = 11; // 0xb
+ field public static final int BAND_12 = 12; // 0xc
+ field public static final int BAND_13 = 13; // 0xd
+ field public static final int BAND_14 = 14; // 0xe
+ field public static final int BAND_17 = 17; // 0x11
+ field public static final int BAND_18 = 18; // 0x12
+ field public static final int BAND_19 = 19; // 0x13
+ field public static final int BAND_2 = 2; // 0x2
+ field public static final int BAND_20 = 20; // 0x14
+ field public static final int BAND_21 = 21; // 0x15
+ field public static final int BAND_22 = 22; // 0x16
+ field public static final int BAND_23 = 23; // 0x17
+ field public static final int BAND_24 = 24; // 0x18
+ field public static final int BAND_25 = 25; // 0x19
+ field public static final int BAND_26 = 26; // 0x1a
+ field public static final int BAND_27 = 27; // 0x1b
+ field public static final int BAND_28 = 28; // 0x1c
+ field public static final int BAND_3 = 3; // 0x3
+ field public static final int BAND_30 = 30; // 0x1e
+ field public static final int BAND_31 = 31; // 0x1f
+ field public static final int BAND_33 = 33; // 0x21
+ field public static final int BAND_34 = 34; // 0x22
+ field public static final int BAND_35 = 35; // 0x23
+ field public static final int BAND_36 = 36; // 0x24
+ field public static final int BAND_37 = 37; // 0x25
+ field public static final int BAND_38 = 38; // 0x26
+ field public static final int BAND_39 = 39; // 0x27
+ field public static final int BAND_4 = 4; // 0x4
+ field public static final int BAND_40 = 40; // 0x28
+ field public static final int BAND_41 = 41; // 0x29
+ field public static final int BAND_42 = 42; // 0x2a
+ field public static final int BAND_43 = 43; // 0x2b
+ field public static final int BAND_44 = 44; // 0x2c
+ field public static final int BAND_45 = 45; // 0x2d
+ field public static final int BAND_46 = 46; // 0x2e
+ field public static final int BAND_47 = 47; // 0x2f
+ field public static final int BAND_48 = 48; // 0x30
+ field public static final int BAND_5 = 5; // 0x5
+ field public static final int BAND_6 = 6; // 0x6
+ field public static final int BAND_65 = 65; // 0x41
+ field public static final int BAND_66 = 66; // 0x42
+ field public static final int BAND_68 = 68; // 0x44
+ field public static final int BAND_7 = 7; // 0x7
+ field public static final int BAND_70 = 70; // 0x46
+ field public static final int BAND_8 = 8; // 0x8
+ field public static final int BAND_9 = 9; // 0x9
+ }
+
+ public static final class AccessNetworkConstants.GeranBand {
+ ctor public AccessNetworkConstants.GeranBand();
+ field public static final int BAND_450 = 3; // 0x3
+ field public static final int BAND_480 = 4; // 0x4
+ field public static final int BAND_710 = 5; // 0x5
+ field public static final int BAND_750 = 6; // 0x6
+ field public static final int BAND_850 = 8; // 0x8
+ field public static final int BAND_DCS1800 = 12; // 0xc
+ field public static final int BAND_E900 = 10; // 0xa
+ field public static final int BAND_ER900 = 14; // 0xe
+ field public static final int BAND_P900 = 9; // 0x9
+ field public static final int BAND_PCS1900 = 13; // 0xd
+ field public static final int BAND_R900 = 11; // 0xb
+ field public static final int BAND_T380 = 1; // 0x1
+ field public static final int BAND_T410 = 2; // 0x2
+ field public static final int BAND_T810 = 7; // 0x7
+ }
+
+ public static final class AccessNetworkConstants.UtranBand {
+ ctor public AccessNetworkConstants.UtranBand();
+ field public static final int BAND_1 = 1; // 0x1
+ field public static final int BAND_10 = 10; // 0xa
+ field public static final int BAND_11 = 11; // 0xb
+ field public static final int BAND_12 = 12; // 0xc
+ field public static final int BAND_13 = 13; // 0xd
+ field public static final int BAND_14 = 14; // 0xe
+ field public static final int BAND_19 = 19; // 0x13
+ field public static final int BAND_2 = 2; // 0x2
+ field public static final int BAND_20 = 20; // 0x14
+ field public static final int BAND_21 = 21; // 0x15
+ field public static final int BAND_22 = 22; // 0x16
+ field public static final int BAND_25 = 25; // 0x19
+ field public static final int BAND_26 = 26; // 0x1a
+ field public static final int BAND_3 = 3; // 0x3
+ field public static final int BAND_4 = 4; // 0x4
+ field public static final int BAND_5 = 5; // 0x5
+ field public static final int BAND_6 = 6; // 0x6
+ field public static final int BAND_7 = 7; // 0x7
+ field public static final int BAND_8 = 8; // 0x8
+ field public static final int BAND_9 = 9; // 0x9
+ }
+
public class CarrierConfigManager {
method public android.os.PersistableBundle getConfig();
method public android.os.PersistableBundle getConfigForSubId(int);
@@ -39881,6 +39993,7 @@
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+ field public static final java.lang.String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
@@ -39980,8 +40093,13 @@
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
- public final class CellIdentityCdma implements android.os.Parcelable {
+ public abstract class CellIdentity implements android.os.Parcelable {
method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentity> CREATOR;
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
method public int getBasestationId();
method public int getLatitude();
method public int getLongitude();
@@ -39993,8 +40111,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityCdma> CREATOR;
}
- public final class CellIdentityGsm implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
method public int getArfcn();
method public int getBsic();
method public int getCid();
@@ -40011,8 +40128,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityGsm> CREATOR;
}
- public final class CellIdentityLte implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
method public int getCi();
method public int getEarfcn();
method public deprecated int getMcc();
@@ -40028,8 +40144,17 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR;
}
- public final class CellIdentityWcdma implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method public int getCid();
+ method public int getCpid();
+ method public int getLac();
+ method public java.lang.String getMccStr();
+ method public java.lang.String getMncStr();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
method public int getCid();
method public int getLac();
method public deprecated int getMcc();
@@ -40353,111 +40478,6 @@
field public static final android.os.Parcelable.Creator<android.telephony.RadioAccessSpecifier> CREATOR;
}
- public final class RadioNetworkConstants {
- ctor public RadioNetworkConstants();
- }
-
- public static final class RadioNetworkConstants.EutranBands {
- ctor public RadioNetworkConstants.EutranBands();
- field public static final int BAND_1 = 1; // 0x1
- field public static final int BAND_10 = 10; // 0xa
- field public static final int BAND_11 = 11; // 0xb
- field public static final int BAND_12 = 12; // 0xc
- field public static final int BAND_13 = 13; // 0xd
- field public static final int BAND_14 = 14; // 0xe
- field public static final int BAND_17 = 17; // 0x11
- field public static final int BAND_18 = 18; // 0x12
- field public static final int BAND_19 = 19; // 0x13
- field public static final int BAND_2 = 2; // 0x2
- field public static final int BAND_20 = 20; // 0x14
- field public static final int BAND_21 = 21; // 0x15
- field public static final int BAND_22 = 22; // 0x16
- field public static final int BAND_23 = 23; // 0x17
- field public static final int BAND_24 = 24; // 0x18
- field public static final int BAND_25 = 25; // 0x19
- field public static final int BAND_26 = 26; // 0x1a
- field public static final int BAND_27 = 27; // 0x1b
- field public static final int BAND_28 = 28; // 0x1c
- field public static final int BAND_3 = 3; // 0x3
- field public static final int BAND_30 = 30; // 0x1e
- field public static final int BAND_31 = 31; // 0x1f
- field public static final int BAND_33 = 33; // 0x21
- field public static final int BAND_34 = 34; // 0x22
- field public static final int BAND_35 = 35; // 0x23
- field public static final int BAND_36 = 36; // 0x24
- field public static final int BAND_37 = 37; // 0x25
- field public static final int BAND_38 = 38; // 0x26
- field public static final int BAND_39 = 39; // 0x27
- field public static final int BAND_4 = 4; // 0x4
- field public static final int BAND_40 = 40; // 0x28
- field public static final int BAND_41 = 41; // 0x29
- field public static final int BAND_42 = 42; // 0x2a
- field public static final int BAND_43 = 43; // 0x2b
- field public static final int BAND_44 = 44; // 0x2c
- field public static final int BAND_45 = 45; // 0x2d
- field public static final int BAND_46 = 46; // 0x2e
- field public static final int BAND_47 = 47; // 0x2f
- field public static final int BAND_48 = 48; // 0x30
- field public static final int BAND_5 = 5; // 0x5
- field public static final int BAND_6 = 6; // 0x6
- field public static final int BAND_65 = 65; // 0x41
- field public static final int BAND_66 = 66; // 0x42
- field public static final int BAND_68 = 68; // 0x44
- field public static final int BAND_7 = 7; // 0x7
- field public static final int BAND_70 = 70; // 0x46
- field public static final int BAND_8 = 8; // 0x8
- field public static final int BAND_9 = 9; // 0x9
- }
-
- public static final class RadioNetworkConstants.GeranBands {
- ctor public RadioNetworkConstants.GeranBands();
- field public static final int BAND_450 = 3; // 0x3
- field public static final int BAND_480 = 4; // 0x4
- field public static final int BAND_710 = 5; // 0x5
- field public static final int BAND_750 = 6; // 0x6
- field public static final int BAND_850 = 8; // 0x8
- field public static final int BAND_DCS1800 = 12; // 0xc
- field public static final int BAND_E900 = 10; // 0xa
- field public static final int BAND_ER900 = 14; // 0xe
- field public static final int BAND_P900 = 9; // 0x9
- field public static final int BAND_PCS1900 = 13; // 0xd
- field public static final int BAND_R900 = 11; // 0xb
- field public static final int BAND_T380 = 1; // 0x1
- field public static final int BAND_T410 = 2; // 0x2
- field public static final int BAND_T810 = 7; // 0x7
- }
-
- public static final class RadioNetworkConstants.RadioAccessNetworks {
- ctor public RadioNetworkConstants.RadioAccessNetworks();
- field public static final int EUTRAN = 3; // 0x3
- field public static final int GERAN = 1; // 0x1
- field public static final int UTRAN = 2; // 0x2
- }
-
- public static final class RadioNetworkConstants.UtranBands {
- ctor public RadioNetworkConstants.UtranBands();
- field public static final int BAND_1 = 1; // 0x1
- field public static final int BAND_10 = 10; // 0xa
- field public static final int BAND_11 = 11; // 0xb
- field public static final int BAND_12 = 12; // 0xc
- field public static final int BAND_13 = 13; // 0xd
- field public static final int BAND_14 = 14; // 0xe
- field public static final int BAND_19 = 19; // 0x13
- field public static final int BAND_2 = 2; // 0x2
- field public static final int BAND_20 = 20; // 0x14
- field public static final int BAND_21 = 21; // 0x15
- field public static final int BAND_22 = 22; // 0x16
- field public static final int BAND_25 = 25; // 0x19
- field public static final int BAND_26 = 26; // 0x1a
- field public static final int BAND_3 = 3; // 0x3
- field public static final int BAND_4 = 4; // 0x4
- field public static final int BAND_5 = 5; // 0x5
- field public static final int BAND_6 = 6; // 0x6
- field public static final int BAND_7 = 7; // 0x7
- field public static final int BAND_8 = 8; // 0x8
- field public static final int BAND_9 = 9; // 0x9
- }
-
public class ServiceState implements android.os.Parcelable {
ctor public ServiceState();
ctor public ServiceState(android.telephony.ServiceState);
@@ -40465,11 +40485,13 @@
method protected void copyFrom(android.telephony.ServiceState);
method public int describeContents();
method public boolean getIsManualSelection();
+ method public int getNetworkId();
method public java.lang.String getOperatorAlphaLong();
method public java.lang.String getOperatorAlphaShort();
method public java.lang.String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
+ method public int getSystemId();
method public void setIsManualSelection(boolean);
method public void setOperatorName(java.lang.String, java.lang.String, java.lang.String);
method public void setRoaming(boolean);
@@ -40482,6 +40504,7 @@
field public static final int STATE_IN_SERVICE = 0; // 0x0
field public static final int STATE_OUT_OF_SERVICE = 1; // 0x1
field public static final int STATE_POWER_OFF = 3; // 0x3
+ field public static final int UNKNOWN_ID = -1; // 0xffffffff
}
public class SignalStrength implements android.os.Parcelable {
@@ -40726,11 +40749,12 @@
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isConcurrentVoiceAndDataSupported();
- method public boolean isDataEnabled();
+ method public deprecated boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
method public deprecated boolean isTtyModeSupported();
+ method public boolean isUserMobileDataEnabled();
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
@@ -40740,12 +40764,13 @@
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(java.lang.String, int, java.lang.String, android.app.PendingIntent);
- method public void setDataEnabled(boolean);
+ method public deprecated void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public void setNetworkSelectionModeAutomatic();
method public boolean setNetworkSelectionModeManual(java.lang.String, boolean);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
+ method public void setUserMobileDataEnabled(boolean);
method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
@@ -40906,6 +40931,78 @@
}
+package android.telephony.data {
+
+ public class ApnSetting implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getApnName();
+ method public int getAuthType();
+ method public java.lang.String getEntryName();
+ method public int getId();
+ method public int getMmsPort();
+ method public java.net.InetAddress getMmsProxy();
+ method public java.net.URL getMmsc();
+ method public java.lang.String getMvnoType();
+ method public java.lang.String getOperatorNumeric();
+ method public java.lang.String getPassword();
+ method public int getPort();
+ method public java.lang.String getProtocol();
+ method public java.net.InetAddress getProxy();
+ method public java.lang.String getRoamingProtocol();
+ method public java.util.List<java.lang.String> getTypes();
+ method public java.lang.String getUser();
+ method public boolean isEnabled();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUTH_TYPE_CHAP = 2; // 0x2
+ field public static final int AUTH_TYPE_NONE = 0; // 0x0
+ field public static final int AUTH_TYPE_PAP = 1; // 0x1
+ field public static final int AUTH_TYPE_PAP_OR_CHAP = 3; // 0x3
+ field public static final android.os.Parcelable.Creator<android.telephony.data.ApnSetting> CREATOR;
+ field public static final java.lang.String MVNO_TYPE_GID = "gid";
+ field public static final java.lang.String MVNO_TYPE_ICCID = "iccid";
+ field public static final java.lang.String MVNO_TYPE_IMSI = "imsi";
+ field public static final java.lang.String MVNO_TYPE_SPN = "spn";
+ field public static final java.lang.String PROTOCOL_IP = "IP";
+ field public static final java.lang.String PROTOCOL_IPV4V6 = "IPV4V6";
+ field public static final java.lang.String PROTOCOL_IPV6 = "IPV6";
+ field public static final java.lang.String PROTOCOL_PPP = "PPP";
+ field public static final java.lang.String TYPE_ALL = "*";
+ field public static final java.lang.String TYPE_CBS = "cbs";
+ field public static final java.lang.String TYPE_DEFAULT = "default";
+ field public static final java.lang.String TYPE_DUN = "dun";
+ field public static final java.lang.String TYPE_EMERGENCY = "emergency";
+ field public static final java.lang.String TYPE_FOTA = "fota";
+ field public static final java.lang.String TYPE_HIPRI = "hipri";
+ field public static final java.lang.String TYPE_IA = "ia";
+ field public static final java.lang.String TYPE_IMS = "ims";
+ field public static final java.lang.String TYPE_MMS = "mms";
+ field public static final java.lang.String TYPE_SUPL = "supl";
+ }
+
+ public static class ApnSetting.Builder {
+ ctor public ApnSetting.Builder();
+ method public android.telephony.data.ApnSetting build();
+ method public android.telephony.data.ApnSetting.Builder setApnName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setAuthType(int);
+ method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+ method public android.telephony.data.ApnSetting.Builder setEntryName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setId(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsPort(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setMmsc(java.net.URL);
+ method public android.telephony.data.ApnSetting.Builder setMvnoType(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPassword(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPort(int);
+ method public android.telephony.data.ApnSetting.Builder setProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setTypes(java.util.List<java.lang.String>);
+ method public android.telephony.data.ApnSetting.Builder setUser(java.lang.String);
+ }
+
+}
+
package android.telephony.gsm {
public class GsmCellLocation extends android.telephony.CellLocation {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3a71189..4eb5c08 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -615,6 +615,7 @@
public final class BluetoothAdapter {
method public boolean disableBLE();
method public boolean enableBLE();
+ method public boolean enableNoAutoConnect();
method public boolean isBleScanAlwaysAvailable();
method public boolean isLeEnabled();
field public static final java.lang.String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
@@ -622,8 +623,25 @@
}
public final class BluetoothDevice implements android.os.Parcelable {
+ method public boolean cancelBondProcess();
method public boolean isConnected();
method public boolean isEncrypted();
+ method public boolean removeBond();
+ method public boolean setPhonebookAccessPermission(int);
+ field public static final int ACCESS_ALLOWED = 1; // 0x1
+ field public static final int ACCESS_REJECTED = 2; // 0x2
+ field public static final int ACCESS_UNKNOWN = 0; // 0x0
+ }
+
+ public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
+ method public boolean connect(android.bluetooth.BluetoothDevice);
+ method public boolean disconnect(android.bluetooth.BluetoothDevice);
+ method public boolean setPriority(android.bluetooth.BluetoothDevice, int);
+ }
+
+ public abstract interface BluetoothProfile {
+ field public static final int PRIORITY_OFF = 0; // 0x0
+ field public static final int PRIORITY_ON = 100; // 0x64
}
}
@@ -4029,7 +4047,7 @@
method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean needsOtaServiceProvisioning();
method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
- method public void setDataEnabled(int, boolean);
+ method public deprecated void setDataEnabled(int, boolean);
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c8d9839..f2160e1 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -268,4 +268,11 @@
* @param token The IApplicationToken for the activity
*/
public abstract void setFocusedActivity(IBinder token);
+
+ public interface ScreenObserver {
+ public void onAwakeStateChanged(boolean isAwake);
+ public void onKeyguardStateChanged(boolean isShowing);
+ }
+
+ public abstract void registerScreenObserver(ScreenObserver observer);
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 6dca400..6ac15a5 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -50,11 +50,6 @@
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
final class SharedPreferencesImpl implements SharedPreferences {
private static final String TAG = "SharedPreferencesImpl";
@@ -74,12 +69,18 @@
private final Object mLock = new Object();
private final Object mWritingToDiskLock = new Object();
- private Future<Map<String, Object>> mMap;
+ @GuardedBy("mLock")
+ private Map<String, Object> mMap;
+ @GuardedBy("mLock")
+ private Throwable mThrowable;
@GuardedBy("mLock")
private int mDiskWritesInFlight = 0;
@GuardedBy("mLock")
+ private boolean mLoaded = false;
+
+ @GuardedBy("mLock")
private StructTimespec mStatTimestamp;
@GuardedBy("mLock")
@@ -106,18 +107,28 @@
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
+ mLoaded = false;
mMap = null;
+ mThrowable = null;
startLoadFromDisk();
}
private void startLoadFromDisk() {
- FutureTask<Map<String, Object>> futureTask = new FutureTask<>(() -> loadFromDisk());
- mMap = futureTask;
- new Thread(futureTask, "SharedPreferencesImpl-load").start();
+ synchronized (mLock) {
+ mLoaded = false;
+ }
+ new Thread("SharedPreferencesImpl-load") {
+ public void run() {
+ loadFromDisk();
+ }
+ }.start();
}
- private Map<String, Object> loadFromDisk() {
+ private void loadFromDisk() {
synchronized (mLock) {
+ if (mLoaded) {
+ return;
+ }
if (mBackupFile.exists()) {
mFile.delete();
mBackupFile.renameTo(mFile);
@@ -131,13 +142,14 @@
Map<String, Object> map = null;
StructStat stat = null;
+ Throwable thrown = null;
try {
stat = Os.stat(mFile.getPath());
if (mFile.canRead()) {
BufferedInputStream str = null;
try {
str = new BufferedInputStream(
- new FileInputStream(mFile), 16*1024);
+ new FileInputStream(mFile), 16 * 1024);
map = (Map<String, Object>) XmlUtils.readMapXml(str);
} catch (Exception e) {
Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
@@ -146,18 +158,37 @@
}
}
} catch (ErrnoException e) {
- /* ignore */
+ // An errno exception means the stat failed. Treat as empty/non-existing by
+ // ignoring.
+ } catch (Throwable t) {
+ thrown = t;
}
synchronized (mLock) {
- if (map != null) {
- mStatTimestamp = stat.st_mtim;
- mStatSize = stat.st_size;
- } else {
- map = new HashMap<>();
+ mLoaded = true;
+ mThrowable = thrown;
+
+ // It's important that we always signal waiters, even if we'll make
+ // them fail with an exception. The try-finally is pretty wide, but
+ // better safe than sorry.
+ try {
+ if (thrown == null) {
+ if (map != null) {
+ mMap = map;
+ mStatTimestamp = stat.st_mtim;
+ mStatSize = stat.st_size;
+ } else {
+ mMap = new HashMap<>();
+ }
+ }
+ // In case of a thrown exception, we retain the old map. That allows
+ // any open editors to commit and store updates.
+ } catch (Throwable t) {
+ mThrowable = t;
+ } finally {
+ mLock.notifyAll();
}
}
- return map;
}
static File makeBackupFile(File prefsFile) {
@@ -216,42 +247,40 @@
}
}
- private @GuardedBy("mLock") Map<String, Object> getLoaded() {
- // For backwards compatibility, we need to ignore any interrupts. b/70122540.
- for (;;) {
- try {
- return mMap.get();
- } catch (ExecutionException e) {
- throw new IllegalStateException(e);
- } catch (InterruptedException e) {
- // Ignore and try again.
- }
- }
- }
- private @GuardedBy("mLock") Map<String, Object> getLoadedWithBlockGuard() {
- if (!mMap.isDone()) {
+ @GuardedBy("mLock")
+ private void awaitLoadedLocked() {
+ if (!mLoaded) {
// Raise an explicit StrictMode onReadFromDisk for this
// thread, since the real read will be in a different
// thread and otherwise ignored by StrictMode.
BlockGuard.getThreadPolicy().onReadFromDisk();
}
- return getLoaded();
+ while (!mLoaded) {
+ try {
+ mLock.wait();
+ } catch (InterruptedException unused) {
+ }
+ }
+ if (mThrowable != null) {
+ throw new IllegalStateException(mThrowable);
+ }
}
@Override
public Map<String, ?> getAll() {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- return new HashMap<String, Object>(map);
+ awaitLoadedLocked();
+ //noinspection unchecked
+ return new HashMap<String, Object>(mMap);
}
}
@Override
@Nullable
public String getString(String key, @Nullable String defValue) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- String v = (String) map.get(key);
+ awaitLoadedLocked();
+ String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
@@ -259,65 +288,66 @@
@Override
@Nullable
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- @SuppressWarnings("unchecked")
- Set<String> v = (Set<String>) map.get(key);
+ awaitLoadedLocked();
+ Set<String> v = (Set<String>) mMap.get(key);
return v != null ? v : defValues;
}
}
@Override
public int getInt(String key, int defValue) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- Integer v = (Integer) map.get(key);
+ awaitLoadedLocked();
+ Integer v = (Integer)mMap.get(key);
return v != null ? v : defValue;
}
}
@Override
public long getLong(String key, long defValue) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- Long v = (Long) map.get(key);
+ awaitLoadedLocked();
+ Long v = (Long)mMap.get(key);
return v != null ? v : defValue;
}
}
@Override
public float getFloat(String key, float defValue) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- Float v = (Float) map.get(key);
+ awaitLoadedLocked();
+ Float v = (Float)mMap.get(key);
return v != null ? v : defValue;
}
}
@Override
public boolean getBoolean(String key, boolean defValue) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- Boolean v = (Boolean) map.get(key);
+ awaitLoadedLocked();
+ Boolean v = (Boolean)mMap.get(key);
return v != null ? v : defValue;
}
}
@Override
public boolean contains(String key) {
- Map<String, Object> map = getLoadedWithBlockGuard();
synchronized (mLock) {
- return map.containsKey(key);
+ awaitLoadedLocked();
+ return mMap.containsKey(key);
}
}
@Override
public Editor edit() {
- // TODO: remove the need to call getLoaded() when
+ // TODO: remove the need to call awaitLoadedLocked() when
// requesting an editor. will require some work on the
// Editor, but then we should be able to do:
//
// context.getSharedPreferences(..).edit().putString(..).apply()
//
// ... all without blocking.
- getLoadedWithBlockGuard();
+ synchronized (mLock) {
+ awaitLoadedLocked();
+ }
return new EditorImpl();
}
@@ -471,43 +501,13 @@
// a memory commit comes in when we're already
// writing to disk.
if (mDiskWritesInFlight > 0) {
- // We can't modify our map as a currently
+ // We can't modify our mMap as a currently
// in-flight write owns it. Clone it before
// modifying it.
// noinspection unchecked
- mMap = new Future<Map<String, Object>>() {
- private Map<String, Object> mCopiedMap =
- new HashMap<String, Object>(getLoaded());
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- return false;
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
-
- @Override
- public boolean isDone() {
- return true;
- }
-
- @Override
- public Map<String, Object> get()
- throws InterruptedException, ExecutionException {
- return mCopiedMap;
- }
-
- @Override
- public Map<String, Object> get(long timeout, TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
- return mCopiedMap;
- }
- };
+ mMap = new HashMap<String, Object>(mMap);
}
- mapToWriteToDisk = getLoaded();
+ mapToWriteToDisk = mMap;
mDiskWritesInFlight++;
boolean hasListeners = mListeners.size() > 0;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index ab70f0e7..97c6681 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -81,10 +81,10 @@
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
-import android.net.nsd.INsdManager;
-import android.net.nsd.NsdManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
import android.net.wifi.IRttManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.IWifiScanner;
@@ -130,6 +130,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -504,6 +505,13 @@
return new EuiccManager(ctx.getOuterContext());
}});
+ registerService(Context.EUICC_CARD_SERVICE, EuiccCardManager.class,
+ new CachedServiceFetcher<EuiccCardManager>() {
+ @Override
+ public EuiccCardManager createService(ContextImpl ctx) {
+ return new EuiccCardManager(ctx.getOuterContext());
+ }});
+
registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
new CachedServiceFetcher<UiModeManager>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 7841b83..35a21a4 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -103,6 +104,24 @@
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
/**
+ * Intent used to broadcast the selection of a connected device as active.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_ACTIVE_DEVICE_CHANGED =
+ "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
+
+ /**
* Intent used to broadcast the change in the Audio Codec state of the
* A2DP Source profile.
*
@@ -425,6 +444,75 @@
}
/**
+ * Select a connected device as active.
+ *
+ * The active device selection is per profile. An active device's
+ * purpose is profile-specific. For example, A2DP audio streaming
+ * is to the active A2DP Sink device. If a remote device is not
+ * connected, it cannot be selected as active.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is not connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that the
+ * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+ * with the active device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device the remote Bluetooth device. Could be null to clear
+ * the active device and stop streaming audio to a Bluetooth device.
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+ if (DBG) log("setActiveDevice(" + device + ")");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && ((device == null) || isValidDevice(device))) {
+ return mService.setActiveDevice(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Get the connected device that is active.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+ * permission.
+ *
+ * @return the connected device that is active or null if no device
+ * is active
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @Nullable
+ public BluetoothDevice getActiveDevice() {
+ if (VDBG) log("getActiveDevice()");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ return mService.getActiveDevice();
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return null;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Set priority of the profile
*
* <p> The device should already be paired.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 158aebb..c7be0f3 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2425,6 +2425,8 @@
*
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean enableNoAutoConnect() {
if (isEnabled()) {
if (DBG) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index d982bb7..9b736b7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -618,6 +618,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_UNKNOWN = 0;
/**
@@ -626,6 +627,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_ALLOWED = 1;
/**
@@ -634,6 +636,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_REJECTED = 2;
/**
@@ -1098,6 +1101,8 @@
* @return true on success, false on error
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean cancelBondProcess() {
final IBluetooth service = sService;
if (service == null) {
@@ -1125,6 +1130,8 @@
* @return true on success, false on error
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean removeBond() {
final IBluetooth service = sService;
if (service == null) {
@@ -1174,6 +1181,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
public boolean isConnected() {
final IBluetooth service = sService;
if (service == null) {
@@ -1197,6 +1205,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
public boolean isEncrypted() {
final IBluetooth service = sService;
if (service == null) {
@@ -1444,6 +1453,8 @@
* @return Whether the value has been successfully set.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
public boolean setPhonebookAccessPermission(int value) {
final IBluetooth service = sService;
if (service == null) {
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 90ae0e6..a68f485 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -16,8 +16,11 @@
package android.bluetooth;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
@@ -91,6 +94,23 @@
public static final String ACTION_AUDIO_STATE_CHANGED =
"android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
+ /**
+ * Intent used to broadcast the selection of a connected device as active.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_ACTIVE_DEVICE_CHANGED =
+ "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
/**
* Intent used to broadcast that the headset has posted a
@@ -416,6 +436,8 @@
* @return false on immediate error, true otherwise
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -456,6 +478,8 @@
* @return false on immediate error, true otherwise
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -532,8 +556,8 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
+ * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
+ * {@link BluetoothProfile#PRIORITY_OFF},
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* permission.
@@ -543,6 +567,8 @@
* @return true if priority is set, false on error
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothHeadset service = mService;
@@ -975,9 +1001,105 @@
}
/**
- * check if in-band ringing is supported for this platform.
+ * Select a connected device as active.
*
- * @return true if in-band ringing is supported false if in-band ringing is not supported
+ * The active device selection is per profile. An active device's
+ * purpose is profile-specific. For example, in HFP and HSP profiles,
+ * it is the device used for phone call audio. If a remote device is not
+ * connected, it cannot be selected as active.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is not connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that the
+ * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+ * with the active device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Remote Bluetooth Device, could be null if phone call audio should not be
+ * streamed to a headset
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+ if (DBG) {
+ Log.d(TAG, "setActiveDevice: " + device);
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && (device == null || isValidDevice(device))) {
+ try {
+ return service.setActiveDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ }
+
+ /**
+ * Get the connected device that is active.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+ * permission.
+ *
+ * @return the connected device that is active or null if no device
+ * is active.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+ public BluetoothDevice getActiveDevice() {
+ if (VDBG) {
+ Log.d(TAG, "getActiveDevice");
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
+ try {
+ return service.getActiveDevice();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return null;
+ }
+
+ /**
+ * Check if in-band ringing is currently enabled. In-band ringing could be disabled during an
+ * active connection.
+ *
+ * @return true if in-band ringing is enabled, false if in-band ringing is disabled
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+ public boolean isInbandRingingEnabled() {
+ if (DBG) {
+ log("isInbandRingingEnabled()");
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
+ try {
+ return service.isInbandRingingEnabled();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ }
+
+ /**
+ * Check if in-band ringing is supported for this platform.
+ *
+ * @return true if in-band ringing is supported, false if in-band ringing is not supported
* @hide
*/
public static boolean isInbandRingingSupported(Context context) {
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index df2028a..0e2263f 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import java.util.List;
@@ -157,12 +158,19 @@
public static final int HID_DEVICE = 19;
/**
+ * Object Push Profile (OPP)
+ *
+ * @hide
+ */
+ public static final int OPP = 20;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- public static final int MAX_PROFILE_ID = 19;
+ public static final int MAX_PROFILE_ID = 20;
/**
* Default priority for devices that we try to auto-connect to and
@@ -178,6 +186,7 @@
*
* @hide
**/
+ @SystemApi
public static final int PRIORITY_ON = 100;
/**
@@ -186,6 +195,7 @@
*
* @hide
**/
+ @SystemApi
public static final int PRIORITY_OFF = 0;
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7e2ac63..70087da 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3589,8 +3589,18 @@
public static final String EUICC_SERVICE = "euicc_service";
/**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.text.ClipboardManager} for accessing and modifying
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.telephony.euicc.EuiccCardManager} to access the device eUICC (embedded SIM).
+ *
+ * @see #getSystemService(String)
+ * @see android.telephony.euicc.EuiccCardManager
+ * TODO(b/35851809): Make this a SystemApi.
+ * @hide
+ */
+ public static final String EUICC_CARD_SERVICE = "euicc_card_service";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.ClipboardManager} for accessing and modifying
* the contents of the global clipboard.
*
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8071e8b..11d338d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1794,7 +1794,7 @@
ITelephony it = ITelephony.Stub.asInterface(b);
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId);
- boolean retVal = it.getDataEnabled(subId);
+ boolean retVal = it.isUserDataEnabled(subId);
Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId
+ " retVal=" + retVal);
return retVal;
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index f82627b..7d752e8 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -231,6 +231,31 @@
}
}
+ /** @hide */
+ public boolean isAuthentication() {
+ switch (getName()) {
+ // Fallthrough
+ case AUTH_HMAC_MD5:
+ case AUTH_HMAC_SHA1:
+ case AUTH_HMAC_SHA256:
+ case AUTH_HMAC_SHA384:
+ case AUTH_HMAC_SHA512:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** @hide */
+ public boolean isEncryption() {
+ return getName().equals(CRYPT_AES_CBC);
+ }
+
+ /** @hide */
+ public boolean isAead() {
+ return getName().equals(AUTH_CRYPT_AES_GCM);
+ }
+
@Override
public String toString() {
return new StringBuilder()
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index e6cd3fc..f54ceb5 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -102,17 +102,11 @@
/** Set the local IP address for Tunnel mode */
public void setLocalAddress(String localAddress) {
- if (localAddress == null) {
- throw new IllegalArgumentException("localAddress may not be null!");
- }
mLocalAddress = localAddress;
}
/** Set the remote IP address for this IPsec transform */
public void setRemoteAddress(String remoteAddress) {
- if (remoteAddress == null) {
- throw new IllegalArgumentException("remoteAddress may not be null!");
- }
mRemoteAddress = remoteAddress;
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 6a4b891..34cfa9b 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -69,7 +69,7 @@
}
/** @hide */
- public static final int INVALID_RESOURCE_ID = 0;
+ public static final int INVALID_RESOURCE_ID = -1;
/**
* Thrown to indicate that a requested SPI is in use.
@@ -128,7 +128,7 @@
private final InetAddress mRemoteAddress;
private final CloseGuard mCloseGuard = CloseGuard.get();
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
- private int mResourceId;
+ private int mResourceId = INVALID_RESOURCE_ID;
/** Get the underlying SPI held by this object. */
public int getSpi() {
@@ -146,6 +146,7 @@
public void close() {
try {
mService.releaseSecurityParameterIndex(mResourceId);
+ mResourceId = INVALID_RESOURCE_ID;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -501,7 +502,7 @@
public static final class UdpEncapsulationSocket implements AutoCloseable {
private final ParcelFileDescriptor mPfd;
private final IIpSecService mService;
- private final int mResourceId;
+ private int mResourceId = INVALID_RESOURCE_ID;
private final int mPort;
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -554,6 +555,7 @@
public void close() throws IOException {
try {
mService.closeUdpEncapsulationSocket(mResourceId);
+ mResourceId = INVALID_RESOURCE_ID;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 7cd742b..102ba6d 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -347,6 +347,9 @@
*/
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());
return this;
}
@@ -381,6 +384,9 @@
public IpSecTransform.Builder setIpv4Encapsulation(
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
mConfig.setEncapType(ENCAP_ESPINUDP);
+ if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
+ throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
+ }
mConfig.setEncapSocketResourceId(localSocket.getResourceId());
mConfig.setEncapRemotePort(remotePort);
return this;
@@ -426,6 +432,9 @@
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
+ if (remoteAddress == null) {
+ throw new IllegalArgumentException("Remote address may not be null or empty!");
+ }
mConfig.setMode(MODE_TRANSPORT);
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
// FIXME: modifying a builder after calling build can change the built transform.
@@ -447,8 +456,12 @@
*/
public IpSecTransform buildTunnelModeTransform(
InetAddress localAddress, InetAddress remoteAddress) {
- // FIXME: argument validation here
- // throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
+ 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!");
+ }
mConfig.setLocalAddress(localAddress.getHostAddress());
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
mConfig.setMode(MODE_TUNNEL);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 1b707bd..336e1b4 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -35,6 +35,9 @@
import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
/**
* Base class for a remotable object, the core part of a lightweight
@@ -789,7 +792,7 @@
/**
* Return the total number of pairs in the map.
*/
- int size() {
+ private int size() {
int size = 0;
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
@@ -800,6 +803,24 @@
}
/**
+ * Return the total number of pairs in the map containing values that have
+ * not been cleared. More expensive than the above size function.
+ */
+ private int unclearedSize() {
+ int size = 0;
+ for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+ if (a != null) {
+ for (WeakReference<BinderProxy> ref : a) {
+ if (ref.get() != null) {
+ ++size;
+ }
+ }
+ }
+ }
+ return size;
+ }
+
+ /**
* Remove ith entry from the hash bucket indicated by hash.
*/
private void remove(int hash, int index) {
@@ -888,17 +909,71 @@
keyArray[size] = key;
}
if (size >= mWarnBucketSize) {
- final int total_size = size();
+ final int totalSize = size();
Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
- + " total = " + total_size);
+ + " total = " + totalSize);
mWarnBucketSize += WARN_INCREMENT;
- if (Build.IS_DEBUGGABLE && total_size > CRASH_AT_SIZE) {
- throw new AssertionError("Binder ProxyMap has too many entries. "
- + "BinderProxy leak?");
+ if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
+ // Use the number of uncleared entries to determine whether we should
+ // really report a histogram and crash. We don't want to fundamentally
+ // change behavior for a debuggable process, so we GC only if we are
+ // about to crash.
+ final int totalUnclearedSize = unclearedSize();
+ if (totalUnclearedSize >= CRASH_AT_SIZE) {
+ dumpProxyInterfaceCounts();
+ Runtime.getRuntime().gc();
+ throw new AssertionError("Binder ProxyMap has too many entries: "
+ + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
+ + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
+ } else if (totalSize > 3 * totalUnclearedSize / 2) {
+ Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
+ + (totalSize - totalUnclearedSize) + " of " + totalSize
+ + " are cleared");
+ }
}
}
}
+ /**
+ * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
+ */
+ private void dumpProxyInterfaceCounts() {
+ Map<String, Integer> counts = new HashMap<>();
+ for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+ if (a != null) {
+ for (WeakReference<BinderProxy> weakRef : a) {
+ BinderProxy bp = weakRef.get();
+ String key;
+ if (bp == null) {
+ key = "<cleared weak-ref>";
+ } else {
+ try {
+ key = bp.getInterfaceDescriptor();
+ } catch (Throwable t) {
+ key = "<exception during getDescriptor>";
+ }
+ }
+ Integer i = counts.get(key);
+ if (i == null) {
+ counts.put(key, 1);
+ } else {
+ counts.put(key, i + 1);
+ }
+ }
+ }
+ }
+ Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
+ new Map.Entry[counts.size()]);
+ Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
+ -> b.getValue().compareTo(a.getValue()));
+ Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):");
+ int printLength = Math.min(10, sorted.length);
+ for (int i = 0; i < printLength; i++) {
+ Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x"
+ + sorted[i].getValue());
+ }
+ }
+
// Corresponding ArrayLists in the following two arrays always have the same size.
// They contain no empty entries. However WeakReferences in the values ArrayLists
// may have been cleared.
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index a080c8d..4d7d931 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -86,6 +86,25 @@
}
/**
+ * Class which can be used to fetch an object out of a lambda. Fetching an object
+ * out of a local scope with HIDL is a common operation (although usually it can
+ * and should be avoided).
+ *
+ * @param <E> Inner object type.
+ */
+ public static final class Mutable<E> {
+ public E value;
+
+ public Mutable() {
+ value = null;
+ }
+
+ public Mutable(E value) {
+ this.value = value;
+ }
+ }
+
+ /**
* Similar to Arrays.deepHashCode, but also take care of lists.
*/
public static int deepHashCode(Object o) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index a474b47..a5e1934 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -339,7 +339,8 @@
/**
* Configure name servers, search paths, and resolver parameters for the given network.
*/
- void setDnsConfigurationForNetwork(int netId, in String[] servers, String domains);
+ void setDnsConfigurationForNetwork(int netId, in String[] servers, in String[] domains,
+ in int[] params, boolean useTls, String tlsHostname);
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8533c7e..18f3a14 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1083,12 +1083,14 @@
/** {@hide} */
public static Pair<String, Long> getPrimaryStoragePathAndSize() {
return Pair.create(null,
- FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()));
+ FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()
+ + Environment.getRootDirectory().getTotalSpace()));
}
/** {@hide} */
public long getPrimaryStorageSize() {
- return FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace());
+ return FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()
+ + Environment.getRootDirectory().getTotalSpace());
}
/** @removed */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ca9544a..ed68276 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -65,6 +65,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.speech.tts.TextToSpeech;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.ArrayMap;
@@ -10077,8 +10078,12 @@
* <p>
* Type: int (0 for false, 1 for true)
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+ * instead.
*/
- public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
+ @Deprecated
+ public static final String ENHANCED_4G_MODE_ENABLED =
+ SubscriptionManager.ENHANCED_4G_MODE_ENABLED;
/**
* Whether VT (Video Telephony over IMS) is enabled
@@ -10086,8 +10091,10 @@
* Type: int (0 for false, 1 for true)
*
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#VT_IMS_ENABLED} instead.
*/
- public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+ @Deprecated
+ public static final String VT_IMS_ENABLED = SubscriptionManager.VT_IMS_ENABLED;
/**
* Whether WFC is enabled
@@ -10095,8 +10102,10 @@
* Type: int (0 for false, 1 for true)
*
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ENABLED} instead.
*/
- public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
+ @Deprecated
+ public static final String WFC_IMS_ENABLED = SubscriptionManager.WFC_IMS_ENABLED;
/**
* WFC mode on home/non-roaming network.
@@ -10104,8 +10113,10 @@
* Type: int - 2=Wi-Fi preferred, 1=Cellular preferred, 0=Wi-Fi only
*
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_MODE} instead.
*/
- public static final String WFC_IMS_MODE = "wfc_ims_mode";
+ @Deprecated
+ public static final String WFC_IMS_MODE = SubscriptionManager.WFC_IMS_MODE;
/**
* WFC mode on roaming network.
@@ -10113,8 +10124,11 @@
* Type: int - see {@link #WFC_IMS_MODE} for values
*
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ROAMING_MODE}
+ * instead.
*/
- public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
+ @Deprecated
+ public static final String WFC_IMS_ROAMING_MODE = SubscriptionManager.WFC_IMS_ROAMING_MODE;
/**
* Whether WFC roaming is enabled
@@ -10122,8 +10136,12 @@
* Type: int (0 for false, 1 for true)
*
* @hide
+ * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ROAMING_ENABLED}
+ * instead
*/
- public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
+ @Deprecated
+ public static final String WFC_IMS_ROAMING_ENABLED =
+ SubscriptionManager.WFC_IMS_ROAMING_ENABLED;
/**
* Whether user can enable/disable LTE as a preferred network. A carrier might control
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index b47e872..09bba4b 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -16,9 +16,14 @@
package android.service.carrier;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telephony.uicc.IccUtils;
+
+import java.util.Objects;
+
/**
* Used to pass info to CarrierConfigService implementations so they can decide what values to
* return.
@@ -40,13 +45,13 @@
private String mMcc;
private String mMnc;
- private String mSpn;
- private String mImsi;
- private String mGid1;
- private String mGid2;
+ private @Nullable String mSpn;
+ private @Nullable String mImsi;
+ private @Nullable String mGid1;
+ private @Nullable String mGid2;
- public CarrierIdentifier(String mcc, String mnc, String spn, String imsi, String gid1,
- String gid2) {
+ public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
+ @Nullable String gid1, @Nullable String gid2) {
mMcc = mcc;
mMnc = mnc;
mSpn = spn;
@@ -55,6 +60,32 @@
mGid2 = gid2;
}
+ /**
+ * Creates a carrier identifier instance.
+ *
+ * @param mccMnc A 3-byte array as defined by 3GPP TS 24.008.
+ * @param gid1 The group identifier level 1.
+ * @param gid2 The group identifier level 2.
+ * @throws IllegalArgumentException If the length of {@code mccMnc} is not 3.
+ */
+ public CarrierIdentifier(byte[] mccMnc, @Nullable String gid1, @Nullable String gid2) {
+ if (mccMnc.length != 3) {
+ throw new IllegalArgumentException(
+ "MCC & MNC must be set by a 3-byte array: byte[" + mccMnc.length + "]");
+ }
+ String hex = IccUtils.bytesToHexString(mccMnc);
+ mMcc = new String(new char[] {hex.charAt(1), hex.charAt(0), hex.charAt(3)});
+ if (hex.charAt(2) == 'F') {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4)});
+ } else {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4), hex.charAt(2)});
+ }
+ mGid1 = gid1;
+ mGid2 = gid2;
+ mSpn = null;
+ mImsi = null;
+ }
+
/** @hide */
public CarrierIdentifier(Parcel parcel) {
readFromParcel(parcel);
@@ -71,26 +102,60 @@
}
/** Get the service provider name. */
+ @Nullable
public String getSpn() {
return mSpn;
}
/** Get the international mobile subscriber identity. */
+ @Nullable
public String getImsi() {
return mImsi;
}
/** Get the group identifier level 1. */
+ @Nullable
public String getGid1() {
return mGid1;
}
/** Get the group identifier level 2. */
+ @Nullable
public String getGid2() {
return mGid2;
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ CarrierIdentifier that = (CarrierIdentifier) obj;
+ return Objects.equals(mMcc, that.mMcc)
+ && Objects.equals(mMnc, that.mMnc)
+ && Objects.equals(mSpn, that.mSpn)
+ && Objects.equals(mImsi, that.mImsi)
+ && Objects.equals(mGid1, that.mGid1)
+ && Objects.equals(mGid2, that.mGid2);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(mMcc);
+ result = 31 * result + Objects.hashCode(mMnc);
+ result = 31 * result + Objects.hashCode(mSpn);
+ result = 31 * result + Objects.hashCode(mImsi);
+ result = 31 * result + Objects.hashCode(mGid1);
+ result = 31 * result + Objects.hashCode(mGid2);
+ return result;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.aidl b/core/java/android/service/euicc/EuiccProfileInfo.aidl
new file mode 100644
index 0000000..321021b
--- /dev/null
+++ b/core/java/android/service/euicc/EuiccProfileInfo.aidl
@@ -0,0 +1,18 @@
+/*
+ * 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 android.service.euicc;
+
+parcelable EuiccProfileInfo;
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index ba6c9a2..8e752d1 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -15,12 +15,19 @@
*/
package android.service.euicc;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
import android.telephony.UiccAccessRule;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Information about an embedded profile (subscription) on an eUICC.
*
@@ -30,18 +37,90 @@
*/
public final class EuiccProfileInfo implements Parcelable {
+ /** Profile policy rules (bit mask) */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "POLICY_RULE_" }, value = {
+ POLICY_RULE_DO_NOT_DISABLE,
+ POLICY_RULE_DO_NOT_DELETE,
+ POLICY_RULE_DELETE_AFTER_DISABLING
+ })
+ public @interface PolicyRule {}
+ /** Once this profile is enabled, it cannot be disabled. */
+ public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
+ /** This profile cannot be deleted. */
+ public static final int POLICY_RULE_DO_NOT_DELETE = 1 << 1;
+ /** This profile should be deleted after being disabled. */
+ public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 1 << 2;
+
+ /** Class of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
+ PROFILE_CLASS_TESTING,
+ PROFILE_CLASS_PROVISIONING,
+ PROFILE_CLASS_OPERATIONAL,
+ PROFILE_CLASS_UNSET
+ })
+ public @interface ProfileClass {}
+ /** Testing profiles */
+ public static final int PROFILE_CLASS_TESTING = 0;
+ /** Provisioning profiles which are pre-loaded on eUICC */
+ public static final int PROFILE_CLASS_PROVISIONING = 1;
+ /** Operational profiles which can be pre-loaded or downloaded */
+ public static final int PROFILE_CLASS_OPERATIONAL = 2;
+ /**
+ * Profile class not set.
+ * @hide
+ */
+ public static final int PROFILE_CLASS_UNSET = -1;
+
+ /** State of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_STATE_" }, value = {
+ PROFILE_STATE_DISABLED,
+ PROFILE_STATE_ENABLED,
+ PROFILE_STATE_UNSET
+ })
+ public @interface ProfileState {}
+ /** Disabled profiles */
+ public static final int PROFILE_STATE_DISABLED = 0;
+ /** Enabled profile */
+ public static final int PROFILE_STATE_ENABLED = 1;
+ /**
+ * Profile state not set.
+ * @hide
+ */
+ public static final int PROFILE_STATE_UNSET = -1;
+
/** The iccid of the subscription. */
public final String iccid;
+ /** An optional nickname for the subscription. */
+ public final @Nullable String nickname;
+
+ /** The service provider name for the subscription. */
+ public final String serviceProviderName;
+
+ /** The profile name for the subscription. */
+ public final String profileName;
+
+ /** Profile class for the subscription. */
+ @ProfileClass public final int profileClass;
+
+ /** The profile state of the subscription. */
+ @ProfileState public final int state;
+
+ /** The operator Id of the subscription. */
+ public final CarrierIdentifier carrierIdentifier;
+
+ /** The policy rules of the subscription. */
+ @PolicyRule public final int policyRules;
+
/**
* Optional access rules defining which apps can manage this subscription. If unset, only the
* platform can manage it.
*/
public final @Nullable UiccAccessRule[] accessRules;
- /** An optional nickname for the subscription. */
- public final @Nullable String nickname;
-
public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
@Override
public EuiccProfileInfo createFromParcel(Parcel in) {
@@ -54,6 +133,12 @@
}
};
+ // TODO(b/70292228): Remove this method when LPA can be updated.
+ /**
+ * @hide
+ * @deprecated - Do not use.
+ */
+ @Deprecated
public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
@Nullable String nickname) {
if (!TextUtils.isDigitsOnly(iccid)) {
@@ -62,23 +147,290 @@
this.iccid = iccid;
this.accessRules = accessRules;
this.nickname = nickname;
+
+ this.serviceProviderName = null;
+ this.profileName = null;
+ this.profileClass = PROFILE_CLASS_UNSET;
+ this.state = PROFILE_CLASS_UNSET;
+ this.carrierIdentifier = null;
+ this.policyRules = 0;
}
private EuiccProfileInfo(Parcel in) {
iccid = in.readString();
- accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
nickname = in.readString();
+ serviceProviderName = in.readString();
+ profileName = in.readString();
+ profileClass = in.readInt();
+ state = in.readInt();
+ byte exist = in.readByte();
+ if (exist == (byte) 1) {
+ carrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
+ } else {
+ carrierIdentifier = null;
+ }
+ policyRules = in.readInt();
+ accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(iccid);
- dest.writeTypedArray(accessRules, flags);
dest.writeString(nickname);
+ dest.writeString(serviceProviderName);
+ dest.writeString(profileName);
+ dest.writeInt(profileClass);
+ dest.writeInt(state);
+ if (carrierIdentifier != null) {
+ dest.writeByte((byte) 1);
+ carrierIdentifier.writeToParcel(dest, flags);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ dest.writeInt(policyRules);
+ dest.writeTypedArray(accessRules, flags);
}
@Override
public int describeContents() {
return 0;
}
+
+ /** The builder to build a new {@link EuiccProfileInfo} instance. */
+ public static final class Builder {
+ public String iccid;
+ public UiccAccessRule[] accessRules;
+ public String nickname;
+ public String serviceProviderName;
+ public String profileName;
+ @ProfileClass public int profileClass;
+ @ProfileState public int state;
+ public CarrierIdentifier carrierIdentifier;
+ @PolicyRule public int policyRules;
+
+ public Builder() {}
+
+ public Builder(EuiccProfileInfo baseProfile) {
+ iccid = baseProfile.iccid;
+ nickname = baseProfile.nickname;
+ serviceProviderName = baseProfile.serviceProviderName;
+ profileName = baseProfile.profileName;
+ profileClass = baseProfile.profileClass;
+ state = baseProfile.state;
+ carrierIdentifier = baseProfile.carrierIdentifier;
+ policyRules = baseProfile.policyRules;
+ accessRules = baseProfile.accessRules;
+ }
+
+ /** Builds the profile instance. */
+ public EuiccProfileInfo build() {
+ if (iccid == null) {
+ throw new IllegalStateException("ICCID must be set for a profile.");
+ }
+ return new EuiccProfileInfo(
+ iccid,
+ nickname,
+ serviceProviderName,
+ profileName,
+ profileClass,
+ state,
+ carrierIdentifier,
+ policyRules,
+ accessRules);
+ }
+
+ /** Sets the iccId of the subscription. */
+ public Builder setIccid(String value) {
+ if (!TextUtils.isDigitsOnly(value)) {
+ throw new IllegalArgumentException("iccid contains invalid characters: " + value);
+ }
+ iccid = value;
+ return this;
+ }
+
+ /** Sets the nickname of the subscription. */
+ public Builder setNickname(String value) {
+ nickname = value;
+ return this;
+ }
+
+ /** Sets the service provider name of the subscription. */
+ public Builder setServiceProviderName(String value) {
+ serviceProviderName = value;
+ return this;
+ }
+
+ /** Sets the profile name of the subscription. */
+ public Builder setProfileName(String value) {
+ profileName = value;
+ return this;
+ }
+
+ /** Sets the profile class of the subscription. */
+ public Builder setProfileClass(@ProfileClass int value) {
+ profileClass = value;
+ return this;
+ }
+
+ /** Sets the state of the subscription. */
+ public Builder setState(@ProfileState int value) {
+ state = value;
+ return this;
+ }
+
+ /** Sets the carrier identifier of the subscription. */
+ public Builder setCarrierIdentifier(CarrierIdentifier value) {
+ carrierIdentifier = value;
+ return this;
+ }
+
+ /** Sets the policy rules of the subscription. */
+ public Builder setPolicyRules(@PolicyRule int value) {
+ policyRules = value;
+ return this;
+ }
+
+ /** Sets the access rules of the subscription. */
+ public Builder setUiccAccessRule(@Nullable UiccAccessRule[] value) {
+ accessRules = value;
+ return this;
+ }
+ }
+
+ private EuiccProfileInfo(
+ String iccid,
+ @Nullable String nickname,
+ String serviceProviderName,
+ String profileName,
+ @ProfileClass int profileClass,
+ @ProfileState int state,
+ CarrierIdentifier carrierIdentifier,
+ @PolicyRule int policyRules,
+ @Nullable UiccAccessRule[] accessRules) {
+ this.iccid = iccid;
+ this.nickname = nickname;
+ this.serviceProviderName = serviceProviderName;
+ this.profileName = profileName;
+ this.profileClass = profileClass;
+ this.state = state;
+ this.carrierIdentifier = carrierIdentifier;
+ this.policyRules = policyRules;
+ this.accessRules = accessRules;
+ }
+
+ /** Gets the ICCID string. */
+ public String getIccid() {
+ return iccid;
+ }
+
+ /** Gets the access rules. */
+ @Nullable
+ public UiccAccessRule[] getUiccAccessRules() {
+ return accessRules;
+ }
+
+ /** Gets the nickname. */
+ public String getNickname() {
+ return nickname;
+ }
+
+ /** Gets the service provider name. */
+ public String getServiceProviderName() {
+ return serviceProviderName;
+ }
+
+ /** Gets the profile name. */
+ public String getProfileName() {
+ return profileName;
+ }
+
+ /** Gets the profile class. */
+ @ProfileClass
+ public int getProfileClass() {
+ return profileClass;
+ }
+
+ /** Gets the state of the subscription. */
+ @ProfileState
+ public int getState() {
+ return state;
+ }
+
+ /** Gets the carrier identifier. */
+ public CarrierIdentifier getCarrierIdentifier() {
+ return carrierIdentifier;
+ }
+
+ /** Gets the policy rules. */
+ @PolicyRule
+ public int getPolicyRules() {
+ return policyRules;
+ }
+
+ /** Returns whether any policy rule exists. */
+ public boolean hasPolicyRules() {
+ return policyRules != 0;
+ }
+
+ /** Checks whether a certain policy rule exists. */
+ public boolean hasPolicyRule(@PolicyRule int policy) {
+ return (policyRules & policy) != 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccProfileInfo that = (EuiccProfileInfo) obj;
+ return Objects.equals(iccid, that.iccid)
+ && Objects.equals(nickname, that.nickname)
+ && Objects.equals(serviceProviderName, that.serviceProviderName)
+ && Objects.equals(profileName, that.profileName)
+ && profileClass == that.profileClass
+ && state == that.state
+ && Objects.equals(carrierIdentifier, that.carrierIdentifier)
+ && policyRules == that.policyRules
+ && Arrays.equals(accessRules, that.accessRules);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(iccid);
+ result = 31 * result + Objects.hashCode(nickname);
+ result = 31 * result + Objects.hashCode(serviceProviderName);
+ result = 31 * result + Objects.hashCode(profileName);
+ result = 31 * result + profileClass;
+ result = 31 * result + state;
+ result = 31 * result + Objects.hashCode(carrierIdentifier);
+ result = 31 * result + policyRules;
+ result = 31 * result + Arrays.hashCode(accessRules);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "EuiccProfileInfo (nickname="
+ + nickname
+ + ", serviceProviderName="
+ + serviceProviderName
+ + ", profileName="
+ + profileName
+ + ", profileClass="
+ + profileClass
+ + ", state="
+ + state
+ + ", CarrierIdentifier="
+ + carrierIdentifier.toString()
+ + ", policyRules="
+ + policyRules
+ + ", accessRules="
+ + Arrays.toString(accessRules)
+ + ")";
+ }
}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index df0842f..be85800 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -23,6 +23,7 @@
import android.os.RemoteException;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
+import android.telephony.euicc.EuiccManager.OtaStatus;
import android.util.ArraySet;
import java.util.concurrent.LinkedBlockingQueue;
@@ -192,6 +193,18 @@
}
/**
+ * Callback class for {@link #onStartOtaIfNecessary(int, OtaStatusChangedCallback)}
+ *
+ * The status of OTA which can be {@code android.telephony.euicc.EuiccManager#EUICC_OTA_}
+ *
+ * @see IEuiccService#startOtaIfNecessary
+ */
+ public interface OtaStatusChangedCallback {
+ /** Called when OTA status is changed. */
+ void onOtaStatusChanged(int status);
+ }
+
+ /**
* Return the EID of the eUICC.
*
* @param slotId ID of the SIM slot being queried. This is currently not populated but is here
@@ -203,6 +216,26 @@
public abstract String onGetEid(int slotId);
/**
+ * Return the status of OTA update.
+ *
+ * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
+ * but is here to future-proof the APIs.
+ * @return The status of Euicc OTA update.
+ * @see android.telephony.euicc.EuiccManager#getOtaStatus
+ */
+ public abstract @OtaStatus int onGetOtaStatus(int slotId);
+
+ /**
+ * Perform OTA if current OS is not the latest one.
+ *
+ * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
+ * but is here to future-proof the APIs.
+ * @param statusChangedCallback Function called when OTA status changed.
+ */
+ public abstract void onStartOtaIfNecessary(
+ int slotId, OtaStatusChangedCallback statusChangedCallback);
+
+ /**
* Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
*
* @param slotId ID of the SIM slot to use for the operation. This is currently not populated
@@ -385,6 +418,41 @@
}
@Override
+ public void startOtaIfNecessary(
+ int slotId, IOtaStatusChangedCallback statusChangedCallback) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ EuiccService.this.onStartOtaIfNecessary(slotId, new OtaStatusChangedCallback() {
+ @Override
+ public void onOtaStatusChanged(int status) {
+ try {
+ statusChangedCallback.onOtaStatusChanged(status);
+ } catch (RemoteException e) {
+ // Can't communicate with the phone process; ignore.
+ }
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public void getOtaStatus(int slotId, IGetOtaStatusCallback callback) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ int status = EuiccService.this.onGetOtaStatus(slotId);
+ try {
+ callback.onSuccess(status);
+ } catch (RemoteException e) {
+ // Can't communicate with the phone process; ignore.
+ }
+ }
+ });
+ }
+
+ @Override
public void getDownloadableSubscriptionMetadata(int slotId,
DownloadableSubscription subscription,
boolean forceDeactivateSim,
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index e10dd8c..45be527 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -24,6 +24,8 @@
import android.service.euicc.IGetEidCallback;
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
+import android.service.euicc.IGetOtaStatusCallback;
+import android.service.euicc.IOtaStatusChangedCallback;
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
@@ -37,6 +39,8 @@
void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
void getEid(int slotId, in IGetEidCallback callback);
+ void getOtaStatus(int slotId, in IGetOtaStatusCallback callback);
+ void startOtaIfNecessary(int slotId, in IOtaStatusChangedCallback statusChangedCallback);
void getEuiccProfileInfoList(int slotId, in IGetEuiccProfileInfoListCallback callback);
void getDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim,
in IGetDefaultDownloadableSubscriptionListCallback callback);
diff --git a/core/java/android/service/euicc/IGetOtaStatusCallback.aidl b/core/java/android/service/euicc/IGetOtaStatusCallback.aidl
new file mode 100644
index 0000000..f667888
--- /dev/null
+++ b/core/java/android/service/euicc/IGetOtaStatusCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.service.euicc;
+
+/** @hide */
+oneway interface IGetOtaStatusCallback {
+ void onSuccess(int status);
+}
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
new file mode 100644
index 0000000..caec75f
--- /dev/null
+++ b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.service.euicc;
+
+/** @hide */
+oneway interface IOtaStatusChangedCallback {
+ void onOtaStatusChanged(int status);
+}
\ No newline at end of file
diff --git a/core/java/android/webkit/FindAddress.java b/core/java/android/webkit/FindAddress.java
new file mode 100644
index 0000000..31b2427
--- /dev/null
+++ b/core/java/android/webkit/FindAddress.java
@@ -0,0 +1,478 @@
+/*
+ * 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 android.webkit;
+
+import java.util.Locale;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Java implementation of legacy WebView.findAddress algorithm.
+ *
+ * @hide
+ */
+class FindAddress {
+ static class ZipRange {
+ int mLow;
+ int mHigh;
+ int mException1;
+ int mException2;
+ ZipRange(int low, int high, int exception1, int exception2) {
+ mLow = low;
+ mHigh = high;
+ mException1 = exception1;
+ mException2 = exception1;
+ }
+ boolean matches(String zipCode) {
+ int prefix = Integer.parseInt(zipCode.substring(0, 2));
+ return (mLow <= prefix && prefix <= mHigh) || prefix == mException1
+ || prefix == mException2;
+ }
+ }
+
+ // Addresses consist of at least this many words, not including state and zip code.
+ private static final int MIN_ADDRESS_WORDS = 4;
+
+ // Adddresses consist of at most this many words, not including state and zip code.
+ private static final int MAX_ADDRESS_WORDS = 14;
+
+ // Addresses consist of at most this many lines.
+ private static final int MAX_ADDRESS_LINES = 5;
+
+ // No words in an address are longer than this many characters.
+ private static final int kMaxAddressNameWordLength = 25;
+
+ // Location name should be in the first MAX_LOCATION_NAME_DISTANCE words
+ private static final int MAX_LOCATION_NAME_DISTANCE = 5;
+
+ private static final ZipRange[] sStateZipCodeRanges = {
+ new ZipRange(99, 99, -1, -1), // AK Alaska.
+ new ZipRange(35, 36, -1, -1), // AL Alabama.
+ new ZipRange(71, 72, -1, -1), // AR Arkansas.
+ new ZipRange(96, 96, -1, -1), // AS American Samoa.
+ new ZipRange(85, 86, -1, -1), // AZ Arizona.
+ new ZipRange(90, 96, -1, -1), // CA California.
+ new ZipRange(80, 81, -1, -1), // CO Colorado.
+ new ZipRange(6, 6, -1, -1), // CT Connecticut.
+ new ZipRange(20, 20, -1, -1), // DC District of Columbia.
+ new ZipRange(19, 19, -1, -1), // DE Delaware.
+ new ZipRange(32, 34, -1, -1), // FL Florida.
+ new ZipRange(96, 96, -1, -1), // FM Federated States of Micronesia.
+ new ZipRange(30, 31, -1, -1), // GA Georgia.
+ new ZipRange(96, 96, -1, -1), // GU Guam.
+ new ZipRange(96, 96, -1, -1), // HI Hawaii.
+ new ZipRange(50, 52, -1, -1), // IA Iowa.
+ new ZipRange(83, 83, -1, -1), // ID Idaho.
+ new ZipRange(60, 62, -1, -1), // IL Illinois.
+ new ZipRange(46, 47, -1, -1), // IN Indiana.
+ new ZipRange(66, 67, 73, -1), // KS Kansas.
+ new ZipRange(40, 42, -1, -1), // KY Kentucky.
+ new ZipRange(70, 71, -1, -1), // LA Louisiana.
+ new ZipRange(1, 2, -1, -1), // MA Massachusetts.
+ new ZipRange(20, 21, -1, -1), // MD Maryland.
+ new ZipRange(3, 4, -1, -1), // ME Maine.
+ new ZipRange(96, 96, -1, -1), // MH Marshall Islands.
+ new ZipRange(48, 49, -1, -1), // MI Michigan.
+ new ZipRange(55, 56, -1, -1), // MN Minnesota.
+ new ZipRange(63, 65, -1, -1), // MO Missouri.
+ new ZipRange(96, 96, -1, -1), // MP Northern Mariana Islands.
+ new ZipRange(38, 39, -1, -1), // MS Mississippi.
+ new ZipRange(55, 56, -1, -1), // MT Montana.
+ new ZipRange(27, 28, -1, -1), // NC North Carolina.
+ new ZipRange(58, 58, -1, -1), // ND North Dakota.
+ new ZipRange(68, 69, -1, -1), // NE Nebraska.
+ new ZipRange(3, 4, -1, -1), // NH New Hampshire.
+ new ZipRange(7, 8, -1, -1), // NJ New Jersey.
+ new ZipRange(87, 88, 86, -1), // NM New Mexico.
+ new ZipRange(88, 89, 96, -1), // NV Nevada.
+ new ZipRange(10, 14, 0, 6), // NY New York.
+ new ZipRange(43, 45, -1, -1), // OH Ohio.
+ new ZipRange(73, 74, -1, -1), // OK Oklahoma.
+ new ZipRange(97, 97, -1, -1), // OR Oregon.
+ new ZipRange(15, 19, -1, -1), // PA Pennsylvania.
+ new ZipRange(6, 6, 0, 9), // PR Puerto Rico.
+ new ZipRange(96, 96, -1, -1), // PW Palau.
+ new ZipRange(2, 2, -1, -1), // RI Rhode Island.
+ new ZipRange(29, 29, -1, -1), // SC South Carolina.
+ new ZipRange(57, 57, -1, -1), // SD South Dakota.
+ new ZipRange(37, 38, -1, -1), // TN Tennessee.
+ new ZipRange(75, 79, 87, 88), // TX Texas.
+ new ZipRange(84, 84, -1, -1), // UT Utah.
+ new ZipRange(22, 24, 20, -1), // VA Virginia.
+ new ZipRange(6, 9, -1, -1), // VI Virgin Islands.
+ new ZipRange(5, 5, -1, -1), // VT Vermont.
+ new ZipRange(98, 99, -1, -1), // WA Washington.
+ new ZipRange(53, 54, -1, -1), // WI Wisconsin.
+ new ZipRange(24, 26, -1, -1), // WV West Virginia.
+ new ZipRange(82, 83, -1, -1) // WY Wyoming.
+ };
+
+ // Newlines
+ private static final String NL = "\n\u000B\u000C\r\u0085\u2028\u2029";
+
+ // Space characters
+ private static final String SP = "\u0009\u0020\u00A0\u1680\u2000\u2001"
+ + "\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F"
+ + "\u205F\u3000";
+
+ // Whitespace
+ private static final String WS = SP + NL;
+
+ // Characters that are considered word delimiters.
+ private static final String WORD_DELIM = ",*\u2022" + WS;
+
+ // Lookahead for word end.
+ private static final String WORD_END = "(?=[" + WORD_DELIM + "]|$)";
+
+ // Address words are a sequence of non-delimiter characters.
+ private static final Pattern sWordRe =
+ Pattern.compile("[^" + WORD_DELIM + "]+" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+ // Characters that are considered suffix delimiters for house numbers.
+ private static final String HOUSE_POST_DELIM = ",\"'" + WS;
+
+ // Lookahead for house end.
+ private static final String HOUSE_END = "(?=[" + HOUSE_POST_DELIM + "]|$)";
+
+ // Characters that are considered prefix delimiters for house numbers.
+ private static final String HOUSE_PRE_DELIM = ":" + HOUSE_POST_DELIM;
+
+ // A house number component is "one" or a number, optionally
+ // followed by a single alphabetic character, or
+ private static final String HOUSE_COMPONENT = "(?:one|\\d+([a-z](?=[^a-z]|$)|st|nd|rd|th)?)";
+
+ // House numbers are a repetition of |HOUSE_COMPONENT|, separated by -, and followed by
+ // a delimiter character.
+ private static final Pattern sHouseNumberRe =
+ Pattern.compile(HOUSE_COMPONENT + "(?:-" + HOUSE_COMPONENT + ")*" + HOUSE_END,
+ Pattern.CASE_INSENSITIVE);
+
+ // XXX: do we want to accept whitespace other than 0x20 in state names?
+ private static final Pattern sStateRe = Pattern.compile("(?:"
+ + "(ak|alaska)|"
+ + "(al|alabama)|"
+ + "(ar|arkansas)|"
+ + "(as|american[" + SP + "]+samoa)|"
+ + "(az|arizona)|"
+ + "(ca|california)|"
+ + "(co|colorado)|"
+ + "(ct|connecticut)|"
+ + "(dc|district[" + SP + "]+of[" + SP + "]+columbia)|"
+ + "(de|delaware)|"
+ + "(fl|florida)|"
+ + "(fm|federated[" + SP + "]+states[" + SP + "]+of[" + SP + "]+micronesia)|"
+ + "(ga|georgia)|"
+ + "(gu|guam)|"
+ + "(hi|hawaii)|"
+ + "(ia|iowa)|"
+ + "(id|idaho)|"
+ + "(il|illinois)|"
+ + "(in|indiana)|"
+ + "(ks|kansas)|"
+ + "(ky|kentucky)|"
+ + "(la|louisiana)|"
+ + "(ma|massachusetts)|"
+ + "(md|maryland)|"
+ + "(me|maine)|"
+ + "(mh|marshall[" + SP + "]+islands)|"
+ + "(mi|michigan)|"
+ + "(mn|minnesota)|"
+ + "(mo|missouri)|"
+ + "(mp|northern[" + SP + "]+mariana[" + SP + "]+islands)|"
+ + "(ms|mississippi)|"
+ + "(mt|montana)|"
+ + "(nc|north[" + SP + "]+carolina)|"
+ + "(nd|north[" + SP + "]+dakota)|"
+ + "(ne|nebraska)|"
+ + "(nh|new[" + SP + "]+hampshire)|"
+ + "(nj|new[" + SP + "]+jersey)|"
+ + "(nm|new[" + SP + "]+mexico)|"
+ + "(nv|nevada)|"
+ + "(ny|new[" + SP + "]+york)|"
+ + "(oh|ohio)|"
+ + "(ok|oklahoma)|"
+ + "(or|oregon)|"
+ + "(pa|pennsylvania)|"
+ + "(pr|puerto[" + SP + "]+rico)|"
+ + "(pw|palau)|"
+ + "(ri|rhode[" + SP + "]+island)|"
+ + "(sc|south[" + SP + "]+carolina)|"
+ + "(sd|south[" + SP + "]+dakota)|"
+ + "(tn|tennessee)|"
+ + "(tx|texas)|"
+ + "(ut|utah)|"
+ + "(va|virginia)|"
+ + "(vi|virgin[" + SP + "]+islands)|"
+ + "(vt|vermont)|"
+ + "(wa|washington)|"
+ + "(wi|wisconsin)|"
+ + "(wv|west[" + SP + "]+virginia)|"
+ + "(wy|wyoming)"
+ + ")" + WORD_END,
+ Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sLocationNameRe = Pattern.compile("(?:"
+ + "alley|annex|arcade|ave[.]?|avenue|alameda|bayou|"
+ + "beach|bend|bluffs?|bottom|boulevard|branch|bridge|"
+ + "brooks?|burgs?|bypass|broadway|camino|camp|canyon|"
+ + "cape|causeway|centers?|circles?|cliffs?|club|common|"
+ + "corners?|course|courts?|coves?|creek|crescent|crest|"
+ + "crossing|crossroad|curve|circulo|dale|dam|divide|"
+ + "drives?|estates?|expressway|extensions?|falls?|ferry|"
+ + "fields?|flats?|fords?|forest|forges?|forks?|fort|"
+ + "freeway|gardens?|gateway|glens?|greens?|groves?|"
+ + "harbors?|haven|heights|highway|hills?|hollow|inlet|"
+ + "islands?|isle|junctions?|keys?|knolls?|lakes?|land|"
+ + "landing|lane|lights?|loaf|locks?|lodge|loop|mall|"
+ + "manors?|meadows?|mews|mills?|mission|motorway|mount|"
+ + "mountains?|neck|orchard|oval|overpass|parks?|"
+ + "parkways?|pass|passage|path|pike|pines?|plains?|"
+ + "plaza|points?|ports?|prairie|privada|radial|ramp|"
+ + "ranch|rapids?|rd[.]?|rest|ridges?|river|roads?|route|"
+ + "row|rue|run|shoals?|shores?|skyway|springs?|spurs?|"
+ + "squares?|station|stravenue|stream|st[.]?|streets?|"
+ + "summit|speedway|terrace|throughway|trace|track|"
+ + "trafficway|trail|tunnel|turnpike|underpass|unions?|"
+ + "valleys?|viaduct|views?|villages?|ville|vista|walks?|"
+ + "wall|ways?|wells?|xing|xrd)" + WORD_END,
+ Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sSuffixedNumberRe =
+ Pattern.compile("(\\d+)(st|nd|rd|th)", Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sZipCodeRe =
+ Pattern.compile("(?:\\d{5}(?:-\\d{4})?)" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+ private static boolean checkHouseNumber(String houseNumber) {
+ // Make sure that there are at most 5 digits.
+ int digitCount = 0;
+ for (int i = 0; i < houseNumber.length(); ++i) {
+ if (Character.isDigit(houseNumber.charAt(i))) ++digitCount;
+ }
+ if (digitCount > 5) return false;
+
+ // Make sure that any ordinals are valid.
+ Matcher suffixMatcher = sSuffixedNumberRe.matcher(houseNumber);
+ while (suffixMatcher.find()) {
+ int num = Integer.parseInt(suffixMatcher.group(1));
+ if (num == 0) {
+ return false; // 0th is invalid.
+ }
+ String suffix = suffixMatcher.group(2).toLowerCase(Locale.getDefault());
+ switch (num % 10) {
+ case 1:
+ return suffix.equals(num % 100 == 11 ? "th" : "st");
+ case 2:
+ return suffix.equals(num % 100 == 12 ? "th" : "nd");
+ case 3:
+ return suffix.equals(num % 100 == 13 ? "th" : "rd");
+ default:
+ return suffix.equals("th");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Attempt to match a house number beginnning at position offset
+ * in content. The house number must be followed by a word
+ * delimiter or the end of the string, and if offset is non-zero,
+ * then it must also be preceded by a word delimiter.
+ *
+ * @return a MatchResult if a valid house number was found.
+ */
+ private static MatchResult matchHouseNumber(String content, int offset) {
+ if (offset > 0 && HOUSE_PRE_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+ Matcher matcher = sHouseNumberRe.matcher(content).region(offset, content.length());
+ if (matcher.lookingAt()) {
+ MatchResult matchResult = matcher.toMatchResult();
+ if (checkHouseNumber(matchResult.group(0))) return matchResult;
+ }
+ return null;
+ }
+
+ /**
+ * Attempt to match a US state beginnning at position offset in
+ * content. The matching state must be followed by a word
+ * delimiter or the end of the string, and if offset is non-zero,
+ * then it must also be preceded by a word delimiter.
+ *
+ * @return a MatchResult if a valid US state (or two letter code)
+ * was found.
+ */
+ private static MatchResult matchState(String content, int offset) {
+ if (offset > 0 && WORD_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+ Matcher stateMatcher = sStateRe.matcher(content).region(offset, content.length());
+ return stateMatcher.lookingAt() ? stateMatcher.toMatchResult() : null;
+ }
+
+ /**
+ * Test whether zipCode matches the U.S. zip code format (ddddd or
+ * ddddd-dddd) and is within the expected range, given that
+ * stateMatch is a match of sStateRe.
+ *
+ * @return true if zipCode is a valid zip code, is legal for the
+ * matched state, and is followed by a word delimiter or the end
+ * of the string.
+ */
+ private static boolean isValidZipCode(String zipCode, MatchResult stateMatch) {
+ if (stateMatch == null) return false;
+ // Work out the index of the state, based on which group matched.
+ int stateIndex = stateMatch.groupCount();
+ while (stateIndex > 0) {
+ if (stateMatch.group(stateIndex--) != null) break;
+ }
+ return sZipCodeRe.matcher(zipCode).matches()
+ && sStateZipCodeRanges[stateIndex].matches(zipCode);
+ }
+
+ /**
+ * Test whether location is one of the valid locations.
+ *
+ * @return true if location starts with a valid location name
+ * followed by a word delimiter or the end of the string.
+ */
+ private static boolean isValidLocationName(String location) {
+ return sLocationNameRe.matcher(location).matches();
+ }
+
+ /**
+ * Attempt to match a complete address in content, starting with
+ * houseNumberMatch.
+ *
+ * @param content The string to search.
+ * @param houseNumberMatch A matching house number to start extending.
+ * @return +ve: the end of the match
+ * +ve: the position to restart searching for house numbers, negated.
+ */
+ private static int attemptMatch(String content, MatchResult houseNumberMatch) {
+ int restartPos = -1;
+ int nonZipMatch = -1;
+ int it = houseNumberMatch.end();
+ int numLines = 1;
+ boolean consecutiveHouseNumbers = true;
+ boolean foundLocationName = false;
+ int wordCount = 1;
+ String lastWord = "";
+
+ Matcher matcher = sWordRe.matcher(content);
+
+ for (; it < content.length(); lastWord = matcher.group(0), it = matcher.end()) {
+ if (!matcher.find(it)) {
+ // No more words in the input sequence.
+ return -content.length();
+ }
+ if (matcher.end() - matcher.start() > kMaxAddressNameWordLength) {
+ // Word is too long to be part of an address. Fail.
+ return -matcher.end();
+ }
+
+ // Count the number of newlines we just consumed.
+ while (it < matcher.start()) {
+ if (NL.indexOf(content.charAt(it++)) != -1) ++numLines;
+ }
+
+ // Consumed too many lines. Fail.
+ if (numLines > MAX_ADDRESS_LINES) break;
+
+ // Consumed too many words. Fail.
+ if (++wordCount > MAX_ADDRESS_WORDS) break;
+
+ if (matchHouseNumber(content, it) != null) {
+ if (consecutiveHouseNumbers && numLines > 1) {
+ // Last line ended with a number, and this this line starts with one.
+ // Restart at this number.
+ return -it;
+ }
+ // Remember the position of this match as the restart position.
+ if (restartPos == -1) restartPos = it;
+ continue;
+ }
+
+ consecutiveHouseNumbers = false;
+
+ if (isValidLocationName(matcher.group(0))) {
+ foundLocationName = true;
+ continue;
+ }
+
+ if (wordCount == MAX_LOCATION_NAME_DISTANCE && !foundLocationName) {
+ // Didn't find a location name in time. Fail.
+ it = matcher.end();
+ break;
+ }
+
+ if (foundLocationName && wordCount > MIN_ADDRESS_WORDS) {
+ // We can now attempt to match a state.
+ MatchResult stateMatch = matchState(content, it);
+ if (stateMatch != null) {
+ if (lastWord.equals("et") && stateMatch.group(0).equals("al")) {
+ // Reject "et al" as a false postitive.
+ it = stateMatch.end();
+ break;
+ }
+
+ // At this point we've matched a state; try to match a zip code after it.
+ Matcher zipMatcher = sWordRe.matcher(content);
+ if (zipMatcher.find(stateMatch.end())
+ && isValidZipCode(zipMatcher.group(0), stateMatch)) {
+ return zipMatcher.end();
+ }
+ // The content ends with a state but no zip
+ // code. This is a legal match according to the
+ // documentation. N.B. This differs from the
+ // original c++ implementation, which only allowed
+ // the zip code to be optional at the end of the
+ // string, which presumably is a bug. Now we
+ // prefer to find a match with a zip code, but
+ // remember non-zip matches and return them if
+ // necessary.
+ nonZipMatch = stateMatch.end();
+ }
+ }
+ }
+
+ if (nonZipMatch > 0) return nonZipMatch;
+
+ return -(restartPos > 0 ? restartPos : it);
+ }
+
+ /**
+ * Return the first matching address in content.
+ *
+ * @param content The string to search.
+ * @return The first valid address, or null if no address was matched.
+ */
+ static String findAddress(String content) {
+ Matcher houseNumberMatcher = sHouseNumberRe.matcher(content);
+ int start = 0;
+ while (houseNumberMatcher.find(start)) {
+ if (checkHouseNumber(houseNumberMatcher.group(0))) {
+ start = houseNumberMatcher.start();
+ int end = attemptMatch(content, houseNumberMatcher);
+ if (end > 0) {
+ return content.substring(start, end);
+ }
+ start = -end;
+ } else {
+ start = houseNumberMatcher.end();
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 637b60e..244b6bd 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1797,9 +1797,10 @@
* @return the address, or if no address is found, null
*/
public static String findAddress(String addr) {
- // TODO: Rewrite this in Java so it is not needed to start up chromium
- // Could also be deprecated
- return getFactory().getStatics().findAddress(addr);
+ if (addr == null) {
+ throw new NullPointerException("addr is null");
+ }
+ return FindAddress.findAddress(addr);
}
/**
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 77cfc2fc..96d3baf 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -411,6 +411,9 @@
mContext.unbindService(mConnection);
mConnection.destroy();
}
+ if (mAfterCompute != null) {
+ mAfterCompute.afterCompute();
+ }
if (DEBUG) {
Log.d(TAG, "Unbinded Resolver Ranker.");
}
@@ -573,7 +576,6 @@
if (DEBUG) {
Log.d(TAG, "Has not found valid ResolverRankerService; Skip Prediction");
}
- return;
} else {
try {
mConnectSignal.await(CONNECTION_COST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index fce5dd5..685df0f 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -236,17 +236,15 @@
return INSTALL_SUCCEEDED;
}
- char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2];
+ char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 1];
if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
!= nativeLibPath.size()) {
ALOGD("Couldn't allocate local file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
- *(localTmpFileName + nativeLibPath.size()) = '/';
-
if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
- TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) {
+ TMP_FILE_PATTERN_LEN + 1) != TMP_FILE_PATTERN_LEN) {
ALOGI("Couldn't allocate temporary file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9072960..fdda55b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -159,6 +159,8 @@
<protected-broadcast
android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
@@ -173,6 +175,8 @@
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
@@ -559,6 +563,9 @@
<protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
<protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+ <!-- Added in P -->
+ <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 15fd34d..e18265b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1753,9 +1753,6 @@
<string-array name="config_twoDigitNumberPattern" translatable="false">
</string-array>
- <!-- The VoiceMail default value is displayed to my own number if it is true -->
- <bool name="config_telephony_use_own_number_for_voicemail">false</bool>
-
<!-- If this value is true, Sms encoded as octet is decoded by utf8 decoder.
If false, decoded by Latin decoder. -->
<bool name="config_sms_utf8_support">false</bool>
@@ -2560,6 +2557,13 @@
<bool name="config_sms_force_7bit_encoding">false</bool>
+ <!-- Number of physical SIM slots on the device. This includes both eSIM and pSIM slots, and
+ is not necessarily the same as the number of phones/logical modems supported by the device.
+ For example, a multi-sim device can have 2 phones/logical modems, but 3 physical slots,
+ or a single SIM device can have 1 phones/logical modems, but 2 physical slots (one eSIM
+ and one pSIM) -->
+ <integer name="config_num_physical_slots">1</integer>
+
<!--Thresholds for LTE dbm in status bar-->
<integer-array translatable="false" name="config_lteDbmThresholds">
<item>-140</item> <!-- SIGNAL_STRENGTH_NONE_OR_UNKNOWN -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1703ef0..f1070de 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -272,7 +272,6 @@
<java-symbol type="bool" name="config_suspendWhenScreenOffDueToProximity" />
<java-symbol type="bool" name="config_swipeDisambiguation" />
<java-symbol type="bool" name="config_syncstorageengine_masterSyncAutomatically" />
- <java-symbol type="bool" name="config_telephony_use_own_number_for_voicemail" />
<java-symbol type="bool" name="config_ui_enableFadingMarquee" />
<java-symbol type="bool" name="config_enableHapticTextHandle" />
<java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
@@ -446,6 +445,7 @@
<java-symbol type="integer" name="config_keepPreloadsMinDays" />
<java-symbol type="bool" name="config_hasPermanentDpad" />
<java-symbol type="bool" name="config_useDefaultFocusHighlight" />
+ <java-symbol type="integer" name="config_num_physical_slots" />
<java-symbol type="color" name="tab_indicator_text_v4" />
diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
new file mode 100644
index 0000000..1e3ddf3
--- /dev/null
+++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+package android.service.euicc;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.service.carrier.CarrierIdentifier;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.UiccAccessRule;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EuiccProfileInfoTest {
+ @Test
+ public void testWriteToParcel() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testWriteToParcelNullCarrierId() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testBuilderAndGetters() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertEquals("21430000000000006587", p.getIccid());
+ assertEquals("profile nickname", p.getNickname());
+ assertEquals("profile name", p.getProfileName());
+ assertEquals("service provider", p.getServiceProviderName());
+ assertEquals("325", p.getCarrierIdentifier().getMcc());
+ assertEquals("764", p.getCarrierIdentifier().getMnc());
+ assertEquals("123", p.getCarrierIdentifier().getGid1());
+ assertEquals("45", p.getCarrierIdentifier().getGid2());
+ assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, p.getState());
+ assertEquals(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, p.getProfileClass());
+ assertEquals(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, p.getPolicyRules());
+ assertTrue(p.hasPolicyRules());
+ assertTrue(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE));
+ assertFalse(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE));
+ assertArrayEquals(
+ new UiccAccessRule[] {new UiccAccessRule(new byte[0], null, 0)},
+ p.getUiccAccessRules());
+ }
+
+ @Test
+ public void testBuilder_BasedOnAnotherProfile() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build();
+
+ assertEquals(p, copied);
+ assertEquals(p.hashCode(), copied.hashCode());
+ }
+
+ @Test
+ public void testEqualsHashCode() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertTrue(p.equals(p));
+ assertFalse(p.equals(new Object()));
+
+ EuiccProfileInfo t = null;
+ assertFalse(p.equals(t));
+
+ t = new EuiccProfileInfo.Builder(p).setIccid("21").build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setNickname(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setProfileName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setServiceProviderName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setCarrierIdentifier(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setState(EuiccProfileInfo.PROFILE_STATE_DISABLED).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_TESTING).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setPolicyRules(0).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setUiccAccessRule(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilderBuild_NoIccid() {
+ new EuiccProfileInfo.Builder().build();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBuilderSetOperatorMccMnc_Illegal() {
+ new EuiccProfileInfo.Builder()
+ .setCarrierIdentifier(new CarrierIdentifier(new byte[] {1, 2, 3, 4}, null, null));
+ }
+
+ @Test
+ public void testCreatorNewArray() {
+ EuiccProfileInfo[] profiles = EuiccProfileInfo.CREATOR.newArray(123);
+ assertEquals(123, profiles.length);
+ }
+}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index c4c14c9e..1d14fa0 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -89,4 +89,7 @@
// initialization with {}.
},
},
+ sanitize: {
+ blacklist: "libandroidfw_blacklist.txt",
+ },
}
diff --git a/libs/androidfw/libandroidfw_blacklist.txt b/libs/androidfw/libandroidfw_blacklist.txt
new file mode 100644
index 0000000..dd17e4d
--- /dev/null
+++ b/libs/androidfw/libandroidfw_blacklist.txt
@@ -0,0 +1 @@
+src:*/ResourceTypes.cpp
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index d7695ef..5785b0c 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -30,13 +30,6 @@
"libandroid_runtime",
"libskia",
],
-
- arch: {
- arm: {
- // TODO: This is to work around b/24465209. Remove after root cause is fixed
- ldflags: ["-Wl,--hash-style=both"],
- },
- },
}
// The headers module is in frameworks/native/Android.bp.
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 8a4a774..6601451 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -488,8 +488,6 @@
<string name="bluetooth_show_devices_without_names">Show Bluetooth devices without names</string>
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
- <!-- Setting Checkbox title for enabling Bluetooth inband ringing -->
- <string name="bluetooth_enable_inband_ringing">Enable in-band ringing</string>
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
<string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
@@ -582,8 +580,6 @@
<string name="bluetooth_show_devices_without_names_summary">Bluetooth devices without names (MAC addresses only) will be displayed</string>
<!-- Summary of checkbox for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume_summary">Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control.</string>
- <!-- Summary of checkbox for enabling Bluetooth inband ringing -->
- <string name="bluetooth_enable_inband_ringing_summary">Allow ringtones on the phone to be played on Bluetooth headsets</string>
<!-- Title of checkbox setting that enables the terminal app. [CHAR LIMIT=32] -->
<string name="enable_terminal_title">Local terminal</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 7d7f9ae7..04be92e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1687,18 +1687,9 @@
}
private List<String> getSettingsNamesLocked(int settingsType, int userId) {
- boolean instantApp;
- if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
- instantApp = false;
- } else {
- ApplicationInfo ai = getCallingApplicationInfoOrThrow();
- instantApp = ai.isInstantApp();
- }
- if (instantApp) {
- return new ArrayList<String>(getInstantAppAccessibleSettings(settingsType));
- } else {
- return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
- }
+ // Don't enforce the instant app whitelist for now -- its too prone to unintended breakage
+ // in the current form.
+ return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
}
private void enforceSettingReadable(String settingName, int settingsType, int userId) {
@@ -1711,8 +1702,10 @@
}
if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)
&& !getOverlayInstantAppAccessibleSettings(settingsType).contains(settingName)) {
- throw new SecurityException("Setting " + settingName + " is not accessible from"
- + " ephemeral package " + getCallingPackage());
+ // Don't enforce the instant app whitelist for now -- its too prone to unintended
+ // breakage in the current form.
+ Slog.w(LOG_TAG, "Instant App " + ai.packageName
+ + " trying to access unexposed setting, this will be an error in the future.");
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5228498..f34730c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -130,6 +130,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
+import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
@@ -232,8 +233,6 @@
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
- private int mNumDnsEntries;
-
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
@@ -407,6 +406,7 @@
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
final private NetworkStateTrackerHandler mTrackerHandler;
+ private final DnsManager mDnsManager;
private boolean mSystemReady;
private Intent mInitialBroadcast;
@@ -857,6 +857,8 @@
mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
mMultinetworkPolicyTracker.start();
+
+ mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
}
private Tethering makeTethering() {
@@ -1803,24 +1805,6 @@
}
}
- private void flushVmDnsCache() {
- /*
- * Tell the VMs to toss their DNS caches
- */
- Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- /*
- * Connectivity events can happen before boot has completed ...
- */
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@Override
public int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = mSystemProperties.get(
@@ -4558,41 +4542,17 @@
return; // no updating necessary
}
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
+
Collection<InetAddress> dnses = newLp.getDnsServers();
if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
try {
- mNetd.setDnsConfigurationForNetwork(
- netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+ mDnsManager.setDnsConfigurationForNetwork(
+ netId, dnses, newLp.getDomains(), isDefaultNetwork);
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
- flushVmDnsCache();
- }
-
- private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
- int last = 0;
- for (InetAddress dns : dnses) {
- ++last;
- setNetDnsProperty(last, dns.getHostAddress());
- }
- for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- setNetDnsProperty(i, "");
- }
- mNumDnsEntries = last;
- }
-
- private void setNetDnsProperty(int which, String value) {
- final String key = "net.dns" + which;
- // Log and forget errors setting unsupported properties.
- try {
- mSystemProperties.set(key, value);
- } catch (Exception e) {
- Log.e(TAG, "Error setting unsupported net.dns property: ", e);
- }
}
private String getNetworkPermission(NetworkCapabilities nc) {
@@ -4865,7 +4825,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+ mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index d3ab125..02cfe3d 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.DUMP;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -51,6 +52,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -101,8 +103,14 @@
/* Binder context for this service */
private final Context mContext;
- /** Should be a never-repeating global ID for resources */
- private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0);
+ /**
+ * 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;
interface IpSecServiceConfiguration {
INetd getNetdInstance() throws RemoteException;
@@ -855,7 +863,7 @@
checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
String localAddress = "";
@@ -978,7 +986,7 @@
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
FileDescriptor sockFd = null;
try {
if (!userRecord.mSocketQuotaTracker.isAvailable()) {
@@ -1023,6 +1031,30 @@
releaseResource(userRecord.mEncapSocketRecords, resourceId);
}
+ @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(
+ 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");
+ }
+
/**
* Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
* IllegalArgumentException if they are not.
@@ -1072,17 +1104,7 @@
}
for (int direction : DIRECTIONS) {
- IpSecAlgorithm crypt = config.getEncryption(direction);
- IpSecAlgorithm auth = config.getAuthentication(direction);
- IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction);
- if (authenticatedEncryption == null && crypt == null && auth == null) {
- throw new IllegalArgumentException(
- "No Encryption or Authentication algorithms specified");
- } else if (authenticatedEncryption != null && (auth != null || crypt != null)) {
- throw new IllegalArgumentException(
- "Authenticated Encryption is mutually"
- + " exclusive with other Authentication or Encryption algorithms");
- }
+ validateAlgorithms(config, direction);
// Retrieve SPI record; will throw IllegalArgumentException if not found
userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction));
@@ -1101,7 +1123,7 @@
IpSecConfig c, IBinder binder) throws RemoteException {
checkIpSecConfig(c);
checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
@@ -1220,7 +1242,11 @@
info.getSpiRecord(direction).getSpi());
}
} catch (ServiceSpecificException e) {
- // FIXME: get the error code and throw is at an IOException from Errno Exception
+ if (e.errorCode == EINVAL) {
+ throw new IllegalArgumentException(e.toString());
+ } else {
+ throw e;
+ }
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8a15ded..40e6d26 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
@@ -209,12 +210,6 @@
public static final int StrictCleartext = 617;
}
- /* Defaults for resolver parameters. */
- public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
- public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
- public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
- public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
-
/**
* String indicating a softap command.
*/
@@ -1768,6 +1763,8 @@
@Override
public boolean setDataSaverModeEnabled(boolean enable) {
+ mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
+
if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
synchronized (mQuotaLock) {
if (mDataSaverMode == enable) {
@@ -1947,66 +1944,14 @@
}
@Override
- public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
+ public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains,
+ int[] params, boolean useTls, String tlsHostname) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final ContentResolver cr = mContext.getContentResolver();
-
- int sampleValidity = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- if (sampleValidity < 0 || sampleValidity > 65535) {
- Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
- }
-
- int successThreshold = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- if (successThreshold < 0 || successThreshold > 100) {
- Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
- }
-
- int minSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
- int maxSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
- if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
- Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
- "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
- DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
- minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
- maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
- }
-
- final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
- final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
- final boolean useTls = shouldUseTls(cr);
- // TODO: Populate tlsHostname once it's decided how the hostname's IP
- // addresses will be resolved:
- //
- // [1] network-provided DNS servers are included here with the
- // hostname and netd will use the network-provided servers to
- // resolve the hostname and fix up its internal structures, or
- //
- // [2] network-provided DNS servers are included here without the
- // hostname, the ConnectivityService layer resolves the given
- // hostname, and then reconfigures netd with this information.
- //
- // In practice, there will always be a need for ConnectivityService or
- // the captive portal app to use the network-provided services to make
- // some queries. This argues in favor of [1], in concert with another
- // mechanism, perhaps setting a high bit in the netid, to indicate
- // via existing DNS APIs which set of servers (network-provided or
- // non-network-provided private DNS) should be queried.
- final String tlsHostname = "";
final String[] tlsFingerprints = new String[0];
try {
- mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
- useTls, tlsHostname, tlsFingerprints);
+ mNetdService.setResolverConfiguration(
+ netId, servers, domains, params, useTls, tlsHostname, tlsFingerprints);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2fe8f2a..6a6b5ce 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2007,11 +2007,11 @@
getAccountRemovedReceivers(accountToRename, accounts);
accounts.accountsDb.beginTransaction();
Account renamedAccount = new Account(newName, accountToRename.type);
- if ((accounts.accountsDb.findCeAccountId(renamedAccount) >= 0)) {
- Log.e(TAG, "renameAccount failed - account with new name already exists");
- return null;
- }
try {
+ if ((accounts.accountsDb.findCeAccountId(renamedAccount) >= 0)) {
+ Log.e(TAG, "renameAccount failed - account with new name already exists");
+ return null;
+ }
final long accountId = accounts.accountsDb.findDeAccountId(accountToRename);
if (accountId >= 0) {
accounts.accountsDb.renameCeAccount(accountId, newName);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dce0c38..6cdf071 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -200,6 +200,7 @@
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManager.TaskThumbnailInfo;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerInternal.ScreenObserver;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
import android.app.ActivityThread;
@@ -1548,6 +1549,8 @@
}
}
+ final List<ScreenObserver> mScreenObservers = new ArrayList<>();
+
final RemoteCallbackList<IProcessObserver> mProcessObservers = new RemoteCallbackList<>();
ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
@@ -1689,6 +1692,8 @@
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
+ static final int DISPATCH_SCREEN_AWAKE_MSG = 71;
+ static final int DISPATCH_SCREEN_KEYGUARD_MSG = 72;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int NOTIFY_VR_KEYGUARD_MSG = 74;
@@ -2412,11 +2417,17 @@
}
}
} break;
- case NOTIFY_VR_SLEEPING_MSG: {
- notifyVrManagerOfSleepState(msg.arg1 != 0);
+ case DISPATCH_SCREEN_AWAKE_MSG: {
+ final boolean isAwake = msg.arg1 != 0;
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onAwakeStateChanged(isAwake);
+ }
} break;
- case NOTIFY_VR_KEYGUARD_MSG: {
- notifyVrManagerOfKeyguardState(msg.arg1 != 0);
+ case DISPATCH_SCREEN_KEYGUARD_MSG: {
+ final boolean isShowing = msg.arg1 != 0;
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onKeyguardStateChanged(isShowing);
+ }
} break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
synchronized (ActivityManagerService.this) {
@@ -3260,32 +3271,6 @@
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
- private void sendNotifyVrManagerOfSleepState(boolean isSleeping) {
- mHandler.sendMessage(
- mHandler.obtainMessage(NOTIFY_VR_SLEEPING_MSG, isSleeping ? 1 : 0, 0));
- }
-
- private void notifyVrManagerOfSleepState(boolean isSleeping) {
- final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
- if (vrService == null) {
- return;
- }
- vrService.onSleepStateChanged(isSleeping);
- }
-
- private void sendNotifyVrManagerOfKeyguardState(boolean isShowing) {
- mHandler.sendMessage(
- mHandler.obtainMessage(NOTIFY_VR_KEYGUARD_MSG, isShowing ? 1 : 0, 0));
- }
-
- private void notifyVrManagerOfKeyguardState(boolean isShowing) {
- final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
- if (vrService == null) {
- return;
- }
- vrService.onKeyguardStateChanged(isShowing);
- }
-
final void showAskCompatModeDialogLocked(ActivityRecord r) {
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
@@ -12497,7 +12482,8 @@
if (wasAwake != isAwake) {
// Also update state in a special way for running foreground services UI.
mServices.updateScreenStateLocked(isAwake);
- sendNotifyVrManagerOfSleepState(!isAwake);
+ mHandler.obtainMessage(DISPATCH_SCREEN_AWAKE_MSG, isAwake ? 1 : 0, 0)
+ .sendToTarget();
}
}
}
@@ -12650,7 +12636,9 @@
Binder.restoreCallingIdentity(ident);
}
}
- sendNotifyVrManagerOfKeyguardState(showing);
+
+ mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, showing ? 1 : 0, 0)
+ .sendToTarget();
}
@Override
@@ -24258,6 +24246,11 @@
}
}
}
+
+ @Override
+ public void registerScreenObserver(ScreenObserver observer) {
+ mScreenObservers.add(observer);
+ }
}
/**
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
new file mode 100644
index 0000000..a4170ce
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -0,0 +1,226 @@
+/*
+ * 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.server.connectivity;
+
+import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
+import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
+import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
+import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkUtils;
+import android.os.Binder;
+import android.os.INetworkManagementService;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.server.connectivity.MockableSystemProperties;
+
+import java.net.InetAddress;
+import java.util.Collection;
+
+
+/**
+ * Encapsulate the management of DNS settings for networks.
+ *
+ * This class it NOT designed for concurrent access. Furthermore, all non-static
+ * methods MUST be called from ConnectivityService's thread.
+ *
+ * @hide
+ */
+public class DnsManager {
+ private static final String TAG = DnsManager.class.getSimpleName();
+
+ /* Defaults for resolver parameters. */
+ private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
+ private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
+ private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
+ private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
+
+ private final Context mContext;
+ private final ContentResolver mContentResolver;
+ private final INetworkManagementService mNMS;
+ private final MockableSystemProperties mSystemProperties;
+
+ private int mNumDnsEntries;
+ private int mSampleValidity;
+ private int mSuccessThreshold;
+ private int mMinSamples;
+ private int mMaxSamples;
+ private String mPrivateDnsMode;
+ private String mPrivateDnsSpecifier;
+
+ public DnsManager(Context ctx, INetworkManagementService nms, MockableSystemProperties sp) {
+ mContext = ctx;
+ mContentResolver = mContext.getContentResolver();
+ mNMS = nms;
+ mSystemProperties = sp;
+
+ // TODO: Create and register ContentObservers to track every setting
+ // used herein, posting messages to respond to changes.
+ }
+
+ public boolean isPrivateDnsInStrictMode() {
+ return !TextUtils.isEmpty(mPrivateDnsMode) &&
+ mPrivateDnsMode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) &&
+ !TextUtils.isEmpty(mPrivateDnsSpecifier);
+ }
+
+ public void setDnsConfigurationForNetwork(
+ int netId, Collection<InetAddress> servers, String domains, boolean isDefaultNetwork) {
+ updateParametersSettings();
+ updatePrivateDnsSettings();
+
+ final String[] serverStrs = NetworkUtils.makeStrings(servers);
+ final String[] domainStrs = (domains == null) ? new String[0] : domains.split(" ");
+ final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+ final boolean useTls = shouldUseTls(mPrivateDnsMode);
+ // TODO: Populate tlsHostname once it's decided how the hostname's IP
+ // addresses will be resolved:
+ //
+ // [1] network-provided DNS servers are included here with the
+ // hostname and netd will use the network-provided servers to
+ // resolve the hostname and fix up its internal structures, or
+ //
+ // [2] network-provided DNS servers are included here without the
+ // hostname, the ConnectivityService layer resolves the given
+ // hostname, and then reconfigures netd with this information.
+ //
+ // In practice, there will always be a need for ConnectivityService or
+ // the captive portal app to use the network-provided services to make
+ // some queries. This argues in favor of [1], in concert with another
+ // mechanism, perhaps setting a high bit in the netid, to indicate
+ // via existing DNS APIs which set of servers (network-provided or
+ // non-network-provided private DNS) should be queried.
+ final String tlsHostname = "";
+ try {
+ mNMS.setDnsConfigurationForNetwork(
+ netId, serverStrs, domainStrs, params, useTls, tlsHostname);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting DNS configuration: " + e);
+ return;
+ }
+
+ // TODO: netd should listen on [::1]:53 and proxy queries to the current
+ // default network, and we should just set net.dns1 to ::1, not least
+ // because applications attempting to use net.dns resolvers will bypass
+ // the privacy protections of things like DNS-over-TLS.
+ if (isDefaultNetwork) setDefaultDnsSystemProperties(servers);
+ flushVmDnsCache();
+ }
+
+ public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
+ int last = 0;
+ for (InetAddress dns : dnses) {
+ ++last;
+ setNetDnsProperty(last, dns.getHostAddress());
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ setNetDnsProperty(i, "");
+ }
+ mNumDnsEntries = last;
+ }
+
+ private void flushVmDnsCache() {
+ /*
+ * Tell the VMs to toss their DNS caches
+ */
+ final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ /*
+ * Connectivity events can happen before boot has completed ...
+ */
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void updatePrivateDnsSettings() {
+ mPrivateDnsMode = getStringSetting(PRIVATE_DNS_MODE);
+ mPrivateDnsSpecifier = getStringSetting(PRIVATE_DNS_SPECIFIER);
+ }
+
+ private void updateParametersSettings() {
+ mSampleValidity = getIntSetting(
+ DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ if (mSampleValidity < 0 || mSampleValidity > 65535) {
+ Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
+ }
+
+ mSuccessThreshold = getIntSetting(
+ DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
+ Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
+ }
+
+ mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
+ mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
+ if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
+ Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
+ "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
+ DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
+ mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
+ mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
+ }
+ }
+
+ private String getStringSetting(String which) {
+ return Settings.Global.getString(mContentResolver, which);
+ }
+
+ private int getIntSetting(String which, int dflt) {
+ return Settings.Global.getInt(mContentResolver, which, dflt);
+ }
+
+ private void setNetDnsProperty(int which, String value) {
+ final String key = "net.dns" + which;
+ // Log and forget errors setting unsupported properties.
+ try {
+ mSystemProperties.set(key, value);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting unsupported net.dns property: ", e);
+ }
+ }
+
+ private static boolean shouldUseTls(String mode) {
+ if (TextUtils.isEmpty(mode)) {
+ mode = PRIVATE_DNS_DEFAULT_MODE;
+ }
+ return mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
+ mode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d1bab89..7b171b3 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -19,7 +19,6 @@
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -43,7 +42,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
@@ -53,9 +51,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -76,7 +72,6 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -85,8 +80,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -110,12 +103,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -193,8 +182,6 @@
private int mLastNotificationId;
private boolean mRndisEnabled; // track the RNDIS function enabled state
- private boolean mUsbTetherRequested; // true if USB tethering should be started
- // when RNDIS is enabled
// True iff. WiFi tethering should be started when soft AP is ready.
private boolean mWifiTetherRequested;
@@ -867,33 +854,18 @@
//
// For more explanation, see b/62552150 .
synchronized (Tethering.this.mPublicSync) {
- // Always record the state of RNDIS.
- // TODO: consider:
- // final boolean disconnected = !usbConnected;
- // if (disconnected) {
- // mRndisEnabled = false;
- // mUsbTetherRequested = false;
- // return;
- // }
- // final boolean configured = usbConnected && usbConfigured;
- // mRndisEnabled = configured ? rndisEnabled : false;
- // if (!configured) return;
- mRndisEnabled = rndisEnabled;
-
- if (usbConnected && !usbConfigured) {
- // Nothing to do here (only CONNECTED, not yet CONFIGURED).
- return;
- }
-
- // start tethering if we have a request pending
- if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
+ if (!usbConnected && mRndisEnabled) {
+ // Turn off tethering if it was enabled and there is a disconnect.
+ tetherMatchingInterfaces(
+ IControlsTethering.STATE_AVAILABLE,
+ ConnectivityManager.TETHERING_USB);
+ } else if (usbConfigured && rndisEnabled) {
+ // Tether if rndis is enabled and usb is configured.
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
}
-
- // TODO: Figure out how to remove the need for this variable.
- mUsbTetherRequested = false;
+ mRndisEnabled = usbConfigured && rndisEnabled;
}
}
@@ -1065,34 +1037,8 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
-
synchronized (mPublicSync) {
- if (enable) {
- if (mRndisEnabled) {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- } else {
- mUsbTetherRequested = true;
- usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
- }
- } else {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- if (mRndisEnabled) {
- usbManager.setCurrentFunction(null, false);
- }
- mUsbTetherRequested = false;
- }
+ usbManager.setCurrentFunction(enable ? UsbManager.USB_FUNCTION_RNDIS : null, false);
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
@@ -1149,7 +1095,7 @@
if (!mForwardedDownstreams.isEmpty()) return true;
synchronized (mPublicSync) {
- return mUsbTetherRequested || mWifiTetherRequested;
+ return mWifiTetherRequested;
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1f24121..3c2d724 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -306,6 +306,7 @@
} else {
for (Network underlying : underlyingNetworks) {
final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
+ if (underlyingCaps == null) continue;
for (int underlyingType : underlyingCaps.getTransportTypes()) {
transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 17adb1a..2224913 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -30,6 +30,7 @@
import android.net.ip.InterfaceController;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.net.util.InterfaceParams;
import android.net.util.NetdService;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
@@ -48,7 +49,6 @@
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
@@ -120,8 +120,7 @@
private int mLastError;
private int mServingMode;
private String mMyUpstreamIfaceName; // may change over time
- private NetworkInterface mNetworkInterface;
- private byte[] mHwAddr;
+ private InterfaceParams mInterfaceParams;
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
// properties are those selected by the IPv6TetheringCoordinator and relayed
// to us. By comparison, mLinkProperties contains the addresses and directly
@@ -247,31 +246,16 @@
}
private boolean startIPv6() {
- // TODO: Refactor for testability (perhaps passing an android.system.Os
- // instance and calling getifaddrs() directly).
- try {
- mNetworkInterface = NetworkInterface.getByName(mIfaceName);
- } catch (SocketException e) {
- mLog.e("Error looking up NetworkInterfaces: " + e);
- stopIPv6();
- return false;
- }
- if (mNetworkInterface == null) {
- mLog.e("Failed to find NetworkInterface");
+ // TODO: Refactor for better testability. This is one of the things
+ // that prohibits unittesting IPv6 tethering setup.
+ mInterfaceParams = InterfaceParams.getByName(mIfaceName);
+ if (mInterfaceParams == null) {
+ mLog.e("Failed to find InterfaceParams");
stopIPv6();
return false;
}
- try {
- mHwAddr = mNetworkInterface.getHardwareAddress();
- } catch (SocketException e) {
- mLog.e("Failed to find hardware address: " + e);
- stopIPv6();
- return false;
- }
-
- final int ifindex = mNetworkInterface.getIndex();
- mRaDaemon = new RouterAdvertisementDaemon(mIfaceName, ifindex, mHwAddr);
+ mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
if (!mRaDaemon.start()) {
stopIPv6();
return false;
@@ -281,8 +265,7 @@
}
private void stopIPv6() {
- mNetworkInterface = null;
- mHwAddr = null;
+ mInterfaceParams = null;
setRaParams(null);
if (mRaDaemon != null) {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 205e828..581e8c7 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -323,7 +323,7 @@
private final BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- EndPoint target = new EndPoint(null, null, context.getUserId());
+ EndPoint target = new EndPoint(null, null, getSendingUserId());
updateRunningAccounts(target /* sync targets for user */);
}
};
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 6c8c9b2..ffc4731 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -5,3 +5,4 @@
per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com
per-file DefaultPermissionGrantPolicy.java = toddke@google.com
per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
+per-file DefaultPermissionGrantPolicy.java = patb@google.com
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 853e1b2..3aca330 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -24,8 +24,6 @@
import android.app.ProgressDialog;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -34,8 +32,6 @@
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioAttributes;
-import android.nfc.INfcAdapter;
-import android.nfc.NfcAdapter;
import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
@@ -122,9 +118,7 @@
private static String METRIC_AM = "shutdown_activity_manager";
private static String METRIC_PM = "shutdown_package_manager";
private static String METRIC_RADIOS = "shutdown_radios";
- private static String METRIC_BT = "shutdown_bt";
private static String METRIC_RADIO = "shutdown_radio";
- private static String METRIC_NFC = "shutdown_nfc";
private static String METRIC_SM = "shutdown_storage_manager";
private final Object mActionDoneSync = new Object();
@@ -418,7 +412,7 @@
/**
* Makes sure we handle the shutdown gracefully.
- * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
+ * Shuts off power regardless of radio state if the allotted time has passed.
*/
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog();
@@ -630,42 +624,10 @@
Thread t = new Thread() {
public void run() {
TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
- boolean nfcOff;
- boolean bluetoothReadyForShutdown;
boolean radioOff;
- final INfcAdapter nfc =
- INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
- final IBluetoothManager bluetooth =
- IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
- BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
- try {
- nfcOff = nfc == null ||
- nfc.getState() == NfcAdapter.STATE_OFF;
- if (!nfcOff) {
- Log.w(TAG, "Turning off NFC...");
- metricStarted(METRIC_NFC);
- nfc.disable(false); // Don't persist new state
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during NFC shutdown", ex);
- nfcOff = true;
- }
-
- try {
- bluetoothReadyForShutdown = bluetooth == null ||
- bluetooth.getState() == BluetoothAdapter.STATE_OFF;
- if (!bluetoothReadyForShutdown) {
- Log.w(TAG, "Disabling Bluetooth...");
- metricStarted(METRIC_BT);
- bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
try {
radioOff = phone == null || !phone.needMobileRadioShutdown();
@@ -679,7 +641,7 @@
radioOff = true;
}
- Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
+ Log.i(TAG, "Waiting for Radio...");
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
@@ -690,25 +652,6 @@
sInstance.setRebootProgress(status, null);
}
- if (!bluetoothReadyForShutdown) {
- try {
- // BLE only mode can happen when BT is turned off
- // We will continue shutting down in such case
- bluetoothReadyForShutdown =
- bluetooth.getState() == BluetoothAdapter.STATE_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_ON;
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
- if (bluetoothReadyForShutdown) {
- Log.i(TAG, "Bluetooth turned off.");
- metricEnded(METRIC_BT);
- shutdownTimingsTraceLog
- .logDuration("ShutdownBt", TRON_METRICS.get(METRIC_BT));
- }
- }
if (!radioOff) {
try {
radioOff = !phone.needMobileRadioShutdown();
@@ -723,23 +666,9 @@
.logDuration("ShutdownRadio", TRON_METRICS.get(METRIC_RADIO));
}
}
- if (!nfcOff) {
- try {
- nfcOff = nfc.getState() == NfcAdapter.STATE_OFF;
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during NFC shutdown", ex);
- nfcOff = true;
- }
- if (nfcOff) {
- Log.i(TAG, "NFC turned off.");
- metricEnded(METRIC_NFC);
- shutdownTimingsTraceLog
- .logDuration("ShutdownNfc", TRON_METRICS.get(METRIC_NFC));
- }
- }
- if (radioOff && bluetoothReadyForShutdown && nfcOff) {
- Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
+ if (radioOff) {
+ Log.i(TAG, "Radio shutdown complete.");
done[0] = true;
break;
}
@@ -756,7 +685,7 @@
} catch (InterruptedException ex) {
}
if (!done[0]) {
- Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown.");
+ Log.w(TAG, "Timed out waiting for Radio shutdown.");
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 7b1e12e..35b6ad3 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -59,13 +59,6 @@
int userId, int processId, @NonNull ComponentName calling);
/**
- * Set whether the system has acquired a sleep token.
- *
- * @param isAsleep is {@code true} if the device is asleep, or {@code false} otherwise.
- */
- public abstract void onSleepStateChanged(boolean isAsleep);
-
- /**
* Set whether the display used for VR output is on.
*
* @param isScreenOn is {@code true} if the display is on and can receive commands,
@@ -74,13 +67,6 @@
public abstract void onScreenStateChanged(boolean isScreenOn);
/**
- * Set whether the keyguard is currently active/showing.
- *
- * @param isShowing is {@code true} if the keyguard is active/showing.
- */
- public abstract void onKeyguardStateChanged(boolean isShowing);
-
- /**
* Return NO_ERROR if the given package is installed on the device and enabled as a
* VrListenerService for the given current user, or a negative error code indicating a failure.
*
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index b0fd248..56cacf4 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerInternal.ScreenObserver;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.INotificationManager;
@@ -104,7 +105,8 @@
*
* @hide
*/
-public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
+public class VrManagerService extends SystemService
+ implements EnabledComponentChangeListener, ScreenObserver {
public static final String TAG = "VrManagerService";
static final boolean DBG = false;
@@ -231,15 +233,17 @@
}
}
- private void setSleepState(boolean isAsleep) {
- setSystemState(FLAG_AWAKE, !isAsleep);
- }
-
private void setScreenOn(boolean isScreenOn) {
setSystemState(FLAG_SCREEN_ON, isScreenOn);
}
- private void setKeyguardShowing(boolean isShowing) {
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+ setSystemState(FLAG_AWAKE, isAwake);
+ }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
}
@@ -675,21 +679,11 @@
}
@Override
- public void onSleepStateChanged(boolean isAsleep) {
- VrManagerService.this.setSleepState(isAsleep);
- }
-
- @Override
public void onScreenStateChanged(boolean isScreenOn) {
VrManagerService.this.setScreenOn(isScreenOn);
}
@Override
- public void onKeyguardStateChanged(boolean isShowing) {
- VrManagerService.this.setKeyguardShowing(isShowing);
- }
-
- @Override
public boolean isCurrentVrListener(String packageName, int userId) {
return VrManagerService.this.isCurrentVrListener(packageName, userId);
}
@@ -740,6 +734,9 @@
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ LocalServices.getService(ActivityManagerInternal.class)
+ .registerScreenObserver(this);
+
mNotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
synchronized (mLock) {
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 31a1abb..7d9736e 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -38,6 +38,7 @@
import android.net.metrics.ApfStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
@@ -56,7 +57,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
@@ -247,7 +247,7 @@
private final ApfCapabilities mApfCapabilities;
private final IpClient.Callback mIpClientCallback;
- private final NetworkInterface mNetworkInterface;
+ private final InterfaceParams mInterfaceParams;
private final IpConnectivityLog mMetricsLog;
@VisibleForTesting
@@ -269,11 +269,11 @@
private int mIPv4PrefixLength;
@VisibleForTesting
- ApfFilter(ApfConfiguration config, NetworkInterface networkInterface,
+ ApfFilter(ApfConfiguration config, InterfaceParams ifParams,
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
mApfCapabilities = config.apfCapabilities;
mIpClientCallback = ipClientCallback;
- mNetworkInterface = networkInterface;
+ mInterfaceParams = ifParams;
mMulticastFilter = config.multicastFilter;
mDrop802_3Frames = config.ieee802_3Filter;
@@ -287,7 +287,7 @@
}
private void log(String s) {
- Log.d(TAG, "(" + mNetworkInterface.getName() + "): " + s);
+ Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
}
@GuardedBy("this")
@@ -332,14 +332,14 @@
void maybeStartFilter() {
FileDescriptor socket;
try {
- mHardwareAddress = mNetworkInterface.getHardwareAddress();
+ mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
synchronized(this) {
// Install basic filters
installNewProgramLocked();
}
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
- mNetworkInterface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress(
+ (short) ETH_P_IPV6, mInterfaceParams.index);
Os.bind(socket, addr);
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
} catch(SocketException|ErrnoException e) {
@@ -1168,10 +1168,10 @@
* filtering using APF programs.
*/
public static ApfFilter maybeCreate(ApfConfiguration config,
- NetworkInterface networkInterface, IpClient.Callback ipClientCallback) {
- if (config == null) return null;
+ InterfaceParams ifParams, IpClient.Callback ipClientCallback) {
+ if (config == null || ifParams == null) return null;
ApfCapabilities apfCapabilities = config.apfCapabilities;
- if (apfCapabilities == null || networkInterface == null) return null;
+ if (apfCapabilities == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
@@ -1186,7 +1186,7 @@
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
- return new ApfFilter(config, networkInterface, ipClientCallback, new IpConnectivityLog());
+ return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog());
}
public synchronized void shutdown() {
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index ed78175..a956cef 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -34,6 +34,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
+import android.net.util.InterfaceParams;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -50,7 +51,6 @@
import java.io.IOException;
import java.lang.Thread;
import java.net.Inet4Address;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -187,7 +187,8 @@
private final String mIfaceName;
private boolean mRegisteredForPreDhcpNotification;
- private NetworkInterface mIface;
+ private InterfaceParams mIface;
+ // TODO: MacAddress-ify more of this class hierarchy.
private byte[] mHwAddr;
private PacketSocketAddress mInterfaceBroadcastAddr;
private int mTransactionId;
@@ -221,8 +222,9 @@
return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
}
+ // TODO: Take an InterfaceParams instance instead of an interface name String.
private DhcpClient(Context context, StateMachine controller, String iface) {
- super(TAG);
+ super(TAG, controller.getHandler());
mContext = context;
mController = controller;
@@ -262,23 +264,23 @@
}
public static DhcpClient makeDhcpClient(
- Context context, StateMachine controller, String intf) {
- DhcpClient client = new DhcpClient(context, controller, intf);
+ Context context, StateMachine controller, InterfaceParams ifParams) {
+ DhcpClient client = new DhcpClient(context, controller, ifParams.name);
+ client.mIface = ifParams;
client.start();
return client;
}
private boolean initInterface() {
- try {
- mIface = NetworkInterface.getByName(mIfaceName);
- mHwAddr = mIface.getHardwareAddress();
- mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(),
- DhcpPacket.ETHER_BROADCAST);
- return true;
- } catch(SocketException | NullPointerException e) {
- Log.e(TAG, "Can't determine ifindex or MAC address for " + mIfaceName, e);
+ if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName);
+ if (mIface == null) {
+ Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName);
return false;
}
+
+ mHwAddr = mIface.macAddr.toByteArray();
+ mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST);
+ return true;
}
private void startNewTransaction() {
@@ -293,7 +295,7 @@
private boolean initPacketSocket() {
try {
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index);
Os.bind(mPacketSock, addr);
NetworkUtils.attachDhcpFilter(mPacketSock);
} catch(SocketException|ErrnoException e) {
diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
index 6cf4fa9a..e6ddbbc 100644
--- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java
+++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
@@ -21,6 +21,7 @@
import android.net.NetworkUtils;
import android.net.util.PacketReader;
import android.net.util.ConnectivityPacketSummary;
+import android.net.util.InterfaceParams;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.Os;
@@ -35,7 +36,6 @@
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.io.IOException;
-import java.net.NetworkInterface;
import java.net.SocketException;
@@ -69,24 +69,12 @@
private boolean mRunning;
private String mDisplayName;
- public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
- final String ifname;
- final int ifindex;
- final byte[] hwaddr;
- final int mtu;
+ public ConnectivityPacketTracker(Handler h, InterfaceParams ifParams, LocalLog log) {
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
- try {
- ifname = netif.getName();
- ifindex = netif.getIndex();
- hwaddr = netif.getHardwareAddress();
- mtu = netif.getMTU();
- } catch (NullPointerException|SocketException e) {
- throw new IllegalArgumentException("bad network interface", e);
- }
-
- mTag = TAG + "." + ifname;
+ mTag = TAG + "." + ifParams.name;
mLog = log;
- mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
+ mPacketListener = new PacketListener(h, ifParams);
}
public void start(String displayName) {
@@ -102,13 +90,11 @@
}
private final class PacketListener extends PacketReader {
- private final int mIfIndex;
- private final byte mHwAddr[];
+ private final InterfaceParams mInterface;
- PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
- super(h, mtu);
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
+ PacketListener(Handler h, InterfaceParams ifParams) {
+ super(h, ifParams.defaultMtu);
+ mInterface = ifParams;
}
@Override
@@ -117,7 +103,7 @@
try {
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
- Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
+ Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index));
} catch (ErrnoException | IOException e) {
logError("Failed to create packet tracking socket: ", e);
closeFd(s);
@@ -129,7 +115,7 @@
@Override
protected void handlePacket(byte[] recvbuf, int length) {
final String summary = ConnectivityPacketSummary.summarize(
- mHwAddr, recvbuf, length);
+ mInterface.macAddr, recvbuf, length);
if (summary == null) return;
if (DBG) Log.d(mTag, summary);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index fdb366c..d3a97b3 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -35,6 +35,7 @@
import android.net.dhcp.DhcpClient;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.net.util.NetworkConstants;
@@ -63,7 +64,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
@@ -556,7 +556,7 @@
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private final InterfaceController mInterfaceCtrl;
- private NetworkInterface mNetworkInterface;
+ private InterfaceParams mInterfaceParams;
/**
* Non-final member variables accessed only from within our StateMachine.
@@ -722,7 +722,12 @@
return;
}
- getNetworkInterface();
+ mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
+ if (mInterfaceParams == null) {
+ logError("Failed to find InterfaceParams for " + mInterfaceName);
+ // TODO: call doImmediateProvisioningFailure() with an error code
+ // indicating something like "interface not ready".
+ }
mCallback.setNeighborDiscoveryOffload(true);
sendMessage(CMD_START, new ProvisioningConfiguration(req));
@@ -858,7 +863,7 @@
protected String getLogRecString(Message msg) {
final String logLine = String.format(
"%s/%d %d %d %s [%s]",
- mInterfaceName, mNetworkInterface == null ? -1 : mNetworkInterface.getIndex(),
+ mInterfaceName, (mInterfaceParams == null) ? -1 : mInterfaceParams.index,
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
@@ -889,15 +894,6 @@
mLog.log(msg);
}
- private void getNetworkInterface() {
- try {
- mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
- } catch (SocketException | NullPointerException e) {
- // TODO: throw new IllegalStateException.
- logError("Failed to get interface object: %s", e);
- }
- }
-
// This needs to be called with care to ensure that our LinkProperties
// are in sync with the actual LinkProperties of the interface. For example,
// we should only call this if we know for sure that there are no IP addresses
@@ -1218,7 +1214,7 @@
}
} else {
// Start DHCPv4.
- mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceName);
+ mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
mDhcpClient.registerForPreDhcpNotification();
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}
@@ -1245,7 +1241,7 @@
try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
- mInterfaceName,
+ mInterfaceParams,
getHandler(),
mLog,
new IpReachabilityMonitor.Callback() {
@@ -1447,7 +1443,7 @@
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
apfConfig.ethTypeBlackList =
mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
- mApfFilter = ApfFilter.maybeCreate(apfConfig, mNetworkInterface, mCallback);
+ mApfFilter = ApfFilter.maybeCreate(apfConfig, mInterfaceParams, mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1515,7 +1511,7 @@
private ConnectivityPacketTracker createPacketTracker() {
try {
return new ConnectivityPacketTracker(
- getHandler(), mNetworkInterface, mConnectivityPacketLog);
+ getHandler(), mInterfaceParams, mConnectivityPacketLog);
} catch (IllegalArgumentException e) {
return null;
}
diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java
index 6807334..fc07aa1 100644
--- a/services/net/java/android/net/ip/IpNeighborMonitor.java
+++ b/services/net/java/android/net/ip/IpNeighborMonitor.java
@@ -16,7 +16,11 @@
package android.net.ip;
-import android.net.netlink.NetlinkConstants;
+import static android.net.netlink.NetlinkConstants.hexify;
+import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
+
+import android.net.MacAddress;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.NetlinkSocket;
@@ -92,37 +96,35 @@
final int ifindex;
final InetAddress ip;
final short nudState;
- final byte[] linkLayerAddr;
+ final MacAddress macAddr;
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
- short nudState, byte[] linkLayerAddr) {
+ short nudState, MacAddress macAddr) {
this.elapsedMs = elapsedMs;
this.msgType = msgType;
this.ifindex = ifindex;
this.ip = ip;
this.nudState = nudState;
- this.linkLayerAddr = linkLayerAddr;
+ this.macAddr = macAddr;
}
boolean isConnected() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateConnected(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
}
boolean isValid() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateValid(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
}
@Override
public String toString() {
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
return j.add("@" + elapsedMs)
- .add(NetlinkConstants.stringForNlMsgType(msgType))
+ .add(stringForNlMsgType(msgType))
.add("if=" + ifindex)
.add(ip.getHostAddress())
.add(StructNdMsg.stringForNudState(nudState))
- .add("[" + NetlinkConstants.hexify(linkLayerAddr) + "]")
+ .add("[" + macAddr + "]")
.toString();
}
}
@@ -183,7 +185,7 @@
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
if (nlMsg == null || nlMsg.getHeader() == null) {
byteBuffer.position(position);
- mLog.e("unparsable netlink msg: " + NetlinkConstants.hexify(byteBuffer));
+ mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
break;
}
@@ -217,12 +219,13 @@
final int ifindex = ndMsg.ndm_ifindex;
final InetAddress destination = neighMsg.getDestination();
final short nudState =
- (msgType == NetlinkConstants.RTM_DELNEIGH)
+ (msgType == RTM_DELNEIGH)
? StructNdMsg.NUD_NONE
: ndMsg.ndm_state;
final NeighborEvent event = new NeighborEvent(
- whenMs, msgType, ifindex, destination, nudState, neighMsg.getLinkLayerAddress());
+ whenMs, msgType, ifindex, destination, nudState,
+ getMacAddress(neighMsg.getLinkLayerAddress()));
if (VDBG) {
Log.d(TAG, neighMsg.toString());
@@ -233,4 +236,16 @@
mConsumer.accept(event);
}
+
+ private static MacAddress getMacAddress(byte[] linkLayerAddress) {
+ if (linkLayerAddress != null) {
+ try {
+ return MacAddress.fromBytes(linkLayerAddress);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed to parse link-layer address: " + hexify(linkLayerAddress));
+ }
+ }
+
+ return null;
+ }
}
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index b31ffbb..7e02a28 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -26,6 +26,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
import android.net.netlink.StructNdMsg;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -46,9 +47,7 @@
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
import java.net.SocketAddress;
-import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -168,8 +167,7 @@
}
}
- private final String mInterfaceName;
- private final int mInterfaceIndex;
+ private final InterfaceParams mInterfaceParams;
private final IpNeighborMonitor mIpNeighborMonitor;
private final SharedLog mLog;
private final Callback mCallback;
@@ -182,30 +180,25 @@
private volatile long mLastProbeTimeMs;
public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback) {
- this(context, ifName, h, log, callback, null);
- }
-
- public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback,
+ Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker) {
- this(ifName, getInterfaceIndex(ifName), h, log, callback, tracker,
- Dependencies.makeDefault(context, ifName));
+ this(ifParams, h, log, callback, tracker, Dependencies.makeDefault(context, ifParams.name));
}
@VisibleForTesting
- IpReachabilityMonitor(String ifName, int ifIndex, Handler h, SharedLog log, Callback callback,
+ IpReachabilityMonitor(InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker, Dependencies dependencies) {
- mInterfaceName = ifName;
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
+
+ mInterfaceParams = ifParams;
mLog = log.forSubComponent(TAG);
mCallback = callback;
mMultinetworkPolicyTracker = tracker;
- mInterfaceIndex = ifIndex;
mDependencies = dependencies;
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
(NeighborEvent event) -> {
- if (mInterfaceIndex != event.ifindex) return;
+ if (mInterfaceParams.index != event.ifindex) return;
if (!mNeighborWatchList.containsKey(event.ip)) return;
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
@@ -241,7 +234,7 @@
private String describeWatchList(String sep) {
final StringBuilder sb = new StringBuilder();
- sb.append("iface{" + mInterfaceName + "/" + mInterfaceIndex + "}," + sep);
+ sb.append("iface{" + mInterfaceParams + "}," + sep);
sb.append("ntable=[" + sep);
String delimiter = "";
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
@@ -262,10 +255,10 @@
}
public void updateLinkProperties(LinkProperties lp) {
- if (!mInterfaceName.equals(lp.getInterfaceName())) {
+ if (!mInterfaceParams.name.equals(lp.getInterfaceName())) {
// TODO: figure out whether / how to cope with interface changes.
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
- "' does not match: " + mInterfaceName);
+ "' does not match: " + mInterfaceParams.name);
return;
}
@@ -353,10 +346,10 @@
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
}
- for (InetAddress target : ipProbeList) {
- final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceIndex, target);
+ for (InetAddress ip : ipProbeList) {
+ final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceParams.index, ip);
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
- target.getHostAddress(), rval));
+ ip.getHostAddress(), rval));
logEvent(IpReachabilityEvent.PROBE, rval);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
@@ -378,22 +371,9 @@
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
}
- private static int getInterfaceIndex(String ifname) {
- final NetworkInterface iface;
- try {
- iface = NetworkInterface.getByName(ifname);
- } catch (SocketException e) {
- throw new IllegalArgumentException("invalid interface '" + ifname + "': ", e);
- }
- if (iface == null) {
- throw new IllegalArgumentException("NetworkInterface was null for " + ifname);
- }
- return iface.getIndex();
- }
-
private void logEvent(int probeType, int errorCode) {
int eventType = probeType | (errorCode & 0xff);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
private void logNudFailed(ProvisioningChange delta) {
@@ -401,6 +381,6 @@
boolean isFromProbe = (duration < getProbeWakeLockDuration());
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
int eventType = IpReachabilityEvent.nudFailureEventType(isFromProbe, isProvisioningLost);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
}
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index cb3123c..49a1e79 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -25,6 +25,7 @@
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.TrafficStats;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructGroupReq;
@@ -96,9 +97,7 @@
(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
- private final String mIfName;
- private final int mIfIndex;
- private final byte[] mHwAddr;
+ private final InterfaceParams mInterface;
private final InetSocketAddress mAllNodes;
// This lock is to protect the RA from being updated while being
@@ -223,11 +222,9 @@
}
- public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) {
- mIfName = ifname;
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
- mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
+ public RouterAdvertisementDaemon(InterfaceParams ifParams) {
+ mInterface = ifParams;
+ mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
}
@@ -279,7 +276,7 @@
try {
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
- putSlla(ra, mHwAddr);
+ putSlla(ra, mInterface.macAddr.toByteArray());
mRaLength = ra.position();
// https://tools.ietf.org/html/rfc5175#section-4 says:
@@ -579,9 +576,9 @@
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
- Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName);
+ Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
NetworkUtils.protectFromVpn(mSocket);
- NetworkUtils.setupRaSocket(mSocket, mIfIndex);
+ NetworkUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -614,7 +611,7 @@
final InetAddress destip = dest.getAddress();
return (destip instanceof Inet6Address) &&
destip.isLinkLocalAddress() &&
- (((Inet6Address) destip).getScopeId() == mIfIndex);
+ (((Inet6Address) destip).getScopeId() == mInterface.index);
}
private void maybeSendRA(InetSocketAddress dest) {
diff --git a/services/net/java/android/net/util/ConnectivityPacketSummary.java b/services/net/java/android/net/util/ConnectivityPacketSummary.java
index dae93af..4951400 100644
--- a/services/net/java/android/net/util/ConnectivityPacketSummary.java
+++ b/services/net/java/android/net/util/ConnectivityPacketSummary.java
@@ -17,6 +17,7 @@
package android.net.util;
import android.net.dhcp.DhcpPacket;
+import android.net.MacAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -45,21 +46,20 @@
private final ByteBuffer mPacket;
private final String mSummary;
- public static String summarize(byte[] hwaddr, byte[] buffer) {
+ public static String summarize(MacAddress hwaddr, byte[] buffer) {
return summarize(hwaddr, buffer, buffer.length);
}
// Methods called herein perform some but by no means all error checking.
// They may throw runtime exceptions on malformed packets.
- public static String summarize(byte[] hwaddr, byte[] buffer, int length) {
- if ((hwaddr == null) || (hwaddr.length != ETHER_ADDR_LEN)) return null;
- if (buffer == null) return null;
+ public static String summarize(MacAddress macAddr, byte[] buffer, int length) {
+ if ((macAddr == null) || (buffer == null)) return null;
length = Math.min(length, buffer.length);
- return (new ConnectivityPacketSummary(hwaddr, buffer, length)).toString();
+ return (new ConnectivityPacketSummary(macAddr, buffer, length)).toString();
}
- private ConnectivityPacketSummary(byte[] hwaddr, byte[] buffer, int length) {
- mHwAddr = hwaddr;
+ private ConnectivityPacketSummary(MacAddress macAddr, byte[] buffer, int length) {
+ mHwAddr = macAddr.toByteArray();
mBytes = buffer;
mLength = Math.min(length, mBytes.length);
mPacket = ByteBuffer.wrap(mBytes, 0, mLength);
diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java
new file mode 100644
index 0000000..a4b2fbb
--- /dev/null
+++ b/services/net/java/android/net/util/InterfaceParams.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+package android.net.util;
+
+import static android.net.MacAddress.ALL_ZEROS_ADDRESS;
+import static android.net.util.NetworkConstants.ETHER_MTU;
+import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.net.MacAddress;
+import android.text.TextUtils;
+
+import java.net.NetworkInterface;
+import java.net.SocketException;
+
+
+/**
+ * Encapsulate the interface parameters common to IpClient/IpServer components.
+ *
+ * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
+ * and IpServer (sub)components need most or all of this information at some
+ * point during their lifecycles, so pass only this simplified object around
+ * which can be created once when IpClient/IpServer are told to start.
+ *
+ * @hide
+ */
+public class InterfaceParams {
+ public final String name;
+ public final int index;
+ public final MacAddress macAddr;
+ public final int defaultMtu;
+
+ public static InterfaceParams getByName(String name) {
+ final NetworkInterface netif = getNetworkInterfaceByName(name);
+ if (netif == null) return null;
+
+ // Not all interfaces have MAC addresses, e.g. rmnet_data0.
+ final MacAddress macAddr = getMacAddress(netif);
+
+ try {
+ return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
+ } catch (IllegalArgumentException|SocketException e) {
+ return null;
+ }
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr) {
+ this(name, index, macAddr, ETHER_MTU);
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
+ checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
+ checkArgument((index > 0), "invalid interface index");
+ this.name = name;
+ this.index = index;
+ this.macAddr = (macAddr != null) ? macAddr : ALL_ZEROS_ADDRESS;
+ this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
+ }
+
+ private static NetworkInterface getNetworkInterfaceByName(String name) {
+ try {
+ return NetworkInterface.getByName(name);
+ } catch (NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+
+ private static MacAddress getMacAddress(NetworkInterface netif) {
+ try {
+ return MacAddress.fromBytes(netif.getHardwareAddress());
+ } catch (IllegalArgumentException|NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c668100..1b057f9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -434,6 +434,8 @@
try {
// Restore default functions.
+ mCurrentOemFunctions = SystemProperties.get(UsbDeviceManager.getPersistProp(false),
+ UsbManager.USB_FUNCTION_NONE);
if (isNormalBoot()) {
mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
@@ -662,8 +664,7 @@
}
if ((!functions.equals(oemFunctions) &&
- (mCurrentOemFunctions == null ||
- !mCurrentOemFunctions.equals(oemFunctions)))
+ !mCurrentOemFunctions.equals(oemFunctions))
|| !mCurrentFunctions.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 4fd602f..e37aeb4 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -145,6 +145,8 @@
private static final String SESSION_STOP_RTT = "CS.-RTT";
private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
private static final String SESSION_HANDOVER_FAILED = "CS.haF";
+ private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
+ private static final String SESSION_CONNECTION_SERVICE_FOCUS_GAINED = "CS.cSFG";
private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
private static final int MSG_CREATE_CONNECTION = 2;
@@ -174,6 +176,8 @@
private static final int MSG_ON_STOP_RTT = 27;
private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
private static final int MSG_CREATE_CONNECTION_COMPLETE = 29;
+ private static final int MSG_CONNECTION_SERVICE_FOCUS_LOST = 30;
+ private static final int MSG_CONNECTION_SERVICE_FOCUS_GAINED = 31;
private static final int MSG_HANDOVER_FAILED = 32;
private static Connection sNullConnection;
@@ -610,6 +614,26 @@
Log.endSession();
}
}
+
+ @Override
+ public void connectionServiceFocusLost(Session.Info sessionInfo) throws RemoteException {
+ Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_LOST);
+ try {
+ mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_LOST).sendToTarget();
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
+ public void connectionServiceFocusGained(Session.Info sessionInfo) throws RemoteException {
+ Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_GAINED);
+ try {
+ mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_GAINED).sendToTarget();
+ } finally {
+ Log.endSession();
+ }
+ }
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -1061,6 +1085,12 @@
}
break;
}
+ case MSG_CONNECTION_SERVICE_FOCUS_GAINED:
+ onConnectionServiceFocusGained();
+ break;
+ case MSG_CONNECTION_SERVICE_FOCUS_LOST:
+ onConnectionServiceFocusLost();
+ break;
default:
break;
}
@@ -1930,6 +1960,16 @@
}
/**
+ * Call to inform Telecom that your {@link ConnectionService} has released call resources (e.g
+ * microphone, camera).
+ *
+ * @see ConnectionService#onConnectionServiceFocusLost()
+ */
+ public final void connectionServiceFocusReleased() {
+ mAdapter.onConnectionServiceFocusReleased();
+ }
+
+ /**
* Adds a connection created by the {@link ConnectionService} and informs telecom of the new
* connection.
*
@@ -2179,6 +2219,20 @@
public void onRemoteExistingConnectionAdded(RemoteConnection connection) {}
/**
+ * Called when the {@link ConnectionService} has lost the call focus.
+ * The {@link ConnectionService} should release the call resources and invokes
+ * {@link ConnectionService#connectionServiceFocusReleased()} to inform telecom that it has
+ * released the call resources.
+ */
+ public void onConnectionServiceFocusLost() {}
+
+ /**
+ * Called when the {@link ConnectionService} has gained the call focus. The
+ * {@link ConnectionService} can acquire the call resources at this time.
+ */
+ public void onConnectionServiceFocusGained() {}
+
+ /**
* @hide
*/
public boolean containsConference(Conference conference) {
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 92a9dc2..0d319bb 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -628,4 +628,17 @@
}
}
}
+
+ /**
+ * Notifies Telecom that the {@link ConnectionService} has released the call resource.
+ */
+ void onConnectionServiceFocusReleased() {
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ Log.d(this, "onConnectionServiceFocusReleased");
+ adapter.onConnectionServiceFocusReleased(Log.getExternalSession());
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 3fbdeb1..3e1bf77 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -73,6 +73,7 @@
private static final int MSG_ON_RTT_REMOTELY_TERMINATED = 32;
private static final int MSG_ON_RTT_UPGRADE_REQUEST = 33;
private static final int MSG_SET_PHONE_ACCOUNT_CHANGED = 34;
+ private static final int MSG_CONNECTION_SERVICE_FOCUS_RELEASED = 35;
private final IConnectionServiceAdapter mDelegate;
@@ -329,6 +330,9 @@
}
break;
}
+ case MSG_CONNECTION_SERVICE_FOCUS_RELEASED:
+ mDelegate.onConnectionServiceFocusReleased(null /*Session.Info*/);
+ break;
}
}
};
@@ -601,6 +605,11 @@
args.arg2 = pHandle;
mHandler.obtainMessage(MSG_SET_PHONE_ACCOUNT_CHANGED, args).sendToTarget();
}
+
+ @Override
+ public void onConnectionServiceFocusReleased(Session.Info sessionInfo) {
+ mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_RELEASED).sendToTarget();
+ }
};
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 3361b5b..83ca470 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -340,24 +340,6 @@
return sSessionManager;
}
- private static MessageDigest sMessageDigest;
-
- public static void initMd5Sum() {
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... args) {
- MessageDigest md;
- try {
- md = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- md = null;
- }
- sMessageDigest = md;
- return null;
- }
- }.execute();
- }
-
public static void setTag(String tag) {
TAG = tag;
DEBUG = isLoggable(android.util.Log.DEBUG);
@@ -425,44 +407,13 @@
/**
* Redact personally identifiable information for production users.
* If we are running in verbose mode, return the original string,
- * and return "****" if we are running on the user build, otherwise
- * return a SHA-1 hash of the input string.
+ * and return "***" otherwise.
*/
public static String pii(Object pii) {
if (pii == null || VERBOSE) {
return String.valueOf(pii);
}
- return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
- }
-
- private static String secureHash(byte[] input) {
- // Refrain from logging user personal information in user build.
- if (USER_BUILD) {
- return "****";
- }
-
- if (sMessageDigest != null) {
- sMessageDigest.reset();
- sMessageDigest.update(input);
- byte[] result = sMessageDigest.digest();
- return encodeHex(result);
- } else {
- return "Uninitialized SHA1";
- }
- }
-
- private static String encodeHex(byte[] bytes) {
- StringBuffer hex = new StringBuffer(bytes.length * 2);
-
- for (int i = 0; i < bytes.length; i++) {
- int byteIntValue = bytes[i] & 0xff;
- if (byteIntValue < 0x10) {
- hex.append("0");
- }
- hex.append(Integer.toString(byteIntValue, 16));
- }
-
- return hex.toString();
+ return "***";
}
private static String getPrefixFromObject(Object obj) {
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 85906ad..59ce590 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -213,6 +213,9 @@
}
@Override
+ public void onConnectionServiceFocusReleased(Session.Info sessionInfo) {}
+
+ @Override
public void addConferenceCall(
final String callId, ParcelableConference parcel, Session.Info sessionInfo) {
RemoteConference conference = new RemoteConference(callId,
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e124750..a9bbd24 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -645,7 +645,6 @@
mContext = context;
}
mTelecomServiceOverride = telecomServiceImpl;
- android.telecom.Log.initMd5Sum();
}
/**
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 732d00d..02e1ff8 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -103,4 +103,8 @@
void handoverFailed(String callId, in ConnectionRequest request,
int error, in Session.Info sessionInfo);
+
+ void connectionServiceFocusLost(in Session.Info sessionInfo);
+
+ void connectionServiceFocusGained(in Session.Info sessionInfo);
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index da2015f..be474bd 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -119,4 +119,6 @@
void onPhoneAccountChanged(String callId, in PhoneAccountHandle pHandle,
in Session.Info sessionInfo);
+
+ void onConnectionServiceFocusReleased(in Session.Info sessionInfo);
}
diff --git a/telephony/java/android/telephony/RadioNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
similarity index 95%
rename from telephony/java/android/telephony/RadioNetworkConstants.java
rename to telephony/java/android/telephony/AccessNetworkConstants.java
index 5f5dd82..fc814be 100644
--- a/telephony/java/android/telephony/RadioNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -17,23 +17,23 @@
package android.telephony;
/**
- * Contains radio access network related constants.
+ * Contains access network related constants.
*/
-public final class RadioNetworkConstants {
+public final class AccessNetworkConstants {
- public static final class RadioAccessNetworks {
+ public static final class AccessNetworkType {
public static final int GERAN = 1;
public static final int UTRAN = 2;
public static final int EUTRAN = 3;
- /** @hide */
public static final int CDMA2000 = 4;
+ public static final int IWLAN = 5;
}
/**
* Frenquency bands for GERAN.
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
- public static final class GeranBands {
+ public static final class GeranBand {
public static final int BAND_T380 = 1;
public static final int BAND_T410 = 2;
public static final int BAND_450 = 3;
@@ -54,7 +54,7 @@
* Frenquency bands for UTRAN.
* http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
*/
- public static final class UtranBands {
+ public static final class UtranBand {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
@@ -83,7 +83,7 @@
* Frenquency bands for EUTRAN.
* http://www.etsi.org/deliver/etsi_ts/136100_136199/136101/14.03.00_60/ts_136101v140p.pdf
*/
- public static final class EutranBands {
+ public static final class EutranBand {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 514222d..d0fb982 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -352,6 +352,17 @@
public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
/**
+ * Flag that specifies to use the user's own phone number as the voicemail number when there is
+ * no pre-loaded voicemail number on the SIM card.
+ * <p>
+ * {@link #KEY_DEFAULT_VM_NUMBER_STRING} takes precedence over this flag.
+ * <p>
+ * If false, the system default (*86) will be used instead.
+ */
+ public static final String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL =
+ "config_telephony_use_own_number_for_voicemail_bool";
+
+ /**
* When {@code true}, changes to the mobile data enabled switch will not cause the VT
* registration state to change. That is, turning on or off mobile data will not cause VT to be
* enabled or disabled.
@@ -995,6 +1006,13 @@
public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL =
"always_show_data_rat_icon_bool";
+ /**
+ * Boolean to decide whether to show precise call failed cause to user
+ * @hide
+ */
+ public static final String KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL =
+ "show_precise_failed_cause_bool";
+
// These variables are used by the MMS service and exposed through another API, {@link
// SmsManager}. The variable names and string values are copied from there.
public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -1737,6 +1755,7 @@
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
+ sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
@@ -2000,6 +2019,7 @@
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_IDENTIFY_HIGH_DEFINITION_CALLS_IN_CALL_LOG_BOOL, false);
+ sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
diff --git a/telephony/java/android/telephony/CellIdentity.aidl b/telephony/java/android/telephony/CellIdentity.aidl
new file mode 100644
index 0000000..aeee769
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentity.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentity;
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
new file mode 100644
index 0000000..e092d52
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -0,0 +1,173 @@
+/*
+ * 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;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * CellIdentity represents the identity of a unique cell. This is the base class for
+ * CellIdentityXxx which represents cell identity for specific network access technology.
+ */
+public abstract class CellIdentity implements Parcelable {
+ /**
+ * Cell identity type
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+ public @interface Type {}
+
+ /**
+ * Unknown cell identity type
+ * @hide
+ */
+ public static final int TYPE_UNKNOWN = 0;
+ /**
+ * GSM cell identity type
+ * @hide
+ */
+ public static final int TYPE_GSM = 1;
+ /**
+ * CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_CDMA = 2;
+ /**
+ * LTE cell identity type
+ * @hide
+ */
+ public static final int TYPE_LTE = 3;
+ /**
+ * WCDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_WCDMA = 4;
+ /**
+ * TDS-CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_TDSCDMA = 5;
+
+ // Log tag
+ /** @hide */
+ protected final String mTag;
+ // Cell identity type
+ /** @hide */
+ protected final int mType;
+ // 3-digit Mobile Country Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMccStr;
+ // 2 or 3-digit Mobile Network Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMncStr;
+
+ /** @hide */
+ protected CellIdentity(String tag, int type, String mcc, String mnc) {
+ mTag = tag;
+ mType = type;
+
+ // Only allow INT_MAX if unknown string mcc/mnc
+ if (mcc == null || mcc.matches("^[0-9]{3}$")) {
+ mMccStr = mcc;
+ } else if (mcc.isEmpty() || mcc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mccStr is empty or unknown, set it as null.
+ mMccStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mcc);
+ }
+
+ if (mnc == null || mnc.matches("^[0-9]{2,3}$")) {
+ mMncStr = mnc;
+ } else if (mnc.isEmpty() || mnc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mncStr is empty or unknown, set it as null.
+ mMncStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mnc);
+ }
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * @hide
+ * @return The type of the cell identity
+ */
+ public @Type int getType() { return mType; }
+
+ /**
+ * Used by child classes for parceling.
+ *
+ * @hide
+ */
+ @CallSuper
+ public void writeToParcel(Parcel dest, int type) {
+ dest.writeInt(type);
+ dest.writeString(mMccStr);
+ dest.writeString(mMncStr);
+ }
+
+ /**
+ * Construct from Parcel
+ * @hide
+ */
+ protected CellIdentity(String tag, int type, Parcel source) {
+ this(tag, type, source.readString(), source.readString());
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<CellIdentity> CREATOR =
+ new Creator<CellIdentity>() {
+ @Override
+ public CellIdentity createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+ case TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
+ case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+ case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+ case TYPE_TDSCDMA: return CellIdentityTdscdma.createFromParcelBody(in);
+ default: throw new IllegalArgumentException("Bad Cell identity Parcel");
+ }
+ }
+
+ @Override
+ public CellIdentity[] newArray(int size) {
+ return new CellIdentity[size];
+ }
+ };
+
+ /** @hide */
+ protected void log(String s) {
+ Rlog.w(mTag, s);
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CellIdentityCdma.aidl b/telephony/java/android/telephony/CellIdentityCdma.aidl
new file mode 100644
index 0000000..b31ad0b
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityCdma.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityCdma;
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index ddc938e..2e1d1dc 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique CDMA cell
*/
-public final class CellIdentityCdma implements Parcelable {
-
- private static final String LOG_TAG = "CellSignalStrengthCdma";
+public final class CellIdentityCdma extends CellIdentity {
+ private static final String TAG = CellIdentityCdma.class.getSimpleName();
private static final boolean DBG = false;
// Network Id 0..65535
@@ -60,6 +57,7 @@
* @hide
*/
public CellIdentityCdma() {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = Integer.MAX_VALUE;
mSystemId = Integer.MAX_VALUE;
mBasestationId = Integer.MAX_VALUE;
@@ -81,7 +79,7 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat) {
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
this(nid, sid, bid, lon, lat, null, null);
}
@@ -99,8 +97,9 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat, String alphal,
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
String alphas) {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = nid;
mSystemId = sid;
mBasestationId = bid;
@@ -196,40 +195,33 @@
CellIdentityCdma o = (CellIdentityCdma) other;
- return mNetworkId == o.mNetworkId &&
- mSystemId == o.mSystemId &&
- mBasestationId == o.mBasestationId &&
- mLatitude == o.mLatitude &&
- mLongitude == o.mLongitude &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mNetworkId == o.mNetworkId
+ && mSystemId == o.mSystemId
+ && mBasestationId == o.mBasestationId
+ && mLatitude == o.mLatitude
+ && mLongitude == o.mLongitude
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityCdma:{");
- sb.append(" mNetworkId="); sb.append(mNetworkId);
- sb.append(" mSystemId="); sb.append(mSystemId);
- sb.append(" mBasestationId="); sb.append(mBasestationId);
- sb.append(" mLongitude="); sb.append(mLongitude);
- sb.append(" mLatitude="); sb.append(mLatitude);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mNetworkId=").append(mNetworkId)
+ .append(" mSystemId=").append(mSystemId)
+ .append(" mBasestationId=").append(mBasestationId)
+ .append(" mLongitude=").append(mLongitude)
+ .append(" mLatitude=").append(mLatitude)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_CDMA);
dest.writeInt(mNetworkId);
dest.writeInt(mSystemId);
dest.writeInt(mBasestationId);
@@ -241,10 +233,16 @@
/** Construct from Parcel, type has already been processed */
private CellIdentityCdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readInt(),
- in.readString(), in.readString());
+ super(TAG, TYPE_CDMA, in);
+ mNetworkId = in.readInt();
+ mSystemId = in.readInt();
+ mBasestationId = in.readInt();
+ mLongitude = in.readInt();
+ mLatitude = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityCdma(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -253,7 +251,8 @@
new Creator<CellIdentityCdma>() {
@Override
public CellIdentityCdma createFromParcel(Parcel in) {
- return new CellIdentityCdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -262,10 +261,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityCdma createFromParcelBody(Parcel in) {
+ return new CellIdentityCdma(in);
}
}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.aidl b/telephony/java/android/telephony/CellIdentityGsm.aidl
new file mode 100644
index 0000000..bcc0751
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityGsm.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityGsm;
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 376e6aa..f948f81 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique GSM cell
*/
-public final class CellIdentityGsm implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityGsm";
+public final class CellIdentityGsm extends CellIdentity {
+ private static final String TAG = CellIdentityGsm.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mArfcn;
// 6-bit Base Station Identity Code
private final int mBsic;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityGsm() {
+ super(TAG, TYPE_GSM, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mArfcn = Integer.MAX_VALUE;
mBsic = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -70,7 +62,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid) {
this(lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE,
String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -86,7 +78,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
this(lac, cid, arfcn, bsic, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -103,8 +95,9 @@
*
* @hide
*/
- public CellIdentityGsm (int lac, int cid, int arfcn, int bsic, String mccStr,
+ public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_GSM, mccStr, mncStr);
mLac = lac;
mCid = cid;
mArfcn = arfcn;
@@ -112,31 +105,6 @@
// for inbound parcels
mBsic = (bsic == 0xFF) ? Integer.MAX_VALUE : bsic;
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -237,6 +205,7 @@
/**
+ * @deprecated Primary Scrambling Code is not applicable to GSM.
* @return Integer.MAX_VALUE, undefined for GSM
*/
@Deprecated
@@ -260,58 +229,54 @@
}
CellIdentityGsm o = (CellIdentityGsm) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mArfcn == o.mArfcn &&
- mBsic == o.mBsic &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mArfcn == o.mArfcn
+ && mBsic == o.mBsic
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityGsm:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mArfcn=").append(mArfcn);
- sb.append(" mBsic=").append("0x").append(Integer.toHexString(mBsic));
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mArfcn=").append(mArfcn)
+ .append(" mBsic=").append("0x").append(Integer.toHexString(mBsic))
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_GSM);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mArfcn);
dest.writeInt(mBsic);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityGsm(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_GSM, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mArfcn = in.readInt();
+ mBsic = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityGsm(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -320,7 +285,8 @@
new Creator<CellIdentityGsm>() {
@Override
public CellIdentityGsm createFromParcel(Parcel in) {
- return new CellIdentityGsm(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -329,10 +295,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityGsm createFromParcelBody(Parcel in) {
+ return new CellIdentityGsm(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityLte.aidl b/telephony/java/android/telephony/CellIdentityLte.aidl
new file mode 100644
index 0000000..940d170
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityLte.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityLte;
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 6ca5daf6..7f20c8a 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique LTE cell
*/
-public final class CellIdentityLte implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityLte";
+public final class CellIdentityLte extends CellIdentity {
+ private static final String TAG = CellIdentityLte.class.getSimpleName();
private static final boolean DBG = false;
// 28-bit cell identity
@@ -39,10 +36,6 @@
private final int mTac;
// 18-bit Absolute RF Channel Number
private final int mEarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityLte() {
+ super(TAG, TYPE_LTE, null, null);
mCi = Integer.MAX_VALUE;
mPci = Integer.MAX_VALUE;
mTac = Integer.MAX_VALUE;
mEarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -72,7 +64,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
this(ci, pci, tac, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -87,7 +79,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
this(ci, pci, tac, earfcn, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -104,38 +96,13 @@
*
* @hide
*/
- public CellIdentityLte (int ci, int pci, int tac, int earfcn, String mccStr,
+ public CellIdentityLte(int ci, int pci, int tac, int earfcn, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_LTE, mccStr, mncStr);
mCi = ci;
mPci = pci;
mTac = tac;
mEarfcn = earfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -248,58 +215,54 @@
}
CellIdentityLte o = (CellIdentityLte) other;
- return mCi == o.mCi &&
- mPci == o.mPci &&
- mTac == o.mTac &&
- mEarfcn == o.mEarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mCi == o.mCi
+ && mPci == o.mPci
+ && mTac == o.mTac
+ && mEarfcn == o.mEarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityLte:{");
- sb.append(" mCi="); sb.append(mCi);
- sb.append(" mPci="); sb.append(mPci);
- sb.append(" mTac="); sb.append(mTac);
- sb.append(" mEarfcn="); sb.append(mEarfcn);
- sb.append(" mMcc="); sb.append(mMccStr);
- sb.append(" mMnc="); sb.append(mMncStr);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mCi=").append(mCi)
+ .append(" mPci=").append(mPci)
+ .append(" mTac=").append(mTac)
+ .append(" mEarfcn=").append(mEarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_LTE);
dest.writeInt(mCi);
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mEarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityLte(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_LTE, in);
+ mCi = in.readInt();
+ mPci = in.readInt();
+ mTac = in.readInt();
+ mEarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityLte(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -308,7 +271,8 @@
new Creator<CellIdentityLte>() {
@Override
public CellIdentityLte createFromParcel(Parcel in) {
- return new CellIdentityLte(in);
+ in.readInt(); // skip;
+ return createFromParcelBody(in);
}
@Override
@@ -317,10 +281,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityLte createFromParcelBody(Parcel in) {
+ return new CellIdentityLte(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.aidl b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
new file mode 100644
index 0000000..2a182cd
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityTdscdma;
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
new file mode 100644
index 0000000..001d19f
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -0,0 +1,196 @@
+/*
+ * 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;
+
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * CellIdentity is to represent a unique TD-SCDMA cell
+ */
+public final class CellIdentityTdscdma extends CellIdentity {
+ private static final String TAG = CellIdentityTdscdma.class.getSimpleName();
+ private static final boolean DBG = false;
+
+ // 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+ private final int mLac;
+ // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+ private final int mCid;
+ // 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+ private final int mCpid;
+
+ /**
+ * @hide
+ */
+ public CellIdentityTdscdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
+ mLac = Integer.MAX_VALUE;
+ mCid = Integer.MAX_VALUE;
+ mCpid = Integer.MAX_VALUE;
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
+ this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid);
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code in string format
+ * @param mnc 2 or 3-digit Mobile Network Code in string format
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
+ super(TAG, TYPE_TDSCDMA, mcc, mnc);
+ mLac = lac;
+ mCid = cid;
+ mCpid = cpid;
+ }
+
+ private CellIdentityTdscdma(CellIdentityTdscdma cid) {
+ this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, cid.mCpid);
+ }
+
+ CellIdentityTdscdma copy() {
+ return new CellIdentityTdscdma(this);
+ }
+
+ /**
+ * Get Mobile Country Code in string format
+ * @return Mobile Country Code in string format, null if unknown
+ */
+ public String getMccStr() {
+ return mMccStr;
+ }
+
+ /**
+ * Get Mobile Network Code in string format
+ * @return Mobile Network Code in string format, null if unknown
+ */
+ public String getMncStr() {
+ return mMncStr;
+ }
+
+ /**
+ * @return 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ */
+ public int getLac() {
+ return mLac;
+ }
+
+ /**
+ * @return 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ */
+ public int getCid() {
+ return mCid;
+ }
+
+ /**
+ * @return 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ */
+ public int getCpid() {
+ return mCpid;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mMccStr, mMncStr, mLac, mCid, mCpid);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof CellIdentityTdscdma)) {
+ return false;
+ }
+
+ CellIdentityTdscdma o = (CellIdentityTdscdma) other;
+ return TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && mLac == o.mLac
+ && mCid == o.mCid
+ && mCpid == o.mCpid;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(TAG)
+ .append(":{ mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mCpid=").append(mCpid)
+ .append("}").toString();
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_TDSCDMA);
+ dest.writeInt(mLac);
+ dest.writeInt(mCid);
+ dest.writeInt(mCpid);
+ }
+
+ /** Construct from Parcel, type has already been processed */
+ private CellIdentityTdscdma(Parcel in) {
+ super(TAG, TYPE_TDSCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mCpid = in.readInt();
+
+ if (DBG) log(toString());
+ }
+
+ /** Implement the Parcelable interface */
+ @SuppressWarnings("hiding")
+ public static final Creator<CellIdentityTdscdma> CREATOR =
+ new Creator<CellIdentityTdscdma>() {
+ @Override
+ public CellIdentityTdscdma createFromParcel(Parcel in) {
+ in.readInt(); // skip
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public CellIdentityTdscdma[] newArray(int size) {
+ return new CellIdentityTdscdma[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellIdentityTdscdma createFromParcelBody(Parcel in) {
+ return new CellIdentityTdscdma(in);
+ }
+}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.aidl b/telephony/java/android/telephony/CellIdentityWcdma.aidl
new file mode 100644
index 0000000..462ce2c
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityWcdma.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityWcdma;
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index e4bb4f2..1aa1715 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique UMTS cell
*/
-public final class CellIdentityWcdma implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityWcdma";
+public final class CellIdentityWcdma extends CellIdentity {
+ private static final String TAG = CellIdentityWcdma.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mPsc;
// 16-bit UMTS Absolute RF Channel Number
private final int mUarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityWcdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mPsc = Integer.MAX_VALUE;
mUarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -106,36 +98,11 @@
*/
public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn,
String mccStr, String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_WCDMA, mccStr, mncStr);
mLac = lac;
mCid = cid;
mPsc = psc;
mUarfcn = uarfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -250,58 +217,53 @@
}
CellIdentityWcdma o = (CellIdentityWcdma) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mPsc == o.mPsc &&
- mUarfcn == o.mUarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mPsc == o.mPsc
+ && mUarfcn == o.mUarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityWcdma:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mPsc=").append(mPsc);
- sb.append(" mUarfcn=").append(mUarfcn);
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mPsc=").append(mPsc)
+ .append(" mUarfcn=").append(mUarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_WCDMA);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mPsc);
dest.writeInt(mUarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityWcdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
-
- if (DBG) log("CellIdentityWcdma(Parcel): " + toString());
+ super(TAG, TYPE_WCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mPsc = in.readInt();
+ mUarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -310,7 +272,8 @@
new Creator<CellIdentityWcdma>() {
@Override
public CellIdentityWcdma createFromParcel(Parcel in) {
- return new CellIdentityWcdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -319,10 +282,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityWcdma createFromParcelBody(Parcel in) {
+ return new CellIdentityWcdma(in);
}
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java
index ea503c3..9726569 100644
--- a/telephony/java/android/telephony/NetworkScanRequest.java
+++ b/telephony/java/android/telephony/NetworkScanRequest.java
@@ -143,7 +143,11 @@
int incrementalResultsPeriodicity,
ArrayList<String> mccMncs) {
this.mScanType = scanType;
- this.mSpecifiers = specifiers.clone();
+ if (specifiers != null) {
+ this.mSpecifiers = specifiers.clone();
+ } else {
+ this.mSpecifiers = null;
+ }
this.mSearchPeriodicity = searchPeriodicity;
this.mMaxSearchTime = maxSearchTime;
this.mIncrementalResults = incrementalResults;
@@ -187,7 +191,7 @@
/** Returns the radio access technologies with bands or channels that need to be scanned. */
public RadioAccessSpecifier[] getSpecifiers() {
- return mSpecifiers.clone();
+ return mSpecifiers == null ? null : mSpecifiers.clone();
}
/**
diff --git a/telephony/java/android/telephony/RadioAccessSpecifier.java b/telephony/java/android/telephony/RadioAccessSpecifier.java
index 5412c61..81e7ed0 100644
--- a/telephony/java/android/telephony/RadioAccessSpecifier.java
+++ b/telephony/java/android/telephony/RadioAccessSpecifier.java
@@ -33,7 +33,7 @@
*
* This parameter must be provided or else the scan will be rejected.
*
- * See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
+ * See {@link AccessNetworkConstants.AccessNetworkType} for details.
*/
private int mRadioAccessNetwork;
@@ -43,7 +43,7 @@
* When no specific bands are specified (empty array or null), all the frequency bands
* supported by the modem will be scanned.
*
- * See {@link RadioNetworkConstants} for details.
+ * See {@link AccessNetworkConstants} for details.
*/
private int[] mBands;
@@ -56,7 +56,7 @@
* When no specific channels are specified (empty array or null), all the frequency channels
* supported by the modem will be scanned.
*
- * See {@link RadioNetworkConstants} for details.
+ * See {@link AccessNetworkConstants} for details.
*/
private int[] mChannels;
@@ -72,14 +72,22 @@
*/
public RadioAccessSpecifier(int ran, int[] bands, int[] channels) {
this.mRadioAccessNetwork = ran;
- this.mBands = bands.clone();
- this.mChannels = channels.clone();
+ if (bands != null) {
+ this.mBands = bands.clone();
+ } else {
+ this.mBands = null;
+ }
+ if (channels != null) {
+ this.mChannels = channels.clone();
+ } else {
+ this.mChannels = null;
+ }
}
/**
* Returns the radio access network that needs to be scanned.
*
- * The returned value is define in {@link RadioNetworkConstants.RadioAccessNetworks};
+ * The returned value is define in {@link AccessNetworkConstants.AccessNetworkType};
*/
public int getRadioAccessNetwork() {
return mRadioAccessNetwork;
@@ -88,17 +96,17 @@
/**
* Returns the frequency bands that need to be scanned.
*
- * The returned value is defined in either of {@link RadioNetworkConstants.GeranBands},
- * {@link RadioNetworkConstants.UtranBands} and {@link RadioNetworkConstants.EutranBands}, and
+ * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}, and
* it depends on the returned value of {@link #getRadioAccessNetwork()}.
*/
public int[] getBands() {
- return mBands.clone();
+ return mBands == null ? null : mBands.clone();
}
/** Returns the frequency channels that need to be scanned. */
public int[] getChannels() {
- return mChannels.clone();
+ return mChannels == null ? null : mChannels.clone();
}
public static final Parcelable.Creator<RadioAccessSpecifier> CREATOR =
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 116e711..d4b4b88 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -16,12 +16,15 @@
package android.telephony;
+import android.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Contains phone state and service related information.
*
@@ -105,6 +108,31 @@
/** @hide */
public static final int RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED = 14;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "RIL_RADIO_TECHNOLOGY_" },
+ value = {
+ RIL_RADIO_TECHNOLOGY_UNKNOWN,
+ RIL_RADIO_TECHNOLOGY_GPRS,
+ RIL_RADIO_TECHNOLOGY_EDGE,
+ RIL_RADIO_TECHNOLOGY_UMTS,
+ RIL_RADIO_TECHNOLOGY_IS95A,
+ RIL_RADIO_TECHNOLOGY_IS95B,
+ RIL_RADIO_TECHNOLOGY_1xRTT,
+ RIL_RADIO_TECHNOLOGY_EVDO_0,
+ RIL_RADIO_TECHNOLOGY_EVDO_A,
+ RIL_RADIO_TECHNOLOGY_HSDPA,
+ RIL_RADIO_TECHNOLOGY_HSUPA,
+ RIL_RADIO_TECHNOLOGY_HSPA,
+ RIL_RADIO_TECHNOLOGY_EVDO_B,
+ RIL_RADIO_TECHNOLOGY_EHRPD,
+ RIL_RADIO_TECHNOLOGY_LTE,
+ RIL_RADIO_TECHNOLOGY_HSPAP,
+ RIL_RADIO_TECHNOLOGY_GSM,
+ RIL_RADIO_TECHNOLOGY_TD_SCDMA,
+ RIL_RADIO_TECHNOLOGY_IWLAN,
+ RIL_RADIO_TECHNOLOGY_LTE_CA})
+ public @interface RilRadioTechnology {}
/**
* Available radio technologies for GSM, UMTS and CDMA.
* Duplicates the constants from hardware/radio/include/ril.h
@@ -162,6 +190,12 @@
*/
public static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
+ /**
+ * Number of radio technologies for GSM, UMTS and CDMA.
+ * @hide
+ */
+ private static final int NEXT_RIL_RADIO_TECHNOLOGY = 20;
+
/** @hide */
public static final int RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =
(1 << (RIL_RADIO_TECHNOLOGY_IS95A - 1))
@@ -216,6 +250,11 @@
*/
public static final int ROAMING_TYPE_INTERNATIONAL = 3;
+ /**
+ * Unknown ID. Could be returned by {@link #getNetworkId()} or {@link #getSystemId()}
+ */
+ public static final int UNKNOWN_ID = -1;
+
private int mVoiceRoamingType;
private int mDataRoamingType;
private String mVoiceOperatorAlphaLong;
@@ -1153,7 +1192,8 @@
return getRilDataRadioTechnology();
}
- private int rilRadioTechnologyToNetworkType(int rt) {
+ /** @hide */
+ public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rt) {
switch(rt) {
case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS:
return TelephonyManager.NETWORK_TYPE_GPRS;
@@ -1212,12 +1252,20 @@
return this.mCssIndicator ? 1 : 0;
}
- /** @hide */
+ /**
+ * Get the CDMA NID (Network Identification Number), a number uniquely identifying a network
+ * within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
+ * @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
+ */
public int getNetworkId() {
return this.mNetworkId;
}
- /** @hide */
+ /**
+ * Get the CDMA SID (System Identification Number), a number uniquely identifying a wireless
+ * system. (Defined in 3GPP2 C.S0023 3.4.8)
+ * @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
+ */
public int getSystemId() {
return this.mSystemId;
}
@@ -1300,6 +1348,34 @@
return bearerBitmask;
}
+ /** @hide */
+ public static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
+ if (networkTypeBitmask == 0) {
+ return 0;
+ }
+ int bearerBitmask = 0;
+ for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
+ if (bitmaskHasTech(networkTypeBitmask, rilRadioTechnologyToNetworkType(bearerInt))) {
+ bearerBitmask |= getBitmaskForTech(bearerInt);
+ }
+ }
+ return bearerBitmask;
+ }
+
+ /** @hide */
+ public static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
+ if (bearerBitmask == 0) {
+ return 0;
+ }
+ int networkTypeBitmask = 0;
+ for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
+ if (bitmaskHasTech(bearerBitmask, bearerInt)) {
+ networkTypeBitmask |= getBitmaskForTech(rilRadioTechnologyToNetworkType(bearerInt));
+ }
+ }
+ return networkTypeBitmask;
+ }
+
/**
* Returns a merged ServiceState consisting of the base SS with voice settings from the
* voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned).
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 62b0f9b..78a4c65 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -339,6 +339,7 @@
* Send a text based SMS without writing it into the SMS Provider.
*
* <p>Requires Permission:
+ * {@link android.Manifest.permission#SEND_SMS} and
* {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
* privileges.
* </p>
@@ -347,7 +348,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ android.Manifest.permission.SEND_SMS
+ })
public void sendTextMessageWithoutPersisting(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c84db95..64cc7c1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -361,6 +361,42 @@
public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
/**
+ * TelephonyProvider column name for enable Volte.
+ *@hide
+ */
+ public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
+
+ /**
+ * TelephonyProvider column name for enable VT (Video Telephony over IMS)
+ *@hide
+ */
+ public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+
+ /**
+ * TelephonyProvider column name for enable Wifi calling
+ *@hide
+ */
+ public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
+
+ /**
+ * TelephonyProvider column name for Wifi calling mode
+ *@hide
+ */
+ public static final String WFC_IMS_MODE = "wfc_ims_mode";
+
+ /**
+ * TelephonyProvider column name for Wifi calling mode in roaming
+ *@hide
+ */
+ public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
+
+ /**
+ * TelephonyProvider column name for enable Wifi calling in roaming
+ *@hide
+ */
+ public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
+
+ /**
* Broadcast Action: The user has changed one of the default subs related to
* data, phone calls, or sms</p>
*
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index d7b6142..e0b6f61 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -2693,6 +2693,7 @@
* but is currently only used for LTE (14) and eHRPD (13).
* <P>Type: INTEGER</P>
*/
+ @Deprecated
public static final String BEARER = "bearer";
/**
@@ -2704,9 +2705,19 @@
* <P>Type: INTEGER</P>
* @hide
*/
+ @Deprecated
public static final String BEARER_BITMASK = "bearer_bitmask";
/**
+ * Radio technology (network type) bitmask.
+ * To check what values can be contained, refer to
+ * {@link android.telephony.TelephonyManager}.
+ * Bitmask for a radio tech R is (1 << (R - 1))
+ * <P>Type: INTEGER</P>
+ */
+ public static final String NETWORK_TYPE_BITMASK = "network_type_bitmask";
+
+ /**
* MVNO type:
* {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
* <P>Type: TEXT</P>
@@ -3342,6 +3353,12 @@
public static final String APN = "apn";
/**
+ * Prefix of Integrated Circuit Card Identifier.
+ * <P>Type: TEXT </P>
+ */
+ public static final String ICCID_PREFIX = "iccid_prefix";
+
+ /**
* User facing carrier name.
* <P>Type: TEXT </P>
*/
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4505994..f278d7c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5676,39 +5676,38 @@
* @param enable Whether to enable mobile data.
*
* @see #hasCarrierPrivileges
+ * @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
- setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
+ setUserMobileDataEnabled(enable);
}
- /** @hide */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void setDataEnabled(int subId, boolean enable) {
- try {
- Log.d(TAG, "setDataEnabled: enabled=" + enable);
- ITelephony telephony = getITelephony();
- if (telephony != null)
- telephony.setDataEnabled(subId, enable);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setDataEnabled", e);
- }
- }
-
-
/**
- * @deprecated use {@link #isDataEnabled()} instead.
+ * @hide
+ * @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
+ */
+ @SystemApi
+ @Deprecated
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setDataEnabled(int subId, boolean enable) {
+ setUserMobileDataEnabled(subId, enable);
+ }
+
+ /**
+ * @deprecated use {@link #isUserMobileDataEnabled()} instead.
* @hide
*/
@SystemApi
@Deprecated
public boolean getDataEnabled() {
- return isDataEnabled();
+ return isUserMobileDataEnabled();
}
/**
- * Returns whether mobile data is enabled or not.
+ * Returns whether mobile data is enabled or not per user setting. There are other factors
+ * that could disable mobile data, but they are not considered here.
*
* If this object has been created with {@link #createForSubscriptionId}, applies to the given
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
@@ -5725,28 +5724,21 @@
* @return true if mobile data is enabled.
*
* @see #hasCarrierPrivileges
+ * @deprecated use {@link #isUserMobileDataEnabled()} instead.
*/
- @SuppressWarnings("deprecation")
+ @Deprecated
public boolean isDataEnabled() {
- return getDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
+ return isUserMobileDataEnabled();
}
/**
- * @deprecated use {@link #isDataEnabled(int)} instead.
+ * @deprecated use {@link #isUserMobileDataEnabled()} instead.
* @hide
*/
+ @Deprecated
@SystemApi
public boolean getDataEnabled(int subId) {
- boolean retVal = false;
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- retVal = telephony.getDataEnabled(subId);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#getDataEnabled", e);
- } catch (NullPointerException e) {
- }
- return retVal;
+ return isUserMobileDataEnabled(subId);
}
/** @hide */
@@ -5859,45 +5851,6 @@
return false;
}
- /**
- * This function retrieves value for setting "name+subId", and if that is not found
- * retrieves value for setting "name", and if that is not found throws
- * SettingNotFoundException
- *
- * @hide
- */
- public static int getIntWithSubId(ContentResolver cr, String name, int subId)
- throws SettingNotFoundException {
- try {
- return Settings.Global.getInt(cr, name + subId);
- } catch (SettingNotFoundException e) {
- try {
- int val = Settings.Global.getInt(cr, name);
- Settings.Global.putInt(cr, name + subId, val);
-
- /* We are now moving from 'setting' to 'setting+subId', and using the value stored
- * for 'setting' as default. Reset the default (since it may have a user set
- * value). */
- int default_val = val;
- if (name.equals(Settings.Global.MOBILE_DATA)) {
- default_val = "true".equalsIgnoreCase(
- SystemProperties.get("ro.com.android.mobiledata", "true")) ? 1 : 0;
- } else if (name.equals(Settings.Global.DATA_ROAMING)) {
- default_val = "true".equalsIgnoreCase(
- SystemProperties.get("ro.com.android.dataroaming", "false")) ? 1 : 0;
- }
-
- if (default_val != val) {
- Settings.Global.putInt(cr, name, default_val);
- }
-
- return val;
- } catch (SettingNotFoundException exc) {
- throw new SettingNotFoundException(name);
- }
- }
- }
-
/**
* Returns the IMS Registration Status
* @hide
@@ -6937,4 +6890,101 @@
}
return null;
}
+
+ /**
+ * Turns mobile data on or off.
+ * If the {@link TelephonyManager} object has been created with
+ * {@link #createForSubscriptionId}, this API applies to the given subId.
+ * Otherwise, it applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges.
+ *
+ * @param enable Whether to enable mobile data.
+ *
+ * @see #hasCarrierPrivileges
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setUserMobileDataEnabled(boolean enable) {
+ setUserMobileDataEnabled(
+ getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
+ }
+
+ /**
+ * Returns whether mobile data is enabled or not per user setting. There are other factors
+ * that could disable mobile data, but they are not considered here.
+ *
+ * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+ * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ *
+ * <p>Requires one of the following permissions:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
+ * calling app has carrier privileges.
+ *
+ * <p>Note that this does not take into account any data restrictions that may be present on the
+ * calling app. Such restrictions may be inspected with
+ * {@link ConnectivityManager#getRestrictBackgroundStatus}.
+ *
+ * @return true if mobile data is enabled.
+ *
+ * @see #hasCarrierPrivileges
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_NETWORK_STATE,
+ android.Manifest.permission.MODIFY_PHONE_STATE
+ })
+ public boolean isUserMobileDataEnabled() {
+ return isUserMobileDataEnabled(
+ getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
+ }
+
+ /**
+ * @hide
+ * Unlike isUserMobileDataEnabled, this API also evaluates carrierDataEnabled,
+ * policyDataEnabled etc to give a final decision.
+ */
+ public boolean isMobileDataEnabled() {
+ boolean retVal = false;
+ try {
+ int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ retVal = telephony.isDataEnabled(subId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#isDataEnabled", e);
+ } catch (NullPointerException e) {
+ }
+ return retVal;
+ }
+
+ /**
+ * Utility class of {@link #isUserMobileDataEnabled()};
+ */
+ private boolean isUserMobileDataEnabled(int subId) {
+ boolean retVal = false;
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ retVal = telephony.isUserDataEnabled(subId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#isUserDataEnabled", e);
+ } catch (NullPointerException e) {
+ }
+ return retVal;
+ }
+
+ /** Utility method of {@link #setUserMobileDataEnabled(boolean)} */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ private void setUserMobileDataEnabled(int subId, boolean enable) {
+ try {
+ Log.d(TAG, "setUserMobileDataEnabled: enabled=" + enable);
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ telephony.setUserDataEnabled(subId, enable);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#setUserDataEnabled", e);
+ }
+ }
}
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index e42a758..3937201 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -32,6 +32,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Objects;
/**
* Describes a single UICC access rule according to the GlobalPlatform Secure Element Access Control
@@ -205,6 +206,21 @@
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccAccessRule that = (UiccAccessRule) obj;
+ return Arrays.equals(mCertificateHash, that.mCertificateHash)
+ && Objects.equals(mPackageName, that.mPackageName)
+ && mAccessType == that.mAccessType;
+ }
+
+ @Override
public String toString() {
return "cert: " + IccUtils.bytesToHexString(mCertificateHash) + " pkg: " +
mPackageName + " access: " + mAccessType;
diff --git a/telephony/java/android/telephony/data/ApnSetting.aidl b/telephony/java/android/telephony/data/ApnSetting.aidl
new file mode 100644
index 0000000..381e5e8
--- /dev/null
+++ b/telephony/java/android/telephony/data/ApnSetting.aidl
@@ -0,0 +1,18 @@
+/*
+ * 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 android.telephony.data;
+
+parcelable ApnSetting;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
new file mode 100644
index 0000000..2ab8d4f
--- /dev/null
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -0,0 +1,1370 @@
+/*
+ * 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 android.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.StringDef;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.hardware.radio.V1_0.ApnTypes;
+import android.net.NetworkUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.net.URL;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A class representing an APN configuration.
+ */
+public class ApnSetting implements Parcelable {
+
+ static final String LOG_TAG = "ApnSetting";
+ private static final boolean VDBG = false;
+
+ private final String mEntryName;
+ private final String mApnName;
+ private final InetAddress mProxy;
+ private final int mPort;
+ private final URL mMmsc;
+ private final InetAddress mMmsProxy;
+ private final int mMmsPort;
+ private final String mUser;
+ private final String mPassword;
+ private final int mAuthType;
+ private final List<String> mTypes;
+ private final int mTypesBitmap;
+ private final int mId;
+ private final String mOperatorNumeric;
+ private final String mProtocol;
+ private final String mRoamingProtocol;
+ private final int mMtu;
+
+ private final boolean mCarrierEnabled;
+ private final int mBearer;
+ private final int mBearerBitmask;
+
+ private final int mProfileId;
+
+ private final boolean mModemCognitive;
+ private final int mMaxConns;
+ private final int mWaitTime;
+ private final int mMaxConnsTime;
+
+ private final String mMvnoType;
+ private final String mMvnoMatchData;
+
+ private boolean mPermanentFailed = false;
+
+ /**
+ * Returns the types bitmap of the APN.
+ *
+ * @return types bitmap of the APN
+ * @hide
+ */
+ public int getTypesBitmap() {
+ return mTypesBitmap;
+ }
+
+ /**
+ * Returns the MTU size of the mobile interface to which the APN connected.
+ *
+ * @return the MTU size of the APN
+ * @hide
+ */
+ public int getMtu() {
+ return mMtu;
+ }
+
+ /**
+ * Radio Access Technology info.
+ * To check what values can hold, refer to ServiceState.java.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the bearer info of the APN
+ * @hide
+ */
+ public int getBearer() {
+ return mBearer;
+ }
+
+ /**
+ * Returns the radio access technology bitmask for this APN.
+ *
+ * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
+ * technologies in ServiceState.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the radio access technology bitmask
+ * @hide
+ */
+ public int getBearerBitmask() {
+ return mBearerBitmask;
+ }
+
+ /**
+ * Returns the profile id to which the APN saved in modem.
+ *
+ * @return the profile id of the APN
+ * @hide
+ */
+ public int getProfileId() {
+ return mProfileId;
+ }
+
+ /**
+ * Returns if the APN setting is to be set in modem.
+ *
+ * @return is the APN setting to be set in modem
+ * @hide
+ */
+ public boolean getModemCognitive() {
+ return mModemCognitive;
+ }
+
+ /**
+ * Returns the max connections of this APN.
+ *
+ * @return the max connections of this APN
+ * @hide
+ */
+ public int getMaxConns() {
+ return mMaxConns;
+ }
+
+ /**
+ * Returns the wait time for retry of the APN.
+ *
+ * @return the wait time for retry of the APN
+ * @hide
+ */
+ public int getWaitTime() {
+ return mWaitTime;
+ }
+
+ /**
+ * Returns the time to limit max connection for the APN.
+ *
+ * @return the time to limit max connection for the APN
+ * @hide
+ */
+ public int getMaxConnsTime() {
+ return mMaxConnsTime;
+ }
+
+ /**
+ * Returns the MVNO data. Examples:
+ * "spn": A MOBILE, BEN NL
+ * "imsi": 302720x94, 2060188
+ * "gid": 4E, 33
+ * "iccid": 898603 etc..
+ *
+ * @return the mvno match data
+ * @hide
+ */
+ public String getMvnoMatchData() {
+ return mMvnoMatchData;
+ }
+
+ /**
+ * Indicates this APN setting is permanently failed and cannot be
+ * retried by the retry manager anymore.
+ *
+ * @return if this APN setting is permanently failed
+ * @hide
+ */
+ public boolean getPermanentFailed() {
+ return mPermanentFailed;
+ }
+
+ /**
+ * Sets if this APN setting is permanently failed.
+ *
+ * @param permanentFailed if this APN setting is permanently failed
+ * @hide
+ */
+ public void setPermanentFailed(boolean permanentFailed) {
+ mPermanentFailed = permanentFailed;
+ }
+
+ /**
+ * Returns the entry name of the APN.
+ *
+ * @return the entry name for the APN
+ */
+ public String getEntryName() {
+ return mEntryName;
+ }
+
+ /**
+ * Returns the name of the APN.
+ *
+ * @return APN name
+ */
+ public String getApnName() {
+ return mApnName;
+ }
+
+ /**
+ * Returns the proxy address of the APN.
+ *
+ * @return proxy address.
+ */
+ public InetAddress getProxy() {
+ return mProxy;
+ }
+
+ /**
+ * Returns the proxy port of the APN.
+ *
+ * @return proxy port
+ */
+ public int getPort() {
+ return mPort;
+ }
+ /**
+ * Returns the MMSC URL of the APN.
+ *
+ * @return MMSC URL.
+ */
+ public URL getMmsc() {
+ return mMmsc;
+ }
+
+ /**
+ * Returns the MMS proxy address of the APN.
+ *
+ * @return MMS proxy address.
+ */
+ public InetAddress getMmsProxy() {
+ return mMmsProxy;
+ }
+
+ /**
+ * Returns the MMS proxy port of the APN.
+ *
+ * @return MMS proxy port
+ */
+ public int getMmsPort() {
+ return mMmsPort;
+ }
+
+ /**
+ * Returns the APN username of the APN.
+ *
+ * @return APN username
+ */
+ public String getUser() {
+ return mUser;
+ }
+
+ /**
+ * Returns the APN password of the APN.
+ *
+ * @return APN password
+ */
+ public String getPassword() {
+ return mPassword;
+ }
+
+ /** @hide */
+ @IntDef({
+ AUTH_TYPE_NONE,
+ AUTH_TYPE_PAP,
+ AUTH_TYPE_CHAP,
+ AUTH_TYPE_PAP_OR_CHAP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AuthType {}
+
+ /**
+ * Returns the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @return authentication type
+ */
+ @AuthType
+ public int getAuthType() {
+ return mAuthType;
+ }
+
+ /** @hide */
+ @StringDef({
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ApnType {}
+
+ /**
+ * Returns the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @return the list of APN types
+ */
+ @ApnType
+ public List<String> getTypes() {
+ return mTypes;
+ }
+
+ /**
+ * Returns the unique database id for this entry.
+ *
+ * @return the unique database id
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the numeric operator ID for the APN. Usually
+ * {@link android.provider.Telephony.Carriers#MCC} +
+ * {@link android.provider.Telephony.Carriers#MNC}.
+ *
+ * @return the numeric operator ID
+ */
+ public String getOperatorNumeric() {
+ return mOperatorNumeric;
+ }
+
+ /** @hide */
+ @StringDef({
+ PROTOCOL_IP,
+ PROTOCOL_IPV6,
+ PROTOCOL_IPV4V6,
+ PROTOCOL_PPP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtocolType {}
+
+ /**
+ * Returns the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @return the protocol
+ */
+ @ProtocolType
+ public String getProtocol() {
+ return mProtocol;
+ }
+
+ /**
+ * Returns the protocol to use to connect to this APN when roaming.
+ *
+ * The syntax is the same as {@link android.provider.Telephony.Carriers#PROTOCOL}.
+ *
+ * @return the roaming protocol
+ */
+ public String getRoamingProtocol() {
+ return mRoamingProtocol;
+ }
+
+ /**
+ * Returns the current status of APN.
+ *
+ * {@code true} : enabled APN.
+ * {@code false} : disabled APN.
+ *
+ * @return the current status
+ */
+ public boolean isEnabled() {
+ return mCarrierEnabled;
+ }
+
+ /** @hide */
+ @StringDef({
+ MVNO_TYPE_SPN,
+ MVNO_TYPE_IMSI,
+ MVNO_TYPE_GID,
+ MVNO_TYPE_ICCID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MvnoType {}
+
+ /**
+ * Returns the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @return the MVNO match type
+ */
+ @MvnoType
+ public String getMvnoType() {
+ return mMvnoType;
+ }
+
+ private ApnSetting(Builder builder) {
+ this.mEntryName = builder.mEntryName;
+ this.mApnName = builder.mApnName;
+ this.mProxy = builder.mProxy;
+ this.mPort = builder.mPort;
+ this.mMmsc = builder.mMmsc;
+ this.mMmsProxy = builder.mMmsProxy;
+ this.mMmsPort = builder.mMmsPort;
+ this.mUser = builder.mUser;
+ this.mPassword = builder.mPassword;
+ this.mAuthType = builder.mAuthType;
+ this.mTypes = (builder.mTypes == null ? new ArrayList<String>() : builder.mTypes);
+ this.mTypesBitmap = builder.mTypesBitmap;
+ this.mId = builder.mId;
+ this.mOperatorNumeric = builder.mOperatorNumeric;
+ this.mProtocol = builder.mProtocol;
+ this.mRoamingProtocol = builder.mRoamingProtocol;
+ this.mMtu = builder.mMtu;
+ this.mCarrierEnabled = builder.mCarrierEnabled;
+ this.mBearer = builder.mBearer;
+ this.mBearerBitmask = builder.mBearerBitmask;
+ this.mProfileId = builder.mProfileId;
+ this.mModemCognitive = builder.mModemCognitive;
+ this.mMaxConns = builder.mMaxConns;
+ this.mWaitTime = builder.mWaitTime;
+ this.mMaxConnsTime = builder.mMaxConnsTime;
+ this.mMvnoType = builder.mMvnoType;
+ this.mMvnoMatchData = builder.mMvnoMatchData;
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
+ String apnName, InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy,
+ int mmsPort, String user, String password, int authType, List<String> types,
+ String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
+ int bearerBitmask, int profileId, boolean modemCognitive, int maxConns,
+ int waitTime, int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
+ return new Builder()
+ .setId(id)
+ .setOperatorNumeric(operatorNumeric)
+ .setEntryName(entryName)
+ .setApnName(apnName)
+ .setProxy(proxy)
+ .setPort(port)
+ .setMmsc(mmsc)
+ .setMmsProxy(mmsProxy)
+ .setMmsPort(mmsPort)
+ .setUser(user)
+ .setPassword(password)
+ .setAuthType(authType)
+ .setTypes(types)
+ .setProtocol(protocol)
+ .setRoamingProtocol(roamingProtocol)
+ .setCarrierEnabled(carrierEnabled)
+ .setBearer(bearer)
+ .setBearerBitmask(bearerBitmask)
+ .setProfileId(profileId)
+ .setModemCognitive(modemCognitive)
+ .setMaxConns(maxConns)
+ .setWaitTime(waitTime)
+ .setMaxConnsTime(maxConnsTime)
+ .setMtu(mtu)
+ .setMvnoType(mvnoType)
+ .setMvnoMatchData(mvnoMatchData)
+ .build();
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(Cursor cursor) {
+ String[] types = parseTypes(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
+
+ return makeApnSetting(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+ URLFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+ Arrays.asList(types),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.BEARER_BITMASK)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MAX_CONNS_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_MATCH_DATA)));
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(ApnSetting apn) {
+ return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
+ apn.mProxy, apn.mPort, apn.mMmsc, apn.mMmsProxy, apn.mMmsPort, apn.mUser,
+ apn.mPassword, apn.mAuthType, apn.mTypes, apn.mProtocol, apn.mRoamingProtocol,
+ apn.mCarrierEnabled, apn.mBearer, apn.mBearerBitmask, apn.mProfileId,
+ apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime, apn.mMaxConnsTime, apn.mMtu,
+ apn.mMvnoType, apn.mMvnoMatchData);
+ }
+
+ /** @hide */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[ApnSettingV3] ")
+ .append(mEntryName)
+ .append(", ").append(mId)
+ .append(", ").append(mOperatorNumeric)
+ .append(", ").append(mApnName)
+ .append(", ").append(inetAddressToString(mProxy))
+ .append(", ").append(URLToString(mMmsc))
+ .append(", ").append(inetAddressToString(mMmsProxy))
+ .append(", ").append(portToString(mMmsPort))
+ .append(", ").append(portToString(mPort))
+ .append(", ").append(mAuthType).append(", ");
+ for (int i = 0; i < mTypes.size(); i++) {
+ sb.append(mTypes.get(i));
+ if (i < mTypes.size() - 1) {
+ sb.append(" | ");
+ }
+ }
+ sb.append(", ").append(mProtocol);
+ sb.append(", ").append(mRoamingProtocol);
+ sb.append(", ").append(mCarrierEnabled);
+ sb.append(", ").append(mBearer);
+ sb.append(", ").append(mBearerBitmask);
+ sb.append(", ").append(mProfileId);
+ sb.append(", ").append(mModemCognitive);
+ sb.append(", ").append(mMaxConns);
+ sb.append(", ").append(mWaitTime);
+ sb.append(", ").append(mMaxConnsTime);
+ sb.append(", ").append(mMtu);
+ sb.append(", ").append(mMvnoType);
+ sb.append(", ").append(mMvnoMatchData);
+ sb.append(", ").append(mPermanentFailed);
+ return sb.toString();
+ }
+
+ /**
+ * Returns true if there are MVNO params specified.
+ * @hide
+ */
+ public boolean hasMvnoParams() {
+ return !TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData);
+ }
+
+ /** @hide */
+ public boolean canHandleType(String type) {
+ if (!mCarrierEnabled) return false;
+ boolean wildcardable = true;
+ if (TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
+ for (String t : mTypes) {
+ // DEFAULT handles all, and HIPRI is handled by DEFAULT
+ if (t.equalsIgnoreCase(type)
+ || (wildcardable && t.equalsIgnoreCase(TYPE_ALL))
+ || (t.equalsIgnoreCase(TYPE_DEFAULT)
+ && type.equalsIgnoreCase(TYPE_HIPRI))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // check whether the types of two APN same (even only one type of each APN is same)
+ private boolean typeSameAny(ApnSetting first, ApnSetting second) {
+ if (VDBG) {
+ StringBuilder apnType1 = new StringBuilder(first.mApnName + ": ");
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ apnType1.append(first.mTypes.get(index1));
+ apnType1.append(",");
+ }
+
+ StringBuilder apnType2 = new StringBuilder(second.mApnName + ": ");
+ for (int index1 = 0; index1 < second.mTypes.size(); index1++) {
+ apnType2.append(second.mTypes.get(index1));
+ apnType2.append(",");
+ }
+ Rlog.d(LOG_TAG, "APN1: is " + apnType1);
+ Rlog.d(LOG_TAG, "APN2: is " + apnType2);
+ }
+
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ for (int index2 = 0; index2 < second.mTypes.size(); index2++) {
+ if (first.mTypes.get(index1).equals(ApnSetting.TYPE_ALL)
+ || second.mTypes.get(index2).equals(ApnSetting.TYPE_ALL)
+ || first.mTypes.get(index1).equals(second.mTypes.get(index2))) {
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
+ return true;
+ }
+ }
+ }
+
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
+ return false;
+ }
+
+ // TODO - if we have this function we should also have hashCode.
+ // Also should handle changes in type order and perhaps case-insensitivity
+ /** @hide */
+ public boolean equals(Object o) {
+ if (o instanceof ApnSetting == false) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort,other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mBearer, other.mBearer)
+ && Objects.equals(mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Compare two APN settings
+ *
+ * Note: This method does not compare 'id', 'bearer', 'bearerBitmask'. We only use this for
+ * determining if tearing a data call is needed when conditions change. See
+ * cleanUpConnectionsOnUpdatedApns in DcTracker.
+ *
+ * @param o the other object to compare
+ * @param isDataRoaming True if the device is on data roaming
+ * @return True if the two APN settings are same
+ * @hide
+ */
+ public boolean equals(Object o, boolean isDataRoaming) {
+ if (!(o instanceof ApnSetting)) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort, other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Check if neither mention DUN and are substantially similar
+ *
+ * @param other The other APN settings to compare
+ * @return True if two APN settings are similar
+ * @hide
+ */
+ public boolean similar(ApnSetting other) {
+ return (!this.canHandleType(TYPE_DUN)
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && !typeSameAny(this, other)
+ && xorEqualsInetAddress(this.mProxy, other.mProxy)
+ && xorEqualsPort(this.mPort, other.mPort)
+ && xorEquals(this.mProtocol, other.mProtocol)
+ && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && xorEqualsURL(this.mMmsc, other.mMmsc)
+ && xorEqualsInetAddress(this.mMmsProxy, other.mMmsProxy)
+ && xorEqualsPort(this.mMmsPort, other.mMmsPort));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEquals(String first, String second) {
+ return (Objects.equals(first, second)
+ || TextUtils.isEmpty(first)
+ || TextUtils.isEmpty(second));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsInetAddress(InetAddress first, InetAddress second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsURL(URL first, URL second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsPort(int first, int second) {
+ return first == -1 || second == -1 || Objects.equals(first, second);
+ }
+
+ // Helper function to convert APN string into a 32-bit bitmask.
+ private static int getApnBitmask(String apn) {
+ switch (apn) {
+ case TYPE_DEFAULT: return ApnTypes.DEFAULT;
+ case TYPE_MMS: return ApnTypes.MMS;
+ case TYPE_SUPL: return ApnTypes.SUPL;
+ case TYPE_DUN: return ApnTypes.DUN;
+ case TYPE_HIPRI: return ApnTypes.HIPRI;
+ case TYPE_FOTA: return ApnTypes.FOTA;
+ case TYPE_IMS: return ApnTypes.IMS;
+ case TYPE_CBS: return ApnTypes.CBS;
+ case TYPE_IA: return ApnTypes.IA;
+ case TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
+ case TYPE_ALL: return ApnTypes.ALL;
+ default: return ApnTypes.NONE;
+ }
+ }
+
+ private String deParseTypes(List<String> types) {
+ if (types == null) {
+ return null;
+ }
+ return TextUtils.join(",", types);
+ }
+
+ /** @hide */
+ // Called by DPM.
+ public ContentValues toContentValues() {
+ ContentValues apnValue = new ContentValues();
+ if (mOperatorNumeric != null) {
+ apnValue.put(Telephony.Carriers.NUMERIC, mOperatorNumeric);
+ }
+ if (mEntryName != null) {
+ apnValue.put(Telephony.Carriers.NAME, mEntryName);
+ }
+ if (mApnName != null) {
+ apnValue.put(Telephony.Carriers.APN, mApnName);
+ }
+ if (mProxy != null) {
+ apnValue.put(Telephony.Carriers.PROXY, inetAddressToString(mProxy));
+ }
+ apnValue.put(Telephony.Carriers.PORT, portToString(mPort));
+ if (mMmsc != null) {
+ apnValue.put(Telephony.Carriers.MMSC, URLToString(mMmsc));
+ }
+ apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsPort));
+ if (mMmsProxy != null) {
+ apnValue.put(Telephony.Carriers.MMSPROXY, inetAddressToString(mMmsProxy));
+ }
+ if (mUser != null) {
+ apnValue.put(Telephony.Carriers.USER, mUser);
+ }
+ if (mPassword != null) {
+ apnValue.put(Telephony.Carriers.PASSWORD, mPassword);
+ }
+ apnValue.put(Telephony.Carriers.AUTH_TYPE, mAuthType);
+ String apnType = deParseTypes(mTypes);
+ if (apnType != null) {
+ apnValue.put(Telephony.Carriers.TYPE, apnType);
+ }
+ if (mProtocol != null) {
+ apnValue.put(Telephony.Carriers.PROTOCOL, mProtocol);
+ }
+ if (mRoamingProtocol != null) {
+ apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL, mRoamingProtocol);
+ }
+ apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
+ // networkTypeBit.
+ apnValue.put(Telephony.Carriers.BEARER_BITMASK, mBearerBitmask);
+ if (mMvnoType != null) {
+ apnValue.put(Telephony.Carriers.MVNO_TYPE, mMvnoType);
+ }
+
+ return apnValue;
+ }
+
+ /**
+ * @param types comma delimited list of APN types
+ * @return array of APN types
+ * @hide
+ */
+ public static String[] parseTypes(String types) {
+ String[] result;
+ // If unset, set to DEFAULT.
+ if (TextUtils.isEmpty(types)) {
+ result = new String[1];
+ result[0] = TYPE_ALL;
+ } else {
+ result = types.split(",");
+ }
+ return result;
+ }
+
+ private static URL URLFromString(String url) {
+ try {
+ return TextUtils.isEmpty(url) ? null : new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(LOG_TAG, "Can't parse URL from string.");
+ return null;
+ }
+ }
+
+ private static String URLToString(URL url) {
+ return url == null ? "" : url.toString();
+ }
+
+ private static InetAddress inetAddressFromString(String inetAddress) {
+ if (TextUtils.isEmpty(inetAddress)) {
+ return null;
+ }
+ try {
+ return InetAddress.getByName(inetAddress);
+ } catch (UnknownHostException e) {
+ Log.e(LOG_TAG, "Can't parse InetAddress from string: unknown host.");
+ return null;
+ }
+ }
+
+ private static String inetAddressToString(InetAddress inetAddress) {
+ if (inetAddress == null) {
+ return null;
+ }
+ return TextUtils.isEmpty(inetAddress.getHostName())
+ ? inetAddress.getHostAddress() : inetAddress.getHostName();
+ }
+
+ private static int portFromString(String strPort) {
+ int port = -1;
+ if (!TextUtils.isEmpty(strPort)) {
+ try {
+ port = Integer.parseInt(strPort);
+ } catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Can't parse port from String");
+ }
+ }
+ return port;
+ }
+
+ private static String portToString(int port) {
+ return port == -1 ? "" : Integer.toString(port);
+ }
+
+ // Implement Parcelable.
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mId);
+ dest.writeString(mOperatorNumeric);
+ dest.writeString(mEntryName);
+ dest.writeString(mApnName);
+ dest.writeValue(mProxy);
+ dest.writeInt(mPort);
+ dest.writeValue(mMmsc);
+ dest.writeValue(mMmsProxy);
+ dest.writeInt(mMmsPort);
+ dest.writeString(mUser);
+ dest.writeString(mPassword);
+ dest.writeInt(mAuthType);
+ dest.writeStringArray(mTypes.toArray(new String[0]));
+ dest.writeString(mProtocol);
+ dest.writeString(mRoamingProtocol);
+ dest.writeInt(mCarrierEnabled ? 1: 0);
+ dest.writeString(mMvnoType);
+ }
+
+ private static ApnSetting readFromParcel(Parcel in) {
+ return makeApnSetting(in.readInt(), in.readString(), in.readString(), in.readString(),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), (URL)in.readValue(URL.class.getClassLoader()),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), in.readString(), in.readString(), in.readInt(),
+ Arrays.asList(in.readStringArray()), in.readString(), in.readString(),
+ in.readInt() > 0, 0, 0, 0, false, 0, 0, 0, 0, in.readString(), null);
+ }
+
+ public static final Parcelable.Creator<ApnSetting> CREATOR =
+ new Parcelable.Creator<ApnSetting>() {
+ @Override
+ public ApnSetting createFromParcel(Parcel in) {
+ return readFromParcel(in);
+ }
+
+ @Override
+ public ApnSetting[] newArray(int size) {
+ return new ApnSetting[size];
+ }
+ };
+
+ /**
+ * APN types for data connections. These are usage categories for an APN
+ * entry. One APN entry may support multiple APN types, eg, a single APN
+ * may service regular internet traffic ("default") as well as MMS-specific
+ * connections.<br/>
+ * ALL is a special type to indicate that this APN entry can
+ * service all data connections.
+ */
+ public static final String TYPE_ALL = "*";
+ /** APN type for default data traffic */
+ public static final String TYPE_DEFAULT = "default";
+ /** APN type for MMS traffic */
+ public static final String TYPE_MMS = "mms";
+ /** APN type for SUPL assisted GPS */
+ public static final String TYPE_SUPL = "supl";
+ /** APN type for DUN traffic */
+ public static final String TYPE_DUN = "dun";
+ /** APN type for HiPri traffic */
+ public static final String TYPE_HIPRI = "hipri";
+ /** APN type for FOTA */
+ public static final String TYPE_FOTA = "fota";
+ /** APN type for IMS */
+ public static final String TYPE_IMS = "ims";
+ /** APN type for CBS */
+ public static final String TYPE_CBS = "cbs";
+ /** APN type for IA Initial Attach APN */
+ public static final String TYPE_IA = "ia";
+ /** APN type for Emergency PDN. This is not an IA apn, but is used
+ * for access to carrier services in an emergency call situation. */
+ public static final String TYPE_EMERGENCY = "emergency";
+ /**
+ * Array of all APN types
+ *
+ * @hide
+ */
+ public static final String[] ALL_TYPES = {
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ };
+
+ // Possible values for authentication types.
+ public static final int AUTH_TYPE_NONE = 0;
+ public static final int AUTH_TYPE_PAP = 1;
+ public static final int AUTH_TYPE_CHAP = 2;
+ public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
+
+ // Possible values for protocol.
+ public static final String PROTOCOL_IP = "IP";
+ public static final String PROTOCOL_IPV6 = "IPV6";
+ public static final String PROTOCOL_IPV4V6 = "IPV4V6";
+ public static final String PROTOCOL_PPP = "PPP";
+
+ // Possible values for MVNO type.
+ public static final String MVNO_TYPE_SPN = "spn";
+ public static final String MVNO_TYPE_IMSI = "imsi";
+ public static final String MVNO_TYPE_GID = "gid";
+ public static final String MVNO_TYPE_ICCID = "iccid";
+
+ public static class Builder{
+ private String mEntryName;
+ private String mApnName;
+ private InetAddress mProxy;
+ private int mPort = -1;
+ private URL mMmsc;
+ private InetAddress mMmsProxy;
+ private int mMmsPort = -1;
+ private String mUser;
+ private String mPassword;
+ private int mAuthType;
+ private List<String> mTypes;
+ private int mTypesBitmap;
+ private int mId;
+ private String mOperatorNumeric;
+ private String mProtocol;
+ private String mRoamingProtocol;
+ private int mMtu;
+ private boolean mCarrierEnabled;
+ private int mBearer;
+ private int mBearerBitmask;
+ private int mProfileId;
+ private boolean mModemCognitive;
+ private int mMaxConns;
+ private int mWaitTime;
+ private int mMaxConnsTime;
+ private String mMvnoType;
+ private String mMvnoMatchData;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Set the MTU size of the mobile interface to which the APN connected.
+ *
+ * @param mtu the MTU size to set for the APN
+ * @hide
+ */
+ public Builder setMtu(int mtu) {
+ this.mMtu = mtu;
+ return this;
+ }
+
+ /**
+ * Sets bearer info.
+ *
+ * @param bearer the bearer info to set for the APN
+ * @hide
+ */
+ public Builder setBearer(int bearer) {
+ this.mBearer = bearer;
+ return this;
+ }
+
+ /**
+ * Sets the radio access technology bitmask for this APN.
+ *
+ * @param bearerBitmask the radio access technology bitmask to set for this APN
+ * @hide
+ */
+ public Builder setBearerBitmask(int bearerBitmask) {
+ this.mBearerBitmask = bearerBitmask;
+ return this;
+ }
+
+ /**
+ * Sets the profile id to which the APN saved in modem.
+ *
+ * @param profileId the profile id to set for the APN
+ * @hide
+ */
+ public Builder setProfileId(int profileId) {
+ this.mProfileId = profileId;
+ return this;
+ }
+
+ /**
+ * Sets if the APN setting is to be set in modem.
+ *
+ * @param modemCognitive if the APN setting is to be set in modem
+ * @hide
+ */
+ public Builder setModemCognitive(boolean modemCognitive) {
+ this.mModemCognitive = modemCognitive;
+ return this;
+ }
+
+ /**
+ * Sets the max connections of this APN.
+ *
+ * @param maxConns the max connections of this APN
+ * @hide
+ */
+ public Builder setMaxConns(int maxConns) {
+ this.mMaxConns = maxConns;
+ return this;
+ }
+
+ /**
+ * Sets the wait time for retry of the APN.
+ *
+ * @param waitTime the wait time for retry of the APN
+ * @hide
+ */
+ public Builder setWaitTime(int waitTime) {
+ this.mWaitTime = waitTime;
+ return this;
+ }
+
+ /**
+ * Sets the time to limit max connection for the APN.
+ *
+ * @param maxConnsTime the time to limit max connection for the APN
+ * @hide
+ */
+ public Builder setMaxConnsTime(int maxConnsTime) {
+ this.mMaxConnsTime = maxConnsTime;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match data for the APN.
+ *
+ * @param mvnoMatchData the MVNO match data for the APN
+ * @hide
+ */
+ public Builder setMvnoMatchData(String mvnoMatchData) {
+ this.mMvnoMatchData = mvnoMatchData;
+ return this;
+ }
+
+ /**
+ * Sets the entry name of the APN.
+ *
+ * @param entryName the entry name to set for the APN
+ */
+ public Builder setEntryName(String entryName) {
+ this.mEntryName = entryName;
+ return this;
+ }
+
+ /**
+ * Sets the name of the APN.
+ *
+ * @param apnName the name to set for the APN
+ */
+ public Builder setApnName(String apnName) {
+ this.mApnName = apnName;
+ return this;
+ }
+
+ /**
+ * Sets the proxy address of the APN.
+ *
+ * @param proxy the proxy address to set for the APN
+ */
+ public Builder setProxy(InetAddress proxy) {
+ this.mProxy = proxy;
+ return this;
+ }
+
+ /**
+ * Sets the proxy port of the APN.
+ *
+ * @param port the proxy port to set for the APN
+ */
+ public Builder setPort(int port) {
+ this.mPort = port;
+ return this;
+ }
+
+ /**
+ * Sets the MMSC URL of the APN.
+ *
+ * @param mmsc the MMSC URL to set for the APN
+ */
+ public Builder setMmsc(URL mmsc) {
+ this.mMmsc = mmsc;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy address of the APN.
+ *
+ * @param mmsProxy the MMS proxy address to set for the APN
+ */
+ public Builder setMmsProxy(InetAddress mmsProxy) {
+ this.mMmsProxy = mmsProxy;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy port of the APN.
+ *
+ * @param mmsPort the MMS proxy port to set for the APN
+ */
+ public Builder setMmsPort(int mmsPort) {
+ this.mMmsPort = mmsPort;
+ return this;
+ }
+
+ /**
+ * Sets the APN username of the APN.
+ *
+ * @param user the APN username to set for the APN
+ */
+ public Builder setUser(String user) {
+ this.mUser = user;
+ return this;
+ }
+
+ /**
+ * Sets the APN password of the APN.
+ *
+ * @see android.provider.Telephony.Carriers#PASSWORD
+ * @param password the APN password to set for the APN
+ */
+ public Builder setPassword(String password) {
+ this.mPassword = password;
+ return this;
+ }
+
+ /**
+ * Sets the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @param authType the authentication type to set for the APN
+ */
+ public Builder setAuthType(@AuthType int authType) {
+ this.mAuthType = authType;
+ return this;
+ }
+
+ /**
+ * Sets the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @param types the list of APN types to set for the APN
+ */
+ public Builder setTypes(@ApnType List<String> types) {
+ this.mTypes = types;
+ int apnBitmap = 0;
+ for (int i = 0; i < mTypes.size(); i++) {
+ mTypes.set(i, mTypes.get(i).toLowerCase());
+ apnBitmap |= getApnBitmask(mTypes.get(i));
+ }
+ this.mTypesBitmap = apnBitmap;
+ return this;
+ }
+
+ /**
+ * Sets the unique database id for this entry.
+ *
+ * @param id the unique database id to set for this entry
+ */
+ public Builder setId(int id) {
+ this.mId = id;
+ return this;
+ }
+
+ /**
+ * Set the numeric operator ID for the APN.
+ *
+ * @param operatorNumeric the numeric operator ID to set for this entry
+ */
+ public Builder setOperatorNumeric(String operatorNumeric) {
+ this.mOperatorNumeric = operatorNumeric;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @param protocol the protocol to set to use to connect to this APN
+ */
+ public Builder setProtocol(@ProtocolType String protocol) {
+ this.mProtocol = protocol;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN when roaming.
+ *
+ * @param roamingProtocol the protocol to set to use to connect to this APN when roaming
+ */
+ public Builder setRoamingProtocol(String roamingProtocol) {
+ this.mRoamingProtocol = roamingProtocol;
+ return this;
+ }
+
+ /**
+ * Sets the current status of APN.
+ *
+ * @param carrierEnabled the current status to set for this APN
+ */
+ public Builder setCarrierEnabled(boolean carrierEnabled) {
+ this.mCarrierEnabled = carrierEnabled;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @param mvnoType the MVNO match type to set for this APN
+ */
+ public Builder setMvnoType(@MvnoType String mvnoType) {
+ this.mMvnoType = mvnoType;
+ return this;
+ }
+
+ public ApnSetting build() {
+ return new ApnSetting(this);
+ }
+ }
+}
+
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
new file mode 100644
index 0000000..29849c1
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.telephony.euicc;
+
+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.IEuiccCardController;
+import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+
+/**
+ * EuiccCardManager is the application interface to an eSIM card.
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a SystemApi.
+ */
+public class EuiccCardManager {
+ private static final String TAG = "EuiccCardManager";
+
+ /** Result code of execution with no error. */
+ public static final int RESULT_OK = 0;
+
+ /**
+ * Callback to receive the result of an eUICC card API.
+ *
+ * @param <T> Type of the result.
+ */
+ public interface ResultCallback<T> {
+ /**
+ * This method will be called when an eUICC card API call is completed.
+ *
+ * @param resultCode This can be {@link #RESULT_OK} or other positive values returned by the
+ * eUICC.
+ * @param result The result object. It can be null if the {@code resultCode} is not
+ * {@link #RESULT_OK}.
+ */
+ void onComplete(int resultCode, T result);
+ }
+
+ private final Context mContext;
+
+ /** @hide */
+ public EuiccCardManager(Context context) {
+ mContext = context;
+ }
+
+ private IEuiccCardController getIEuiccCardController() {
+ return IEuiccCardController.Stub.asInterface(
+ ServiceManager.getService("euicc_card_controller"));
+ }
+
+ /**
+ * Gets all the profiles on eUicc.
+ *
+ * @param callback the callback to get the result code and all the profiles.
+ */
+ public void getAllProfiles(ResultCallback<EuiccProfileInfo[]> callback) {
+ try {
+ getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(),
+ new IGetAllProfilesCallback.Stub() {
+ @Override
+ public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
+ callback.onComplete(resultCode, profiles);
+ }
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling getAllProfiles", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 84d0087..3dfadf5 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -15,8 +15,10 @@
*/
package android.telephony.euicc;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
@@ -29,6 +31,9 @@
import com.android.internal.telephony.euicc.IEuiccController;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs.
*
@@ -55,6 +60,20 @@
public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+
+ /**
+ * Broadcast Action: The eUICC OTA status is changed.
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ * TODO(b/35851809): Make this a SystemApi.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_OTA_STATUS_CHANGED
+ = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+
/**
* Intent action to provision an embedded subscription.
*
@@ -167,6 +186,35 @@
*/
public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
+ /**
+ * Euicc OTA update status which can be got by {@link #getOtaStatus}
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"EUICC_OTA_"}, value = {
+ EUICC_OTA_IN_PROGRESS,
+ EUICC_OTA_FAILED,
+ EUICC_OTA_SUCCEEDED,
+ EUICC_OTA_NOT_NEEDED,
+ EUICC_OTA_STATUS_UNAVAILABLE
+
+ })
+ public @interface OtaStatus{}
+
+ /**
+ * An OTA is in progress. During this time, the eUICC is not available and the user may lose
+ * network access.
+ */
+ public static final int EUICC_OTA_IN_PROGRESS = 1;
+ /** The OTA update failed. */
+ public static final int EUICC_OTA_FAILED = 2;
+ /** The OTA update finished successfully. */
+ public static final int EUICC_OTA_SUCCEEDED = 3;
+ /** The OTA update not needed since current eUICC OS is latest. */
+ public static final int EUICC_OTA_NOT_NEEDED = 4;
+ /** The OTA status is unavailable since eUICC service is unavailable. */
+ public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
+
private final Context mContext;
/** @hide */
@@ -211,6 +259,26 @@
}
/**
+ * Returns the current status of eUICC OTA.
+ *
+ * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+ *
+ * @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready,
+ * {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
+ */
+ @SystemApi
+ public int getOtaStatus() {
+ if (!isEnabled()) {
+ return EUICC_OTA_STATUS_UNAVAILABLE;
+ }
+ try {
+ return getIEuiccController().getOtaStatus();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Attempt to download the given {@link DownloadableSubscription}.
*
* <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 64083e3..b0af9a8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -870,14 +870,33 @@
*
* @param enable true to turn on, else false
*/
- void setDataEnabled(int subId, boolean enable);
+ void setUserDataEnabled(int subId, boolean enable);
+
+ /**
+ * Get the user enabled state of Mobile Data.
+ *
+ * TODO: remove and use isUserDataEnabled.
+ * This can't be removed now because some vendor codes
+ * calls through ITelephony directly while they should
+ * use TelephonyManager.
+ *
+ * @return true on enabled
+ */
+ boolean getDataEnabled(int subId);
/**
* Get the user enabled state of Mobile Data.
*
* @return true on enabled
*/
- boolean getDataEnabled(int subId);
+ boolean isUserDataEnabled(int subId);
+
+ /**
+ * Get the overall enabled state of Mobile Data.
+ *
+ * @return true on enabled
+ */
+ boolean isDataEnabled(int subId);
/**
* Get P-CSCF address from PCO after data connection is established or modified.
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index e2d25b8..f804cb0 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -417,6 +417,8 @@
int RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION = 141;
int RIL_REQUEST_START_NETWORK_SCAN = 142;
int RIL_REQUEST_STOP_NETWORK_SCAN = 143;
+ int RIL_REQUEST_GET_SLOT_STATUS = 144;
+ int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 145;
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -471,4 +473,5 @@
int RIL_UNSOL_MODEM_RESTART = 1047;
int RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION = 1048;
int RIL_UNSOL_NETWORK_SCAN_RESULT = 1049;
+ int RIL_UNSOL_ICC_SLOT_STATUS = 1050;
}
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
new file mode 100644
index 0000000..2846a1a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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 com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+
+/** @hide */
+interface IEuiccCardController {
+ oneway void getAllProfiles(String callingPackage, in IGetAllProfilesCallback callback);
+}
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index b3fc90d..0a0ad90 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -30,6 +30,7 @@
oneway void getDefaultDownloadableSubscriptionList(
String callingPackage, in PendingIntent callbackIntent);
String getEid();
+ int getOtaStatus();
oneway void downloadSubscription(in DownloadableSubscription subscription,
boolean switchAfterDownload, String callingPackage, in PendingIntent callbackIntent);
EuiccInfo getEuiccInfo();
diff --git a/telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl
new file mode 100644
index 0000000..97b0768
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.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.service.euicc.EuiccProfileInfo;
+
+/** @hide */
+oneway interface IGetAllProfilesCallback {
+ void onComplete(int resultCode, in EuiccProfileInfo[] profiles);
+}
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
index 088f322..6e0d58a 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
@@ -40,6 +40,6 @@
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
-LOCAL_NDK_STL_VARIANT := stlport_static
+LOCAL_NDK_STL_VARIANT := c++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/NetworkUtilsTest.java
rename to tests/net/java/android/net/NetworkUtilsTest.java
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/tests/net/java/android/net/RouteInfoTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/RouteInfoTest.java
rename to tests/net/java/android/net/RouteInfoTest.java
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 725ddb9..9b75a50 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -35,6 +35,7 @@
import android.net.ip.IpManager;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -62,7 +63,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
@@ -635,7 +635,7 @@
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
IpConnectivityLog log) throws Exception {
- super(config, NetworkInterface.getByName("lo"), ipManagerCallback, log);
+ super(config, InterfaceParams.getByName("lo"), ipManagerCallback, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
diff --git a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
index 54776db..e65585f 100644
--- a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
+++ b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;
+import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -54,8 +55,8 @@
}
IpReachabilityMonitor makeMonitor() {
- return new IpReachabilityMonitor(
- "fake0", 1, mHandler, mLog, mCallback, null, mDependencies);
+ final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
+ return new IpReachabilityMonitor(ifParams, mHandler, mLog, mCallback, null, mDependencies);
}
@Test
diff --git a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
index 38d3d74..f9b7ec8 100644
--- a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
+++ b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.net.MacAddress;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
@@ -36,9 +37,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectivityPacketSummaryTest {
- private static final byte[] MYHWADDR = {
- asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
- };
+ private static final MacAddress MYHWADDR = MacAddress.fromString("80:7a:bf:6f:48:f3");
private String getSummary(String hexBytes) {
hexBytes = hexBytes.replaceAll("\\s+", "");
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
new file mode 100644
index 0000000..21728af
--- /dev/null
+++ b/tests/net/java/android/net/util/InterfaceParamsTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package android.net.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InterfaceParamsTest {
+ @Test
+ public void testNullInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName(null));
+ }
+
+ @Test
+ public void testNonExistentInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName("doesnotexist0"));
+ }
+
+ @Test
+ public void testLoopback() {
+ final InterfaceParams ifParams = InterfaceParams.getByName("lo");
+ assertNotNull(ifParams);
+ assertEquals("lo", ifParams.name);
+ assertTrue(ifParams.index > 0);
+ assertNotNull(ifParams.macAddr);
+ assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 113cd37..2b0349c 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -55,14 +55,20 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -116,6 +122,7 @@
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -132,6 +139,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -174,8 +182,11 @@
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
+ private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
+
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
// reflect the state of our test ConnectivityService.
@@ -872,7 +883,7 @@
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
- mock(INetworkManagementService.class),
+ mNetworkManagementService,
mStatsService,
mock(INetworkPolicyManager.class),
mock(IpConnectivityLog.class));
@@ -3489,6 +3500,44 @@
reset(mStatsService);
}
+ @Test
+ public void testBasicDnsConfigurationPushed() throws Exception {
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
+ anyInt(), any(), any(), any(), anyBoolean(), anyString());
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName("test_rmnet_data0");
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ // CS tells netd about the empty DNS config for this network.
+ assertEmpty(mStringArrayCaptor.getValue());
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(1, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 80e42a3..2282c13 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -348,64 +348,6 @@
}
@Test
- public void testCreateInvalidConfigAeadWithAuth() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setAuthentication(direction, AUTH_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on authentication being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testCreateInvalidConfigAeadWithCrypt() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setEncryption(direction, CRYPT_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on encryption being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testCreateInvalidConfigAeadWithAuthAndCrypt() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setAuthentication(direction, AUTH_ALGO);
- ipSecConfig.setEncryption(direction, CRYPT_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on authentication and encryption being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
public void testDeleteTransportModeTransform() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 5d1e10e..0467989 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -35,6 +35,8 @@
import android.content.Context;
import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
@@ -76,6 +78,36 @@
private static final InetAddress INADDR_ANY;
+ private static final byte[] AEAD_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x73, 0x61, 0x6C, 0x74
+ };
+ private static final byte[] CRYPT_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ private static final byte[] AUTH_KEY = {
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
+ };
+
+ private static final IpSecAlgorithm AUTH_ALGO =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
+ private static final IpSecAlgorithm CRYPT_ALGO =
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
+ 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});
@@ -270,6 +302,127 @@
}
@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) {
+ }
+ }
+ }
+ }
+
+ @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) {
+ }
+ }
+ }
+ }
+
+ @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) {
+ }
+ }
+ }
+ }
+
+ @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);
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsNoAlgorithms() {
+ IpSecConfig config = new IpSecConfig();
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; no algorithms specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAeadWithAuth() {
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+ config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; both AEAD and auth algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAeadWithCrypt() {
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+ config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; both AEAD and crypt algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @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);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; AEAD, auth and crypt algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
public void testDeleteInvalidTransportModeTransform() throws Exception {
try {
mIpSecService.deleteTransportModeTransform(1);
diff --git a/tools/aapt2/filter/AbiFilter.h b/tools/aapt2/filter/AbiFilter.h
index d875cb2..2832711 100644
--- a/tools/aapt2/filter/AbiFilter.h
+++ b/tools/aapt2/filter/AbiFilter.h
@@ -33,6 +33,8 @@
*/
class AbiFilter : public IPathFilter {
public:
+ virtual ~AbiFilter() = default;
+
/** Factory method to create a filter from a list of configuration::Abi. */
static std::unique_ptr<AbiFilter> FromAbiList(const std::vector<configuration::Abi>& abi_list);
diff --git a/tools/aapt2/filter/Filter.h b/tools/aapt2/filter/Filter.h
index d737dc9..f932f9c 100644
--- a/tools/aapt2/filter/Filter.h
+++ b/tools/aapt2/filter/Filter.h
@@ -27,7 +27,7 @@
/** A filter to be applied to a path segment. */
class IPathFilter {
public:
- ~IPathFilter() = default;
+ virtual ~IPathFilter() = default;
/** Returns true if the path should be kept. */
virtual bool Keep(const std::string& path) = 0;
diff --git a/tools/sdkparcelables/Android.bp b/tools/sdkparcelables/Android.bp
new file mode 100644
index 0000000..00fb8aa
--- /dev/null
+++ b/tools/sdkparcelables/Android.bp
@@ -0,0 +1,22 @@
+java_binary_host {
+ name: "sdkparcelables",
+ manifest: "manifest.txt",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "asm-6.0",
+ ],
+}
+
+java_library_host {
+ name: "sdkparcelables_test",
+ manifest: "manifest.txt",
+ srcs: [
+ "tests/**/*.kt",
+ ],
+ static_libs: [
+ "sdkparcelables",
+ "junit",
+ ],
+}
diff --git a/tools/sdkparcelables/manifest.txt b/tools/sdkparcelables/manifest.txt
new file mode 100644
index 0000000..cd5420c
--- /dev/null
+++ b/tools/sdkparcelables/manifest.txt
@@ -0,0 +1 @@
+Main-class: com.android.sdkparcelables.MainKt
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt
new file mode 100644
index 0000000..f278aec
--- /dev/null
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt
@@ -0,0 +1,28 @@
+package com.android.sdkparcelables
+
+import org.objectweb.asm.ClassVisitor
+import java.util.*
+
+data class Ancestors(val superName: String?, val interfaces: List<String>?)
+
+/** A class that implements an ASM ClassVisitor that collects super class and
+ * implemented interfaces for each class that it visits.
+ */
+class AncestorCollector(api: Int, dest: ClassVisitor?) : ClassVisitor(api, dest) {
+ private val _ancestors = LinkedHashMap<String, Ancestors>()
+
+ val ancestors: Map<String, Ancestors>
+ get() = _ancestors
+
+ override fun visit(version: Int, access: Int, name: String?, signature: String?,
+ superName: String?, interfaces: Array<out String>?) {
+ name!!
+
+ val old = _ancestors.put(name, Ancestors(superName, interfaces?.toList()))
+ if (old != null) {
+ throw RuntimeException("class $name already found")
+ }
+
+ super.visit(version, access, name, signature, superName, interfaces)
+ }
+}
\ No newline at end of file
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
new file mode 100644
index 0000000..3e9d92c
--- /dev/null
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
@@ -0,0 +1,56 @@
+package com.android.sdkparcelables
+
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.Opcodes
+import java.io.File
+import java.io.IOException
+import java.util.zip.ZipFile
+
+fun main(args: Array<String>) {
+ if (args.size != 2) {
+ usage()
+ }
+
+ val zipFileName = args[0]
+ val aidlFileName = args[1]
+
+ val zipFile: ZipFile
+
+ try {
+ zipFile = ZipFile(zipFileName)
+ } catch (e: IOException) {
+ System.err.println("error reading input jar: ${e.message}")
+ kotlin.system.exitProcess(2)
+ }
+
+ val ancestorCollector = AncestorCollector(Opcodes.ASM6, null)
+
+ for (entry in zipFile.entries()) {
+ if (entry.name.endsWith(".class")) {
+ val reader = ClassReader(zipFile.getInputStream(entry))
+ reader.accept(ancestorCollector,
+ ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
+ }
+ }
+
+ val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorCollector.ancestors)
+
+ try {
+ val outFile = File(aidlFileName)
+ val outWriter = outFile.bufferedWriter()
+ for (parcelable in parcelables) {
+ outWriter.write("parcelable ")
+ outWriter.write(parcelable.replace('/', '.').replace('$', '.'))
+ outWriter.write(";\n")
+ }
+ outWriter.flush()
+ } catch (e: IOException) {
+ System.err.println("error writing output aidl: ${e.message}")
+ kotlin.system.exitProcess(2)
+ }
+}
+
+fun usage() {
+ System.err.println("Usage: <input jar> <output aidl>")
+ kotlin.system.exitProcess(1)
+}
\ No newline at end of file
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
new file mode 100644
index 0000000..620f798
--- /dev/null
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
@@ -0,0 +1,52 @@
+package com.android.sdkparcelables
+
+/** A class that uses an ancestor map to find all classes that
+ * implement android.os.Parcelable, including indirectly through
+ * super classes or super interfaces.
+ */
+class ParcelableDetector {
+ companion object {
+ fun ancestorsToParcelables(ancestors: Map<String, Ancestors>): List<String> {
+ val impl = Impl(ancestors)
+ impl.build()
+ return impl.parcelables
+ }
+ }
+
+ private class Impl(val ancestors: Map<String, Ancestors>) {
+ val isParcelableCache = HashMap<String, Boolean>()
+ val parcelables = ArrayList<String>()
+
+ fun build() {
+ val classList = ancestors.keys
+ classList.filterTo(parcelables, this::isParcelable)
+ parcelables.sort()
+ }
+
+ private fun isParcelable(c: String?): Boolean {
+ if (c == null) {
+ return false
+ }
+
+ if (c == "android/os/Parcelable") {
+ return true
+ }
+
+ val old = isParcelableCache[c]
+ if (old != null) {
+ return old
+ }
+
+ val cAncestors = ancestors[c] ?:
+ throw RuntimeException("class $c missing ancestor information")
+
+ val seq = (cAncestors.interfaces?.asSequence() ?: emptySequence()) +
+ cAncestors.superName
+
+ val ancestorIsParcelable = seq.any(this::isParcelable)
+
+ isParcelableCache[c] = ancestorIsParcelable
+ return ancestorIsParcelable
+ }
+ }
+}
diff --git a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
new file mode 100644
index 0000000..edfc825
--- /dev/null
+++ b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
@@ -0,0 +1,57 @@
+package com.android.sdkparcelables
+
+import junit.framework.TestCase.assertEquals
+import org.junit.Test
+
+class ParcelableDetectorTest {
+ @Test
+ fun `detect implements`() {
+ val ancestorMap = mapOf(
+ testAncestors("android/test/Parcelable",null, "android/os/Parcelable"),
+ testAncestors("android/os/Parcelable", null))
+
+ val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
+
+ assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+ }
+
+ @Test
+ fun `detect implements in reverse order`() {
+ val ancestorMap = mapOf(
+ testAncestors("android/os/Parcelable", null),
+ testAncestors("android/test/Parcelable",null, "android/os/Parcelable"))
+
+ val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
+
+ assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+ }
+
+ @Test
+ fun `detect super implements`() {
+ val ancestorMap = mapOf(
+ testAncestors("android/test/SuperParcelable",null, "android/os/Parcelable"),
+ testAncestors("android/test/Parcelable","android/test/SuperParcelable"),
+ testAncestors("android/os/Parcelable", null))
+
+ val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
+
+ assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable", "android/test/SuperParcelable"))
+ }
+
+ @Test
+ fun `detect super interface`() {
+ val ancestorMap = mapOf(
+ testAncestors("android/test/IParcelable",null, "android/os/Parcelable"),
+ testAncestors("android/test/Parcelable",null, "android/test/IParcelable"),
+ testAncestors("android/os/Parcelable", null))
+
+ val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
+
+ assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/IParcelable", "android/test/Parcelable"))
+ }
+
+}
+
+private fun testAncestors(name: String, superName: String?, vararg interfaces: String): Pair<String, Ancestors> {
+ return Pair(name, Ancestors(superName, interfaces.toList()))
+}