diff options
467 files changed, 25557 insertions, 8568 deletions
diff --git a/Android.bp b/Android.bp index 90dca0350a0c..670860bb2c51 100644 --- a/Android.bp +++ b/Android.bp @@ -34,6 +34,27 @@ filegroup { path: "core/java", } +// These are subset of framework-core-sources that are needed by the +// android.test.mock library. Ideally, the library should use public APIs only, +// but unfortunately its API signature has some references to these private APIs. +filegroup { + name: "framework-core-sources-for-test-mock", + srcs: [ + "core/java/android/app/IApplicationThread.aidl", + "core/java/android/app/IServiceConnection.aidl", + "core/java/android/content/IContentProvider.java", + "core/java/android/content/pm/IPackageDataObserver.aidl", + "core/java/android/content/pm/InstantAppInfo.java", + "core/java/android/content/pm/KeySet.java", + "core/java/android/content/pm/PackageManager.java", + "core/java/android/content/pm/VerifierDeviceIdentity.java", + "core/java/android/content/res/Resources.java", + "core/java/android/os/storage/VolumeInfo.java", + "core/java/android/view/DisplayAdjustments.java", + ], + path: "core/java", +} + filegroup { name: "framework-drm-sources", srcs: [ @@ -162,6 +183,23 @@ filegroup { } filegroup { + name: "framework-telephony-common-sources", + srcs: [ + "telephony/common/**/*.java", + ], + path: "telephony/common", +} + +filegroup { + name: "framework-mms-sources", + srcs: [ + "mms/java/**/*.java", + "mms/java/**/*.aidl", + ], + path: "mms/java", +} + +filegroup { name: "framework-wifi-sources", srcs: [ "wifi/java/**/*.java", @@ -185,10 +223,12 @@ filegroup { ":framework-mca-filterfw-sources", ":framework-mca-filterpacks-sources", ":framework-mime-sources", + ":framework-mms-sources", ":framework-opengl-sources", ":framework-rs-sources", ":framework-sax-sources", ":framework-telecomm-sources", + ":framework-telephony-common-sources", ":framework-telephony-sources", ":framework-wifi-sources", ":PacProcessor-aidl-sources", @@ -246,6 +286,7 @@ java_defaults { "media/mca/effect/java", "media/mca/filterfw/java", "media/mca/filterpacks/java", + "mms/java", "opengl/java", "rs/java", "sax/java", @@ -377,6 +418,7 @@ java_library { name: "framework-minus-apex", defaults: ["framework-defaults"], srcs: [":framework-non-updatable-sources"], + libs: ["app-compat-annotations"], installable: true, javac_shard_size: 150, required: [ @@ -413,12 +455,14 @@ java_library { defaults: ["framework-defaults"], srcs: [":framework-all-sources"], installable: false, + libs: ["app-compat-annotations"], } java_library { name: "framework-annotation-proc", defaults: ["framework-defaults"], srcs: [":framework-all-sources"], + libs: ["app-compat-annotations"], installable: false, plugins: [ "unsupportedappusage-annotation-processor", @@ -459,6 +503,7 @@ java_library { java_library { name: "framework-atb-backward-compatibility", installable: true, + libs: ["app-compat-annotations"], srcs: [ "core/java/android/content/pm/AndroidTestBaseUpdater.java", ], @@ -475,24 +520,22 @@ gensrcs { name: "framework-javastream-protos", depfile: true, - tool_files: ["tools/genprotos.sh"], tools: [ "aprotoc", "protoc-gen-javastream", "soong_zip", ], - // TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can - // end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to - // the way sbox rewrites the command. See b/70221552. - cmd: "$(location tools/genprotos.sh) " + - " $(location aprotoc) " + - " $(location protoc-gen-javastream) " + - " $(location soong_zip) " + - " $(genDir) " + - " $(depfile) " + - " $(in) " + - " $(out)", + cmd: "mkdir -p $(genDir)/$(in) " + + "&& $(location aprotoc) " + + " --plugin=$(location protoc-gen-javastream) " + + " --dependency_out=$(depfile) " + + " --javastream_out=$(genDir)/$(in) " + + " -Iexternal/protobuf/src " + + " -I . " + + " $(in) " + + "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)", + srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", @@ -820,26 +863,6 @@ python_binary_host { ], } -// TODO: Don't rely on this list by switching package.html into package-info.java -frameworks_base_subdirs = [ - "core/java", - "graphics/java", - "location/java", - "media/java", - "media/mca/effect/java", - "media/mca/filterfw/java", - "media/mca/filterpacks/java", - "drm/java", - "opengl/java", - "sax/java", - "telecomm/java", - "telephony/java", - "wifi/java", - "lowpan/java", - "keystore/java", - "rs/java", -] - // Make the api/current.txt file available for use by modules in other // directories. filegroup { @@ -915,29 +938,14 @@ framework_docs_only_libs = [ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " + "--ignore-classes-on-classpath " + - "--hide-package com.android.okhttp " + - "--hide-package com.android.org.conscrypt --hide-package com.android.server " + + "--hide-package com.android.server " + "--error UnhiddenSystemApi " + "--hide RequiresPermission " + + "--hide CallbackInterface " + "--hide MissingPermission --hide BroadcastBehavior " + "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " + "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " -// http://b/129765390 Rewrite links to "platform" or "technotes" folders -// which are siblings (and thus outside of) {@docRoot}. -// -// We have to escape \ as \\ and $ as $$ here because they get resolved by -// different layers of the build tooling. The arguments are wrapped in '' so -// that the shell doesn't add yet another level of escaping. -metalava_framework_docs_args += " --replace-documentation " + - // packages whose descendants to apply replacement to (all packages from - // libcore/ojluni/src/main/java that contribute to documentation). - "com.sun:java:javax:jdk.net:sun " + - // regex of the string to replace - "'(<a\\s+href\\s?=[\\*\\s]*\")(?:(?:\\{@docRoot\\}/\\.\\./)|(?:(?:\\.\\./)+))((?:platform|technotes).+)\">' " + - // replacement (with $1, $2 backreferences to the regex groups) - "'$$1https://docs.oracle.com/javase/8/docs/$$2\">' " - packages_to_document = [ "android", "dalvik", @@ -966,7 +974,6 @@ stubs_defaults { "test-runner/src/**/*.java", ], libs: framework_docs_only_libs, - local_sourcepaths: frameworks_base_subdirs, create_doc_stubs: true, annotations_enabled: true, api_levels_annotations_enabled: true, @@ -977,7 +984,6 @@ stubs_defaults { previous_api: ":last-released-public-api", merge_annotations_dirs: [ "metalava-manual", - "ojluni-annotated-sdk-stubs", ], } @@ -1028,13 +1034,11 @@ stubs_defaults { ":updatable-media-srcs", ], libs: ["framework-internal-utils"], - local_sourcepaths: frameworks_base_subdirs, installable: false, annotations_enabled: true, previous_api: ":last-released-public-api", merge_annotations_dirs: [ "metalava-manual", - "ojluni-annotated-sdk-stubs", ], api_levels_annotations_enabled: true, api_levels_annotations_dirs: [ @@ -1369,7 +1373,6 @@ droidstubs { previous_api: ":last-released-public-api", merge_annotations_dirs: [ "metalava-manual", - "ojluni-annotated-sdk-stubs", ], args: " --show-annotation android.annotation.SystemApi", } @@ -1401,8 +1404,6 @@ droidstubs { name: "hiddenapi-mappings", defaults: ["metalava-api-stubs-default"], srcs: [ - ":non_openjdk_java_files", - ":openjdk_java_files", ":opt-telephony-common-srcs", ], @@ -1493,6 +1494,10 @@ droidstubs { api_file: "api/test-current.txt", removed_api_file: "api/test-removed.txt", }, + api_lint: { + enabled: true, + baseline_file: "api/test-lint-baseline.txt", + }, }, } diff --git a/CleanSpec.mk b/CleanSpec.mk index 6a909c0364e9..f7a285835126 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -254,6 +254,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DynamicAndroidInsta $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DefaultContainerService) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms) # ****************************************************************** # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER # ****************************************************************** diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index e731138ff40d..68311176a783 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,8 +1,6 @@ [Hook Scripts] checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} -api_lint_hook = ${REPO_ROOT}/frameworks/base/tools/apilint/apilint_sha.sh ${PREUPLOAD_COMMIT} - strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT} hidden_api_txt_checksorted_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT} diff --git a/api/current.txt b/api/current.txt index 8b06719dfad5..4ba4fbee7b15 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2023,7 +2023,7 @@ package android { field public static final int fingerprint_icon_content_description = 17039384; // 0x1040018 field public static final int httpErrorBadUrl = 17039367; // 0x1040007 field public static final int httpErrorUnsupportedScheme = 17039368; // 0x1040008 - field public static final int no = 17039369; // 0x1040009 + field @Deprecated public static final int no = 17039369; // 0x1040009 field public static final int ok = 17039370; // 0x104000a field public static final int paste = 17039371; // 0x104000b field public static final int paste_as_plain_text = 17039385; // 0x1040019 @@ -2033,7 +2033,7 @@ package android { field public static final int status_bar_notification_info_overflow = 17039383; // 0x1040017 field public static final int unknownName = 17039374; // 0x104000e field public static final int untitled = 17039375; // 0x104000f - field public static final int yes = 17039379; // 0x1040013 + field @Deprecated public static final int yes = 17039379; // 0x1040013 } public static final class R.style { @@ -2815,7 +2815,7 @@ package android.accessibilityservice { method public final boolean dispatchGesture(@NonNull android.accessibilityservice.GestureDescription, @Nullable android.accessibilityservice.AccessibilityService.GestureResultCallback, @Nullable android.os.Handler); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method @NonNull public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController(); - method @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) @NonNull public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController(); + method @NonNull @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController(); method @NonNull public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController(); method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); @@ -3021,9 +3021,9 @@ package android.accounts { field public final String type; } - public class AccountAuthenticatorActivity extends android.app.Activity { - ctor public AccountAuthenticatorActivity(); - method public final void setAccountAuthenticatorResult(android.os.Bundle); + @Deprecated public class AccountAuthenticatorActivity extends android.app.Activity { + ctor @Deprecated public AccountAuthenticatorActivity(); + method @Deprecated public final void setAccountAuthenticatorResult(android.os.Bundle); } public class AccountAuthenticatorResponse implements android.os.Parcelable { @@ -3524,11 +3524,11 @@ package android.animation { package android.annotation { - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressLint { method public abstract String[] value(); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface TargetApi { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) public @interface TargetApi { method public abstract int value(); } @@ -3741,7 +3741,7 @@ package android.app { method public void onContentChanged(); method public boolean onContextItemSelected(@NonNull android.view.MenuItem); method public void onContextMenuClosed(@NonNull android.view.Menu); - method @MainThread @CallSuper protected void onCreate(@Nullable android.os.Bundle); + method @CallSuper @MainThread protected void onCreate(@Nullable android.os.Bundle); method public void onCreate(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle); method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo); method @Nullable public CharSequence onCreateDescription(); @@ -3883,8 +3883,8 @@ package android.app { method public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int); method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); - method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int); - method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int, @Nullable android.os.Bundle); + method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int); + method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle); method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; @@ -3892,8 +3892,8 @@ package android.app { method public void startLocalVoiceInteraction(android.os.Bundle); method public void startLockTask(); method @Deprecated public void startManagingCursor(android.database.Cursor); - method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent); - method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent, @Nullable android.os.Bundle); + method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent); + method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent, @Nullable android.os.Bundle); method public void startPostponedEnterTransition(); method public void startSearch(@Nullable String, boolean, @Nullable android.os.Bundle, boolean); method public void stopLocalVoiceInteraction(); @@ -4244,8 +4244,8 @@ package android.app { method public android.app.AlertDialog show(); } - public class AliasActivity extends android.app.Activity { - ctor public AliasActivity(); + @Deprecated public class AliasActivity extends android.app.Activity { + ctor @Deprecated public AliasActivity(); } public class AppComponentFactory { @@ -6642,7 +6642,7 @@ package android.app.admin { method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName); method @Nullable public java.util.Set<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName); method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName); - method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String); + method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String); method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName); method public boolean getAutoTimeRequired(); method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName); @@ -7562,7 +7562,7 @@ package android.app.slice { method public int checkSlicePermission(@NonNull android.net.Uri, int, int); method @NonNull public java.util.List<android.net.Uri> getPinnedSlices(); method @NonNull public java.util.Set<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); - method @WorkerThread @NonNull public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri); + method @NonNull @WorkerThread public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri); method public void grantSlicePermission(@NonNull String, @NonNull android.net.Uri); method @Nullable public android.net.Uri mapIntentToUri(@NonNull android.content.Intent); method public void pinSlice(@NonNull android.net.Uri, @NonNull java.util.Set<android.app.slice.SliceSpec>); @@ -7718,10 +7718,10 @@ package android.app.usage { public class StorageStatsManager { method @WorkerThread public long getFreeBytes(@NonNull java.util.UUID) throws java.io.IOException; method @WorkerThread public long getTotalBytes(@NonNull java.util.UUID) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException; - method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException; + method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException; } public final class UsageEvents implements android.os.Parcelable { @@ -7980,9 +7980,9 @@ package android.bluetooth { method public boolean isMultipleAdvertisementSupported(); method public boolean isOffloadedFilteringSupported(); method public boolean isOffloadedScanBatchingSupported(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery(); @@ -8350,13 +8350,14 @@ package android.bluetooth { method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int); method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; method public int describeContents(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp(); method public String getAddress(); + method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getAlias(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothClass getBluetoothClass(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBondState(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getName(); @@ -8368,6 +8369,7 @@ package android.bluetooth { field public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED"; field public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED"; field public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"; + field public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.action.ALIAS_CHANGED"; field public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED"; field public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED"; field public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND"; @@ -9517,14 +9519,14 @@ package android.content { method public static void addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long); method public static Object addStatusChangeListener(int, android.content.SyncStatusObserver); method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException; - method public final int bulkInsert(@RequiresPermission.Write @NonNull android.net.Uri, @NonNull android.content.ContentValues[]); + method public final int bulkInsert(@NonNull @RequiresPermission.Write android.net.Uri, @NonNull android.content.ContentValues[]); method @Nullable public final android.os.Bundle call(@NonNull android.net.Uri, @NonNull String, @Nullable String, @Nullable android.os.Bundle); method @Nullable public final android.os.Bundle call(@NonNull String, @NonNull String, @Nullable String, @Nullable android.os.Bundle); method @Deprecated public void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, String); method public static void cancelSync(android.content.SyncRequest); method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri); - method public final int delete(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable String, @Nullable String[]); + method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]); method @Deprecated public static android.content.SyncInfo getCurrentSync(); method public static java.util.List<android.content.SyncInfo> getCurrentSyncs(); method public static int getIsSyncable(android.accounts.Account, String); @@ -9537,7 +9539,7 @@ package android.content { method public static boolean getSyncAutomatically(android.accounts.Account, String); method @Nullable public final String getType(@NonNull android.net.Uri); method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String); - method @Nullable public final android.net.Uri insert(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues); + method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues); method public static boolean isSyncActive(android.accounts.Account, String); method public static boolean isSyncPending(android.accounts.Account, String); method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException; @@ -9556,9 +9558,9 @@ package android.content { method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException; method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle) throws java.io.FileNotFoundException; method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException; - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String); - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal); - method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal); + method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); method public final boolean refresh(@NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal); method public final void registerContentObserver(@NonNull android.net.Uri, boolean, @NonNull android.database.ContentObserver); method public void releasePersistableUriPermission(@NonNull android.net.Uri, int); @@ -9573,7 +9575,7 @@ package android.content { method public void takePersistableUriPermission(@NonNull android.net.Uri, int); method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri); method public final void unregisterContentObserver(@NonNull android.database.ContentObserver); - method public final int update(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]); + method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]); method public static void validateSyncExtrasBundle(android.os.Bundle); method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider); method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient); @@ -9669,9 +9671,9 @@ package android.content { public abstract class Context { ctor public Context(); - method public boolean bindIsolatedService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); + method public boolean bindIsolatedService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); method public abstract boolean bindService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int); - method public boolean bindService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); + method public boolean bindService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection); method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String); method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int); method @CheckResult(suggest="#enforceCallingPermission(String,String)") public abstract int checkCallingPermission(@NonNull String); @@ -9768,7 +9770,8 @@ package android.content { method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String); method public abstract void sendOrderedBroadcast(@RequiresPermission android.content.Intent, @Nullable String); - method public abstract void sendOrderedBroadcast(@RequiresPermission @NonNull android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public abstract void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendOrderedBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission android.content.Intent); method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void sendStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); @@ -11621,7 +11624,7 @@ package android.content.pm { method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle, @Nullable android.graphics.Rect, int); method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedIcon(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle); method @NonNull public abstract CharSequence getUserBadgedLabel(@NonNull CharSequence, @NonNull android.os.UserHandle); - method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int); + method @NonNull @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int); method @Nullable public abstract android.content.res.XmlResourceParser getXml(@NonNull String, @XmlRes int, @Nullable android.content.pm.ApplicationInfo); method public boolean hasSigningCertificate(@NonNull String, @NonNull byte[], int); method public boolean hasSigningCertificate(int, @NonNull byte[], int); @@ -12312,7 +12315,7 @@ package android.content.res { ctor @Deprecated public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); method public final void finishPreloading(); method public final void flushLayoutCache(); - method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimatorRes @AnimRes int) throws android.content.res.Resources.NotFoundException; + method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimRes @AnimatorRes int) throws android.content.res.Resources.NotFoundException; method public final android.content.res.AssetManager getAssets(); method @AnyRes public static int getAttributeSetSourceResId(@Nullable android.util.AttributeSet); method public boolean getBoolean(@BoolRes int) throws android.content.res.Resources.NotFoundException; @@ -13582,10 +13585,10 @@ package android.graphics { method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean); method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); - method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, @NonNull android.graphics.Bitmap.Config); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture, int, int, @NonNull android.graphics.Bitmap.Config); method public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean); @@ -13816,8 +13819,8 @@ package android.graphics { method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, float, float, @NonNull android.graphics.RectF, float, float, @NonNull android.graphics.Paint); method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.Paint); method public void drawLine(float, float, float, float, @NonNull android.graphics.Paint); - method public void drawLines(@Size(multiple=4) @NonNull float[], int, int, @NonNull android.graphics.Paint); - method public void drawLines(@Size(multiple=4) @NonNull float[], @NonNull android.graphics.Paint); + method public void drawLines(@NonNull @Size(multiple=4) float[], int, int, @NonNull android.graphics.Paint); + method public void drawLines(@NonNull @Size(multiple=4) float[], @NonNull android.graphics.Paint); method public void drawOval(@NonNull android.graphics.RectF, @NonNull android.graphics.Paint); method public void drawOval(float, float, float, float, @NonNull android.graphics.Paint); method public void drawPaint(@NonNull android.graphics.Paint); @@ -13827,7 +13830,7 @@ package android.graphics { method public void drawPicture(@NonNull android.graphics.Picture, @NonNull android.graphics.Rect); method public void drawPoint(float, float, @NonNull android.graphics.Paint); method public void drawPoints(@Size(multiple=2) float[], int, int, @NonNull android.graphics.Paint); - method public void drawPoints(@Size(multiple=2) @NonNull float[], @NonNull android.graphics.Paint); + method public void drawPoints(@NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method @Deprecated public void drawPosText(@NonNull char[], int, int, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method @Deprecated public void drawPosText(@NonNull String, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint); method public void drawRGB(int, int, int); @@ -14188,10 +14191,10 @@ package android.graphics { method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.nio.ByteBuffer); method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.io.File); method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.util.concurrent.Callable<android.content.res.AssetFileDescriptor>); - method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; - method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException; method public int getAllocator(); method @Nullable public android.graphics.Rect getCrop(); method public int getMemorySizePolicy(); @@ -14210,7 +14213,7 @@ package android.graphics { method public void setPostProcessor(@Nullable android.graphics.PostProcessor); method public void setTargetColorSpace(android.graphics.ColorSpace); method public void setTargetSampleSize(@IntRange(from=1) int); - method public void setTargetSize(@Px @IntRange(from=1) int, @Px @IntRange(from=1) int); + method public void setTargetSize(@IntRange(from=1) @Px int, @IntRange(from=1) @Px int); method public void setUnpremultipliedRequired(boolean); field public static final int ALLOCATOR_DEFAULT = 0; // 0x0 field public static final int ALLOCATOR_HARDWARE = 3; // 0x3 @@ -14317,8 +14320,8 @@ package android.graphics { } public class LinearGradient extends android.graphics.Shader { - ctor public LinearGradient(float, float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); - ctor public LinearGradient(float, float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public LinearGradient(float, float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public LinearGradient(float, float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } @@ -14860,8 +14863,8 @@ package android.graphics { } public class RadialGradient extends android.graphics.Shader { - ctor public RadialGradient(float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); - ctor public RadialGradient(float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); + ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } @@ -15119,8 +15122,8 @@ package android.graphics { } public class SweepGradient extends android.graphics.Shader { - ctor public SweepGradient(float, float, @NonNull @ColorInt int[], @Nullable float[]); - ctor public SweepGradient(float, float, @NonNull @ColorLong long[], @Nullable float[]); + ctor public SweepGradient(float, float, @ColorInt @NonNull int[], @Nullable float[]); + ctor public SweepGradient(float, float, @ColorLong @NonNull long[], @Nullable float[]); ctor public SweepGradient(float, float, @ColorInt int, @ColorInt int); ctor public SweepGradient(float, float, @ColorLong long, @ColorLong long); } @@ -15513,8 +15516,8 @@ package android.graphics.drawable { method public void setColor(@ColorInt int); method public void setColor(@Nullable android.content.res.ColorStateList); method public void setColorFilter(@Nullable android.graphics.ColorFilter); - method public void setColors(@Nullable @ColorInt int[]); - method public void setColors(@Nullable @ColorInt int[], @Nullable float[]); + method public void setColors(@ColorInt @Nullable int[]); + method public void setColors(@ColorInt @Nullable int[], @Nullable float[]); method public void setCornerRadii(@Nullable float[]); method public void setCornerRadius(float); method public void setDither(boolean); @@ -15962,14 +15965,14 @@ package android.graphics.text { public static class LineBreaker.ParagraphConstraints { ctor public LineBreaker.ParagraphConstraints(); - method @Px @FloatRange(from=0) public float getDefaultTabStop(); - method @Px @FloatRange(from=0.0f) public float getFirstWidth(); - method @Px @IntRange(from=0) public int getFirstWidthLineCount(); + method @FloatRange(from=0) @Px public float getDefaultTabStop(); + method @FloatRange(from=0.0f) @Px public float getFirstWidth(); + method @IntRange(from=0) @Px public int getFirstWidthLineCount(); method @Nullable public float[] getTabStops(); - method @Px @FloatRange(from=0.0f) public float getWidth(); - method public void setIndent(@Px @FloatRange(from=0.0f) float, @Px @IntRange(from=0) int); - method public void setTabStops(@Nullable float[], @Px @FloatRange(from=0) float); - method public void setWidth(@Px @FloatRange(from=0.0f) float); + method @FloatRange(from=0.0f) @Px public float getWidth(); + method public void setIndent(@FloatRange(from=0.0f) @Px float, @IntRange(from=0) @Px int); + method public void setTabStops(@Nullable float[], @FloatRange(from=0) @Px float); + method public void setWidth(@FloatRange(from=0.0f) @Px float); } public static class LineBreaker.Result { @@ -15992,7 +15995,7 @@ package android.graphics.text { public static final class MeasuredText.Builder { ctor public MeasuredText.Builder(@NonNull char[]); ctor public MeasuredText.Builder(@NonNull android.graphics.text.MeasuredText); - method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @Px @FloatRange(from=0) float); + method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float); method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean); method @NonNull public android.graphics.text.MeasuredText build(); method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean); @@ -23003,7 +23006,7 @@ package android.location { method @Nullable public String getGnssHardwareModelName(); method public int getGnssYearOfHardware(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus); - method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) @Nullable public android.location.Location getLastKnownLocation(@NonNull String); + method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String); method @Nullable public android.location.LocationProvider getProvider(@NonNull String); method @NonNull public java.util.List<java.lang.String> getProviders(boolean); method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean); @@ -28457,17 +28460,17 @@ package android.net { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public boolean bindProcessToNetwork(@Nullable android.net.Network); method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.Network getActiveNetwork(); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @NonNull public android.net.Network[] getAllNetworks(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks(); method @Deprecated public boolean getBackgroundDataSetting(); method @Nullable public android.net.Network getBoundNetworkForProcess(); method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); method @Nullable public android.net.ProxyInfo getDefaultProxy(); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network); method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference(); @@ -29366,7 +29369,8 @@ package android.net.rtp { } public class AudioGroup { - ctor public AudioGroup(); + ctor @Deprecated public AudioGroup(); + ctor public AudioGroup(@Nullable android.content.Context); method public void clear(); method public int getMode(); method public android.net.rtp.AudioStream[] getStreams(); @@ -30773,10 +30777,10 @@ package android.nfc.cardemulation { method public boolean isDefaultServiceForCategory(android.content.ComponentName, String); method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>); method public boolean removeAidsForService(android.content.ComponentName, String); - method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); + method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); method public boolean supportsAidPrefixRegistration(); - method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean unsetOffHostForService(@NonNull android.content.ComponentName); + method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName); method public boolean unsetPreferredService(android.app.Activity); field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final String CATEGORY_OTHER = "other"; @@ -33982,31 +33986,31 @@ package android.opengl { package android.os { - public abstract class AsyncTask<Params, Progress, Result> { - ctor public AsyncTask(); - method public final boolean cancel(boolean); - method @WorkerThread protected abstract Result doInBackground(Params...); - method @MainThread public final android.os.AsyncTask<Params,Progress,Result> execute(Params...); - method @MainThread public static void execute(Runnable); - method @MainThread public final android.os.AsyncTask<Params,Progress,Result> executeOnExecutor(java.util.concurrent.Executor, Params...); - method public final Result get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; - method public final Result get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; - method public final android.os.AsyncTask.Status getStatus(); - method public final boolean isCancelled(); - method @MainThread protected void onCancelled(Result); - method @MainThread protected void onCancelled(); - method @MainThread protected void onPostExecute(Result); - method @MainThread protected void onPreExecute(); - method @MainThread protected void onProgressUpdate(Progress...); - method @WorkerThread protected final void publishProgress(Progress...); - field public static final java.util.concurrent.Executor SERIAL_EXECUTOR; - field public static final java.util.concurrent.Executor THREAD_POOL_EXECUTOR; - } - - public enum AsyncTask.Status { - enum_constant public static final android.os.AsyncTask.Status FINISHED; - enum_constant public static final android.os.AsyncTask.Status PENDING; - enum_constant public static final android.os.AsyncTask.Status RUNNING; + @Deprecated public abstract class AsyncTask<Params, Progress, Result> { + ctor @Deprecated public AsyncTask(); + method @Deprecated public final boolean cancel(boolean); + method @Deprecated @WorkerThread protected abstract Result doInBackground(Params...); + method @Deprecated @MainThread public final android.os.AsyncTask<Params,Progress,Result> execute(Params...); + method @Deprecated @MainThread public static void execute(Runnable); + method @Deprecated @MainThread public final android.os.AsyncTask<Params,Progress,Result> executeOnExecutor(java.util.concurrent.Executor, Params...); + method @Deprecated public final Result get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; + method @Deprecated public final Result get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method @Deprecated public final android.os.AsyncTask.Status getStatus(); + method @Deprecated public final boolean isCancelled(); + method @Deprecated @MainThread protected void onCancelled(Result); + method @Deprecated @MainThread protected void onCancelled(); + method @Deprecated @MainThread protected void onPostExecute(Result); + method @Deprecated @MainThread protected void onPreExecute(); + method @Deprecated @MainThread protected void onProgressUpdate(Progress...); + method @Deprecated @WorkerThread protected final void publishProgress(Progress...); + field @Deprecated public static final java.util.concurrent.Executor SERIAL_EXECUTOR; + field @Deprecated public static final java.util.concurrent.Executor THREAD_POOL_EXECUTOR; + } + + @Deprecated public enum AsyncTask.Status { + enum_constant @Deprecated public static final android.os.AsyncTask.Status FINISHED; + enum_constant @Deprecated public static final android.os.AsyncTask.Status PENDING; + enum_constant @Deprecated public static final android.os.AsyncTask.Status RUNNING; } public class BadParcelableException extends android.util.AndroidRuntimeException { @@ -34431,7 +34435,7 @@ package android.os { method public void addData(String, byte[], int); method public void addFile(String, java.io.File, int) throws java.io.IOException; method public void addText(String, String); - method @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.DropBoxManager.Entry getNextEntry(String, long); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.DropBoxManager.Entry getNextEntry(String, long); method public boolean isTagEnabled(String); field public static final String ACTION_DROPBOX_ENTRY_ADDED = "android.intent.action.DROPBOX_ENTRY_ADDED"; field public static final String EXTRA_DROPPED_COUNT = "android.os.extra.DROPPED_COUNT"; @@ -34544,8 +34548,8 @@ package android.os { } public class Handler { - ctor public Handler(); - ctor public Handler(@Nullable android.os.Handler.Callback); + ctor @Deprecated public Handler(); + ctor @Deprecated public Handler(@Nullable android.os.Handler.Callback); ctor public Handler(@NonNull android.os.Looper); ctor public Handler(@NonNull android.os.Looper, @Nullable android.os.Handler.Callback); method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper); @@ -36909,6 +36913,7 @@ package android.provider { field public static final String DURATION = "duration"; field public static final String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final String FEATURES = "features"; + field public static final int FEATURES_ASSISTED_DIALING_USED = 16; // 0x10 field public static final int FEATURES_HD_CALL = 4; // 0x4 field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_RTT = 32; // 0x20 @@ -42666,6 +42671,7 @@ package android.system { field public static final int IP_MULTICAST_TTL; field public static final int IP_TOS; field public static final int IP_TTL; + field public static final int MAP_ANONYMOUS; field public static final int MAP_FIXED; field public static final int MAP_PRIVATE; field public static final int MAP_SHARED; @@ -43133,6 +43139,7 @@ package android.telecom { field public static final int DIRECTION_INCOMING = 0; // 0x0 field public static final int DIRECTION_OUTGOING = 1; // 0x1 field public static final int DIRECTION_UNKNOWN = -1; // 0xffffffff + field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200 field public static final int PROPERTY_CONFERENCE = 1; // 0x1 field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20 @@ -43246,6 +43253,7 @@ package android.telecom { method public final void removeConnection(android.telecom.Connection); method public final void removeExtras(java.util.List<java.lang.String>); method public final void removeExtras(java.lang.String...); + method public void sendConferenceEvent(@NonNull String, @Nullable android.os.Bundle); method public final void setActive(); method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final void setConnectionCapabilities(int); @@ -43385,6 +43393,7 @@ package android.telecom { field public static final String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT"; field public static final String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; field public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE"; + field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4 field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 @@ -43511,6 +43520,7 @@ package android.telecom { field public static final int LOCAL = 2; // 0x2 field public static final int MISSED = 5; // 0x5 field public static final int OTHER = 9; // 0x9 + field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; field public static final int REJECTED = 6; // 0x6 field public static final int REMOTE = 3; // 0x3 field public static final int RESTRICTED = 8; // 0x8 @@ -43799,8 +43809,9 @@ package android.telecom { method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts(); method public android.telecom.PhoneAccountHandle getSimCallManager(); + method @Nullable public android.telecom.PhoneAccountHandle getSimCallManagerForSubscription(int); method @Nullable public String getSystemDialerPackage(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle); @@ -43847,6 +43858,7 @@ package android.telecom { field public static final String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT"; field public static final String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE"; field public static final String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; + field public static final String EXTRA_USE_ASSISTED_DIALING = "android.telecom.extra.USE_ASSISTED_DIALING"; field public static final String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; field public static final String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; @@ -44029,11 +44041,15 @@ package android.telephony { field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; + field public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrp_thresholds_int_array"; + field public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrq_thresholds_int_array"; + field public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = "5g_nr_sssinr_thresholds_int_array"; field public static final String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; field public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; field public static final String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool"; + field public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = "allow_hold_call_during_emergency_bool"; field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool"; field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool"; field public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; @@ -44050,7 +44066,7 @@ package android.telephony { field public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings"; field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT = "carrier_default_wfc_ims_mode_int"; field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT = "carrier_default_wfc_ims_roaming_mode_int"; - field public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; + field @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; field public static final String KEY_CARRIER_IMS_GBA_REQUIRED_BOOL = "carrier_ims_gba_required_bool"; field public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL = "carrier_instant_lettering_available_bool"; field public static final String KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING = "carrier_instant_lettering_encoding_string"; @@ -44160,6 +44176,7 @@ package android.telephony { field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int"; field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int"; field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int"; + field public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT = "parameters_use_for_5g_nr_signal_bar_int"; field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool"; field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool"; field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array"; @@ -44295,6 +44312,8 @@ package android.telephony { public abstract class CellInfo implements android.os.Parcelable { method public int describeContents(); method public int getCellConnectionStatus(); + method @NonNull public abstract android.telephony.CellIdentity getCellIdentity(); + method @NonNull public abstract android.telephony.CellSignalStrength getCellSignalStrength(); method public long getTimeStamp(); method public boolean isRegistered(); field public static final int CONNECTION_NONE = 0; // 0x0 @@ -44439,6 +44458,7 @@ package android.telephony { method public int describeContents(); method public int getAsuLevel(); method public int getDbm(); + method public int getEcNo(); method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR; @@ -44726,6 +44746,7 @@ package android.telephony { method public static int getDefaultSmsSubscriptionId(); method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback); + method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress(); method public int getSubscriptionId(); method public void injectSmsPdu(byte[], String, android.app.PendingIntent); method public void sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); @@ -44733,6 +44754,7 @@ package android.telephony { method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>); method public void sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.SEND_SMS}) public void sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSmscAddress(@NonNull String); field public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; field public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; field public static final String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; @@ -44774,13 +44796,60 @@ package android.telephony { field public static final int MMS_ERROR_RETRY = 6; // 0x6 field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 + field public static final int RESULT_BLUETOOTH_DISCONNECTED = 27; // 0x1b + field public static final int RESULT_CANCELLED = 23; // 0x17 + field public static final int RESULT_ENCODING_ERROR = 18; // 0x12 + field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; // 0x6 field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 field public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; // 0x5 + field public static final int RESULT_ERROR_NONE = 0; // 0x0 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2 field public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; // 0x8 field public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; // 0x7 + field public static final int RESULT_INTERNAL_ERROR = 21; // 0x15 + field public static final int RESULT_INVALID_ARGUMENTS = 11; // 0xb + field public static final int RESULT_INVALID_BLUETOOTH_ADDRESS = 26; // 0x1a + field public static final int RESULT_INVALID_SMSC_ADDRESS = 19; // 0x13 + field public static final int RESULT_INVALID_SMS_FORMAT = 14; // 0xe + field public static final int RESULT_INVALID_STATE = 12; // 0xc + field public static final int RESULT_MODEM_ERROR = 16; // 0x10 + field public static final int RESULT_NETWORK_ERROR = 17; // 0x11 + field public static final int RESULT_NETWORK_REJECT = 10; // 0xa + field public static final int RESULT_NO_BLUETOOTH_SERVICE = 25; // 0x19 + field public static final int RESULT_NO_DEFAULT_SMS_APP = 32; // 0x20 + field public static final int RESULT_NO_MEMORY = 13; // 0xd + field public static final int RESULT_NO_RESOURCES = 22; // 0x16 + field public static final int RESULT_OPERATION_NOT_ALLOWED = 20; // 0x14 + field public static final int RESULT_RADIO_NOT_AVAILABLE = 9; // 0x9 + field public static final int RESULT_REMOTE_EXCEPTION = 31; // 0x1f + field public static final int RESULT_REQUEST_NOT_SUPPORTED = 24; // 0x18 + field public static final int RESULT_RIL_CANCELLED = 119; // 0x77 + field public static final int RESULT_RIL_ENCODING_ERR = 109; // 0x6d + field public static final int RESULT_RIL_INTERNAL_ERR = 113; // 0x71 + field public static final int RESULT_RIL_INVALID_ARGUMENTS = 104; // 0x68 + field public static final int RESULT_RIL_INVALID_MODEM_STATE = 115; // 0x73 + field public static final int RESULT_RIL_INVALID_SMSC_ADDRESS = 110; // 0x6e + field public static final int RESULT_RIL_INVALID_SMS_FORMAT = 107; // 0x6b + field public static final int RESULT_RIL_INVALID_STATE = 103; // 0x67 + field public static final int RESULT_RIL_MODEM_ERR = 111; // 0x6f + field public static final int RESULT_RIL_NETWORK_ERR = 112; // 0x70 + field public static final int RESULT_RIL_NETWORK_NOT_READY = 116; // 0x74 + field public static final int RESULT_RIL_NETWORK_REJECT = 102; // 0x66 + field public static final int RESULT_RIL_NO_MEMORY = 105; // 0x69 + field public static final int RESULT_RIL_NO_RESOURCES = 118; // 0x76 + field public static final int RESULT_RIL_OPERATION_NOT_ALLOWED = 117; // 0x75 + field public static final int RESULT_RIL_RADIO_NOT_AVAILABLE = 100; // 0x64 + field public static final int RESULT_RIL_REQUEST_NOT_SUPPORTED = 114; // 0x72 + field public static final int RESULT_RIL_REQUEST_RATE_LIMITED = 106; // 0x6a + field public static final int RESULT_RIL_SIM_ABSENT = 120; // 0x78 + field public static final int RESULT_RIL_SMS_SEND_FAIL_RETRY = 101; // 0x65 + field public static final int RESULT_RIL_SYSTEM_ERR = 108; // 0x6c + field public static final int RESULT_SMS_BLOCKED_DURING_EMERGENCY = 29; // 0x1d + field public static final int RESULT_SMS_SEND_RETRY_FAILED = 30; // 0x1e + field public static final int RESULT_SYSTEM_ERROR = 15; // 0xf + field public static final int RESULT_UNEXPECTED_EVENT_STOP_SENDING = 28; // 0x1c field public static final int STATUS_ON_ICC_FREE = 0; // 0x0 field public static final int STATUS_ON_ICC_READ = 1; // 0x1 field public static final int STATUS_ON_ICC_SENT = 5; // 0x5 @@ -44886,6 +44955,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>); method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context); method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList(); + method public static int getActiveDataSubscriptionId(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount(); method public int getActiveSubscriptionInfoCountMax(); @@ -44919,6 +44989,7 @@ package android.telephony { field public static final int DATA_ROAMING_DISABLE = 0; // 0x0 field public static final int DATA_ROAMING_ENABLE = 1; // 0x1 field public static final int DEFAULT_SUBSCRIPTION_ID = 2147483647; // 0x7fffffff + field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; field public static final int INVALID_SIM_SLOT_INDEX = -1; // 0xffffffff field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff @@ -44983,9 +45054,9 @@ package android.telephony { method public int getDataState(); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getGroupIdLevel1(); method public String getIccAuthentication(int, int, String); @@ -45020,10 +45091,11 @@ package android.telephony { method public int getSimState(); method public int getSimState(int); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId(); + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle); method public int getSupportedModemCount(); method @Nullable public String getTypeAllocationCode(); method @Nullable public String getTypeAllocationCode(int); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo(); + method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(); @@ -45432,11 +45504,13 @@ package android.telephony.euicc { method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent); field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE"; + field public static final String ACTION_START_EUICC_ACTIVATION = "android.telephony.euicc.action.START_EUICC_ACTIVATION"; field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2 field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0 field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1 field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION"; + field public static final String EXTRA_USE_QR_SCANNER = "android.telephony.euicc.extra.USE_QR_SCANNER"; field public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon"; } @@ -46957,7 +47031,7 @@ package android.text.style { } public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan android.text.ParcelableSpan { - ctor public LineHeightSpan.Standard(@Px @IntRange(from=1) int); + ctor public LineHeightSpan.Standard(@IntRange(from=1) @Px int); ctor public LineHeightSpan.Standard(@NonNull android.os.Parcel); method public void chooseHeight(@NonNull CharSequence, int, int, int, int, @NonNull android.graphics.Paint.FontMetricsInt); method public int describeContents(); @@ -51086,11 +51160,11 @@ package android.view { field @Deprecated public static final boolean TRACE_RECYCLER = false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.CapturedViewProperty { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.CapturedViewProperty { method public abstract boolean retrieveReturn() default false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.ExportedProperty { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.ExportedProperty { method public abstract String category() default ""; method public abstract boolean deepExport() default false; method public abstract android.view.ViewDebug.FlagToString[] flagMapping() default {}; @@ -51102,7 +51176,7 @@ package android.view { method public abstract boolean resolveId() default false; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.FlagToString { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.FlagToString { method public abstract int equals(); method public abstract int mask(); method public abstract String name(); @@ -51120,7 +51194,7 @@ package android.view { enum_constant @Deprecated public static final android.view.ViewDebug.HierarchyTraceType REQUEST_LAYOUT; } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.IntToString { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.IntToString { method public abstract int from(); method public abstract String to(); } @@ -53669,18 +53743,18 @@ package android.view.textclassifier { } public interface TextClassifier { - method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); + method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); method public default void destroy(); - method @WorkerThread @NonNull public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request); method @WorkerThread public default int getMaxGenerateLinksTextLength(); method public default boolean isDestroyed(); method public default void onSelectionEvent(@NonNull android.view.textclassifier.SelectionEvent); method public default void onTextClassifierEvent(@NonNull android.view.textclassifier.TextClassifierEvent); - method @WorkerThread @NonNull public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request); - method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); + method @NonNull @WorkerThread public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request); + method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList); field public static final String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER"; field public static final String HINT_TEXT_IS_EDITABLE = "android.text_is_editable"; field public static final String HINT_TEXT_IS_NOT_EDITABLE = "android.text_is_not_editable"; @@ -56143,12 +56217,12 @@ package android.widget { ctor public Magnifier.Builder(@NonNull android.view.View); method @NonNull public android.widget.Magnifier build(); method @NonNull public android.widget.Magnifier.Builder setClippingEnabled(boolean); - method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@Px @FloatRange(from=0) float); + method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@FloatRange(from=0) @Px float); method @NonNull public android.widget.Magnifier.Builder setDefaultSourceToMagnifierOffset(@Px int, @Px int); - method @NonNull public android.widget.Magnifier.Builder setElevation(@Px @FloatRange(from=0) float); + method @NonNull public android.widget.Magnifier.Builder setElevation(@FloatRange(from=0) @Px float); method @NonNull public android.widget.Magnifier.Builder setInitialZoom(@FloatRange(from=0.0f) float); method @NonNull public android.widget.Magnifier.Builder setOverlay(@Nullable android.graphics.drawable.Drawable); - method @NonNull public android.widget.Magnifier.Builder setSize(@Px @IntRange(from=0) int, @Px @IntRange(from=0) int); + method @NonNull public android.widget.Magnifier.Builder setSize(@IntRange(from=0) @Px int, @IntRange(from=0) @Px int); method @NonNull public android.widget.Magnifier.Builder setSourceBounds(int, int, int, int); } @@ -56642,7 +56716,7 @@ package android.widget { method @NonNull public static android.widget.RemoteViews.RemoteResponse fromPendingIntent(@NonNull android.app.PendingIntent); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface RemoteViews.RemoteView { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface RemoteViews.RemoteView { } public abstract class RemoteViewsService extends android.app.Service { @@ -57318,7 +57392,7 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFallbackLineSpacing(boolean); method public void setFilters(android.text.InputFilter[]); - method public void setFirstBaselineToTopHeight(@Px @IntRange(from=0) int); + method public void setFirstBaselineToTopHeight(@IntRange(from=0) @Px int); method public void setFontFeatureSettings(@Nullable String); method public boolean setFontVariationSettings(@Nullable String); method protected boolean setFrame(int, int, int, int); @@ -57340,9 +57414,9 @@ package android.widget { method public void setInputType(int); method public void setJustificationMode(int); method public void setKeyListener(android.text.method.KeyListener); - method public void setLastBaselineToBottomHeight(@Px @IntRange(from=0) int); + method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int); method public void setLetterSpacing(float); - method public void setLineHeight(@Px @IntRange(from=0) int); + method public void setLineHeight(@IntRange(from=0) @Px int); method public void setLineSpacing(float, float); method public void setLines(int); method public final void setLinkTextColor(@ColorInt int); @@ -60397,7 +60471,7 @@ package java.lang { ctor public OutOfMemoryError(String); } - @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface Override { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface Override { } public class Package implements java.lang.reflect.AnnotatedElement { @@ -60889,9 +60963,9 @@ package java.lang { method @NonNull public StringBuilder reverse(); method public void setCharAt(int, char); method public void setLength(int); - method public CharSequence subSequence(int, int); - method public String substring(int); - method public String substring(int, int); + method @NonNull public CharSequence subSequence(int, int); + method @NonNull public String substring(int); + method @NonNull public String substring(int, int); method public void trimToSize(); } @@ -60901,7 +60975,7 @@ package java.lang { ctor public StringIndexOutOfBoundsException(int); } - @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface SuppressWarnings { + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressWarnings { method public abstract String[] value(); } @@ -71224,20 +71298,20 @@ package java.util.concurrent { method public boolean addAll(@NonNull java.util.Collection<? extends K>); method public final void clear(); method public boolean contains(@NonNull Object); - method public final boolean containsAll(java.util.Collection<?>); + method public final boolean containsAll(@NonNull java.util.Collection<?>); method public void forEach(@NonNull java.util.function.Consumer<? super K>); - method public java.util.concurrent.ConcurrentHashMap<K,V> getMap(); + method @NonNull public java.util.concurrent.ConcurrentHashMap<K,V> getMap(); method @Nullable public V getMappedValue(); method public final boolean isEmpty(); method @NonNull public java.util.Iterator<K> iterator(); method public boolean remove(@NonNull Object); - method public final boolean removeAll(java.util.Collection<?>); - method public final boolean retainAll(java.util.Collection<?>); + method public final boolean removeAll(@NonNull java.util.Collection<?>); + method public final boolean retainAll(@NonNull java.util.Collection<?>); method public final int size(); method @NonNull public java.util.Spliterator<K> spliterator(); - method public final Object[] toArray(); - method public final <T> T[] toArray(T[]); - method public final String toString(); + method @NonNull public final Object[] toArray(); + method @NonNull public final <T> T[] toArray(@NonNull T[]); + method @NonNull public final String toString(); } public class ConcurrentLinkedDeque<E> extends java.util.AbstractCollection<E> implements java.util.Deque<E> java.io.Serializable { diff --git a/api/removed.txt b/api/removed.txt index b947918dc757..a4ccfb6db128 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -595,10 +595,6 @@ package android.provider { field public static final String VOLUME_VOICE = "volume_voice"; } - public static final class Telephony.Sms.Intents { - field public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; - } - } package android.speech.tts { diff --git a/api/system-current.txt b/api/system-current.txt index 2321e3e78b18..3732b6cc0157 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -568,7 +568,7 @@ package android.app { method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent); @@ -1239,12 +1239,18 @@ package android.bluetooth { public final class BluetoothAdapter { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean disableBLE(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean enableBLE(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean enableNoAutoConnect(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean factoryReset(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public long getDiscoveryEndMillis(); method public boolean isBleScanAlwaysAvailable(); method public boolean isLeEnabled(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setScanMode(int, int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setScanMode(int); field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE"; } @@ -1260,6 +1266,7 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean); @@ -1355,7 +1362,7 @@ package android.content { method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); - method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@RequiresPermission @NonNull android.content.Intent, @NonNull android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle); field public static final String APP_PREDICTION_SERVICE = "app_prediction"; field public static final String BACKUP_SERVICE = "backup"; field public static final String BUGREPORT_SERVICE = "bugreport"; @@ -1373,6 +1380,7 @@ package android.content { field public static final String STATS_MANAGER = "stats"; field public static final String STATUS_BAR_SERVICE = "statusbar"; field public static final String SYSTEM_UPDATE_SERVICE = "system_update"; + field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry"; field public static final String VR_SERVICE = "vrmanager"; field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager"; field public static final String WIFI_SCANNING_SERVICE = "wifiscanner"; @@ -1740,6 +1748,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 + field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; field @StringRes public int requestRes; @@ -1842,8 +1851,8 @@ package android.content.rollback { public final class RollbackManager { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; field public static final int STATUS_FAILURE = 1; // 0x1 @@ -2353,24 +2362,24 @@ package android.hardware.location { } public final class ContextHubManager { - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] findNanoAppOnHub(int, @NonNull android.hardware.location.NanoAppFilter); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] getContextHubHandles(); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubInfo getContextHubInfo(int); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs(); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int loadNanoApp(int, @NonNull android.hardware.location.NanoApp); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo); method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback); method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int unloadNanoApp(int); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); + method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback); field public static final int EVENT_HUB_RESET = 6; // 0x6 field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4 @@ -3035,7 +3044,7 @@ package android.hardware.usb { } public final class UsbPort { - method @RequiresPermission(android.Manifest.permission.MANAGE_USB) @Nullable public android.hardware.usb.UsbPortStatus getStatus(); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int); } @@ -3428,7 +3437,7 @@ package android.location { method @NonNull public android.location.LocationRequest setFastestInterval(long); method public void setHideFromAppOps(boolean); method @NonNull public android.location.LocationRequest setInterval(long); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean); method @NonNull public android.location.LocationRequest setLowPowerMode(boolean); method @NonNull public android.location.LocationRequest setNumUpdates(int); method @NonNull public android.location.LocationRequest setProvider(@NonNull String); @@ -4432,7 +4441,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } @@ -4651,6 +4661,13 @@ package android.net.wifi { field @Deprecated public byte id; } + public final class WifiClient implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.MacAddress getMacAddress(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiClient> CREATOR; + } + @Deprecated public class WifiConfiguration implements android.os.Parcelable { method @Deprecated public boolean hasNoInternetAccess(); method @Deprecated public boolean isEphemeral(); @@ -4691,6 +4708,7 @@ package android.net.wifi { method public boolean isPortableHotspotSupported(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled(); method public boolean isWifiScannerSupported(); + method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback, @Nullable java.util.concurrent.Executor); method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener); method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int); @@ -4698,8 +4716,11 @@ package android.net.wifi { method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource); + method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startSoftAp(@Nullable android.net.wifi.WifiConfiguration); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession(); + method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp(); + method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateInterfaceIpState(@Nullable String, int); method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void updateWifiUsabilityScore(int, int, int); field public static final int CHANGE_REASON_ADDED = 0; // 0x0 field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2 @@ -4714,10 +4735,16 @@ package android.net.wifi { field public static final String EXTRA_CHANGE_REASON = "changeReason"; field public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; field public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; + field public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; + field public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; field public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; field public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; field public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; field public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; + field public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; // 0x0 + field public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; // 0x2 + field public static final int IFACE_IP_MODE_TETHERED = 1; // 0x1 + field public static final int IFACE_IP_MODE_UNSPECIFIED = -1; // 0xffffffff field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0 field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1 field public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED"; @@ -4740,6 +4767,11 @@ package android.net.wifi { method public void onWifiUsabilityStats(int, boolean, @NonNull android.net.wifi.WifiUsabilityStatsEntry); } + public static interface WifiManager.SoftApCallback { + method public void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>); + method public void onStateChanged(int, int); + } + public class WifiNetworkConnectionStatistics implements android.os.Parcelable { ctor public WifiNetworkConnectionStatistics(int, int); ctor public WifiNetworkConnectionStatistics(); @@ -5315,8 +5347,8 @@ package android.os { method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports(); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs); method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener); @@ -6090,15 +6122,25 @@ package android.provider { field public static final String DELIVERY_TIME = "date"; field public static final String ETWS_WARNING_TYPE = "etws_warning_type"; field public static final String GEOGRAPHICAL_SCOPE = "geo_scope"; + field public static final String GEOMETRIES = "geometries"; field public static final String LAC = "lac"; field public static final String LANGUAGE_CODE = "language"; + field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; field public static final String MESSAGE_BODY = "body"; + field public static final String MESSAGE_BROADCASTED = "message_broadcasted"; field public static final String MESSAGE_FORMAT = "format"; + field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI; field public static final String MESSAGE_PRIORITY = "priority"; field public static final String MESSAGE_READ = "read"; field public static final String PLMN = "plmn"; + field public static final String RECEIVED_TIME = "received_time"; field public static final String SERIAL_NUMBER = "serial_number"; field public static final String SERVICE_CATEGORY = "service_category"; + field public static final String SLOT_INDEX = "slot_index"; + } + + public static final class Telephony.Sms.Intents { + field public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = "android.provider.action.SMS_EMERGENCY_CB_RECEIVED"; } public final class TimeZoneRulesDataContract { @@ -6122,7 +6164,7 @@ package android.provider { package android.security.keystore { public abstract class AttestationUtils { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 @@ -6202,18 +6244,18 @@ package android.security.keystore.recovery { } public class RecoveryController { - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public android.security.keystore.recovery.RecoverySession createRecoverySession(); + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.RecoverySession createRecoverySession(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context); - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context); + method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException; + method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException; method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int getRecoveryStatus(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates(); + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void initRecoveryService(@NonNull String, @NonNull byte[], @NonNull byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static boolean isRecoverableKeyStoreEnabled(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void removeKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException; @@ -6228,8 +6270,8 @@ package android.security.keystore.recovery { public class RecoverySession implements java.lang.AutoCloseable { method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void close(); - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException; - method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException; + method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; } public class SessionExpiredException extends java.security.GeneralSecurityException { @@ -6370,7 +6412,29 @@ package android.service.carrier { public abstract class ApnService extends android.app.Service { ctor public ApnService(); method @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent); - method @WorkerThread @NonNull public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); + method @NonNull @WorkerThread public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); + } + + public abstract class CarrierMessagingServiceWrapper { + ctor public CarrierMessagingServiceWrapper(); + method public boolean bindToCarrierMessagingService(@NonNull android.content.Context, @NonNull String); + method public void disposeConnection(@NonNull android.content.Context); + method public void downloadMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void filterSms(@NonNull android.service.carrier.MessagePdu, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public abstract void onServiceReady(); + method public void sendDataSms(@NonNull byte[], int, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendMultipartTextSms(@NonNull java.util.List<java.lang.String>, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + method public void sendTextSms(@NonNull String, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper); + } + + public abstract static class CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper { + ctor public CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper(); + method public void onDownloadMmsComplete(int); + method public void onFilterComplete(int); + method public void onSendMmsComplete(int, @Nullable byte[]); + method public void onSendMultipartSmsComplete(int, @Nullable int[]); + method public void onSendSmsComplete(int, int); } } @@ -6482,13 +6546,13 @@ package android.service.euicc { method public android.service.euicc.EuiccProfileInfo.Builder setUiccAccessRule(@Nullable java.util.List<android.telephony.UiccAccessRule>); } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) public static @interface EuiccProfileInfo.PolicyRule { + @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.PolicyRule { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileClass { + @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileClass { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileState { + @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileState { } public abstract class EuiccService extends android.app.Service { @@ -6498,7 +6562,7 @@ package android.service.euicc { method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle); method @Deprecated public int onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean); method @Deprecated public abstract int onEraseSubscriptions(int); - method public int onEraseSubscriptionsWithOptions(int, @android.telephony.euicc.EuiccCardManager.ResetOption int); + method public int onEraseSubscriptions(int, @android.telephony.euicc.EuiccCardManager.ResetOption int); method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean); method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean); method public abstract String onGetEid(int); @@ -6518,6 +6582,8 @@ package android.service.euicc { field public static final String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM"; field public static final String ACTION_RESOLVE_NO_PRIVILEGES = "android.service.euicc.action.RESOLVE_NO_PRIVILEGES"; field public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS = "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS"; + field public static final String ACTION_START_CARRIER_ACTIVATION = "android.service.euicc.action.START_CARRIER_ACTIVATION"; + field public static final String ACTION_START_EUICC_ACTIVATION = "android.service.euicc.action.START_EUICC_ACTIVATION"; field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED"; field public static final String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI"; field public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService"; @@ -6667,7 +6733,7 @@ package android.service.notification { package android.service.oemlock { public class OemLockManager { - method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) @Nullable public String getLockName(); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public String getLockName(); method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByCarrier(); method @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByUser(); method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public void setOemUnlockAllowedByCarrier(boolean, @Nullable byte[]); @@ -6680,7 +6746,7 @@ package android.service.persistentdata { public class PersistentDataBlockManager { method @RequiresPermission("android.permission.ACCESS_PDB_STATE") public int getDataBlockSize(); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) @android.service.persistentdata.PersistentDataBlockManager.FlashLockState public int getFlashLockState(); + method @android.service.persistentdata.PersistentDataBlockManager.FlashLockState @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public int getFlashLockState(); method public long getMaximumDataBlockSize(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public boolean getOemUnlockEnabled(); method public byte[] read(); @@ -6913,14 +6979,18 @@ package android.telecom { public abstract class Conference extends android.telecom.Conferenceable { method @Deprecated public final android.telecom.AudioState getAudioState(); method @Deprecated public final long getConnectTimeMillis(); + method public final long getConnectionStartElapsedRealTime(); method public android.telecom.Connection getPrimaryConnection(); + method @NonNull public final String getTelecomCallId(); method @Deprecated public void onAudioStateChanged(android.telecom.AudioState); + method public final void setAddress(@NonNull android.net.Uri, int); + method public final void setCallerDisplayName(@NonNull String, int); + method public void setConferenceState(boolean); method @Deprecated public final void setConnectTimeMillis(long); } public abstract class Connection extends android.telecom.Conferenceable { method @Deprecated public final android.telecom.AudioState getAudioState(); - method public final int getCallRadioTech(); method public final long getConnectElapsedTimeMillis(); method public final long getConnectTimeMillis(); method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle(); @@ -6928,7 +6998,6 @@ package android.telecom { method @Deprecated public void onAudioStateChanged(android.telecom.AudioState); method public final void resetConnectionTime(); method public void setCallDirection(int); - method public final void setCallRadioTech(int); method public final void setConnectTimeMillis(long); method public final void setConnectionStartElapsedRealTime(long); method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle); @@ -6942,6 +7011,10 @@ package android.telecom { field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800 } + public abstract class ConnectionService extends android.app.Service { + method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference); + } + public abstract class InCallService extends android.app.Service { method @Deprecated public android.telecom.Phone getPhone(); method @Deprecated public void onPhoneCreated(android.telecom.Phone); @@ -7073,6 +7146,10 @@ package android.telecom { field public static final int CAPABILITY_MULTI_USER = 32; // 0x20 } + public static class PhoneAccount.Builder { + method @NonNull public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String); + } + public class PhoneAccountSuggestionService extends android.app.Service { ctor public PhoneAccountSuggestionService(); method public void onAccountSuggestionRequest(@NonNull String); @@ -7143,6 +7220,7 @@ package android.telecom { method public int getCallState(); method public android.telecom.PhoneAccountHandle getConnectionManager(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(int); method @Deprecated public android.content.ComponentName getDefaultPhoneApp(); method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage(); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String); @@ -7203,13 +7281,6 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR; } - public class CallerInfo { - method @Nullable public android.net.Uri getContactDisplayPhotoUri(); - method public long getContactId(); - method @Nullable public String getName(); - method @Nullable public String getPhoneNumber(); - } - public class CarrierConfigManager { method @NonNull public static android.os.PersistableBundle getDefaultConfig(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); @@ -7243,11 +7314,27 @@ package android.telephony { method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int); } + public class CbGeoUtils { + } + + public static interface CbGeoUtils.Geometry { + method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); + } + + public static class CbGeoUtils.LatLng { + ctor public CbGeoUtils.LatLng(double, double); + method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng); + method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng); + field public final double lat; + field public final double lng; + } + public abstract class CellBroadcastService extends android.app.Service { ctor public CellBroadcastService(); - method @CallSuper public android.os.IBinder onBind(android.content.Intent); - method public abstract void onCdmaCellBroadcastSms(int, byte[]); - method public abstract void onGsmCellBroadcastSms(int, byte[]); + method @CallSuper @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent); + method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int); + method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>); + method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]); field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService"; } @@ -7597,6 +7684,7 @@ package android.telephony { public final class DataSpecificRegistrationInfo implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method public boolean isUsingCarrierAggregation(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; } @@ -7664,6 +7752,7 @@ package android.telephony { field public static final int NUMBER_UNREACHABLE = 8; // 0x8 field public static final int OTASP_PROVISIONING_IN_PROCESS = 76; // 0x4c field public static final int OUTGOING_CANCELED = 44; // 0x2c + field public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; // 0x50 field public static final int OUTGOING_FAILURE = 43; // 0x2b field public static final int OUT_OF_NETWORK = 11; // 0xb field public static final int OUT_OF_SERVICE = 18; // 0x12 @@ -7709,6 +7798,7 @@ package android.telephony { method @Nullable public android.telephony.CellIdentity getCellIdentity(); method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getDomain(); + method public int getNrState(); method public int getRegistrationState(); method public int getRejectCause(); method public int getRoamingType(); @@ -7791,6 +7881,12 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR; } + public class PhoneNumberUtils { + method @NonNull public static String getUsernameFromUriNumber(@NonNull String); + method public static boolean isUriNumber(@Nullable String); + method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String); + } + public class PhoneStateListener { method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int); @@ -7945,6 +8041,9 @@ package android.telephony { method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList(); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int); + method public int getNrFrequencyRange(); + method @Nullable public String getOperatorAlphaLongRaw(); + method @Nullable public String getOperatorAlphaShortRaw(); field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2 field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3 field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0 @@ -8043,6 +8142,7 @@ package android.telephony { method public int getGeographicalScope(); method @Nullable public String getLanguageCode(); method @NonNull public android.telephony.SmsCbLocation getLocation(); + method public int getMaximumWaitingDuration(); method @Nullable public String getMessageBody(); method public int getMessageFormat(); method public int getMessagePriority(); @@ -8071,25 +8171,8 @@ package android.telephony { public final class SmsManager { method public boolean disableCellBroadcastRange(int, int, int); method public boolean enableCellBroadcastRange(int, int, int); + method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>); - field public static final int RESULT_CANCELLED = 23; // 0x17 - field public static final int RESULT_ENCODING_ERROR = 18; // 0x12 - field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; // 0x6 - field public static final int RESULT_ERROR_NONE = 0; // 0x0 - field public static final int RESULT_INTERNAL_ERROR = 21; // 0x15 - field public static final int RESULT_INVALID_ARGUMENTS = 11; // 0xb - field public static final int RESULT_INVALID_SMSC_ADDRESS = 19; // 0x13 - field public static final int RESULT_INVALID_SMS_FORMAT = 14; // 0xe - field public static final int RESULT_INVALID_STATE = 12; // 0xc - field public static final int RESULT_MODEM_ERROR = 16; // 0x10 - field public static final int RESULT_NETWORK_ERROR = 17; // 0x11 - field public static final int RESULT_NETWORK_REJECT = 10; // 0xa - field public static final int RESULT_NO_MEMORY = 13; // 0xd - field public static final int RESULT_NO_RESOURCES = 22; // 0x16 - field public static final int RESULT_OPERATION_NOT_ALLOWED = 20; // 0x14 - field public static final int RESULT_RADIO_NOT_AVAILABLE = 9; // 0x9 - field public static final int RESULT_REQUEST_NOT_SUPPORTED = 24; // 0x18 - field public static final int RESULT_SYSTEM_ERROR = 15; // 0xf } public class SubscriptionInfo implements android.os.Parcelable { @@ -8106,6 +8189,7 @@ package android.telephony { method public void requestEmbeddedSubscriptionInfoListRefresh(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean); field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI; @@ -8174,11 +8258,15 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState(); method @Deprecated public boolean getDataEnabled(); method @Deprecated public boolean getDataEnabled(int); + method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping(); + method public int getMaxNumberOfSimultaneouslyActiveSims(); method public static long getMaxNumberVerificationTimeoutMillis(); + method @NonNull public String getNetworkCountryIso(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask(); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState(); method public int getSimApplicationState(); @@ -8199,12 +8287,14 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int); method public boolean isDataConnectivityPossible(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetherApnRequired(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); method public boolean needsOtaServiceProvisioning(); @@ -8212,6 +8302,7 @@ package android.telephony { method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig(); + method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); @@ -8234,6 +8325,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); method public void updateServiceLocation(); field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED"; + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED"; field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; @@ -8286,6 +8378,15 @@ package android.telephony { field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 } + public class TelephonyRegistryManager { + method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor); + method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyCallStateChangedForAllSubscriptions(int, @Nullable String); + method public void notifyCarrierNetworkChange(boolean); + method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); + method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + } + public final class UiccAccessRule implements android.os.Parcelable { ctor public UiccAccessRule(byte[], @Nullable String, long); method public int describeContents(); @@ -8529,10 +8630,10 @@ package android.telephony.euicc { field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) public static @interface EuiccCardManager.CancelReason { + @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason { } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) public static @interface EuiccCardManager.ResetOption { + @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption { } public static interface EuiccCardManager.ResultCallback<T> { @@ -8542,7 +8643,7 @@ package android.telephony.euicc { public class EuiccManager { method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptionsWithOptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent); method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent); method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent); method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus(); @@ -8565,6 +8666,7 @@ package android.telephony.euicc { field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION"; field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION"; field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID"; + field public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID"; field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID"; field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME"; } @@ -8588,7 +8690,7 @@ package android.telephony.euicc { field public static final int EVENT_INSTALL = 1; // 0x1 } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) public static @interface EuiccNotification.Event { + @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event { } public final class EuiccRulesAuthTable implements android.os.Parcelable { @@ -8606,7 +8708,7 @@ package android.telephony.euicc { method public android.telephony.euicc.EuiccRulesAuthTable build(); } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { + @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { } } @@ -8651,6 +8753,7 @@ package android.telephony.ims { method public android.os.Bundle getCallExtras(); method public int getCallType(); method public static int getCallTypeFromVideoState(int); + method public int getCallerNumberVerificationStatus(); method public int getEmergencyCallRouting(); method public int getEmergencyServiceCategories(); method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); @@ -8668,6 +8771,7 @@ package android.telephony.ims { method public void setCallExtraBoolean(String, boolean); method public void setCallExtraInt(String, int); method public void setCallRestrictCause(int); + method public void setCallerNumberVerificationStatus(int); method public void setEmergencyCallRouting(int); method public void setEmergencyCallTesting(boolean); method public void setEmergencyServiceCategories(int); @@ -8718,6 +8822,9 @@ package android.telephony.ims { field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2 field public static final int SERVICE_TYPE_NONE = 0; // 0x0 field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1 + field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2 + field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0 + field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1 } public class ImsCallSessionListener { @@ -8810,17 +8917,23 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; } - public class ImsMmTelManager { + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); @@ -8830,7 +8943,8 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0 @@ -8842,12 +8956,8 @@ package android.telephony.ims { method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); } - public static class ImsMmTelManager.RegistrationCallback { - ctor public ImsMmTelManager.RegistrationCallback(); - method public void onRegistered(int); - method public void onRegistering(int); - method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); - method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); + @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { + ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); } public final class ImsReasonInfo implements android.os.Parcelable { @@ -9223,14 +9333,17 @@ package android.telephony.ims { } public class ImsUtListener { + method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo); method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData); method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]); method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]); method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]); - method public void onUtConfigurationQueried(int, android.os.Bundle); + method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle); method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo); method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo); method public void onUtConfigurationUpdated(int); + field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir"; + field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; } public abstract class ImsVideoCallProvider { @@ -9257,12 +9370,12 @@ package android.telephony.ims { public class ProvisioningManager { method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); - method @WorkerThread @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b @@ -9279,6 +9392,24 @@ package android.telephony.ims { method public void onProvisioningStringChanged(int, @NonNull String); } + public interface RegistrationManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0 + field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2 + field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1 + } + + public static class RegistrationManager.RegistrationCallback { + ctor public RegistrationManager.RegistrationCallback(); + method public void onRegistered(int); + method public void onRegistering(int); + method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); + method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); + } + } package android.telephony.ims.feature { @@ -9343,6 +9474,8 @@ package android.telephony.ims.feature { method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); method public void setUiTtyMode(int, @Nullable android.os.Message); method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]); + field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; field public static final int PROCESS_CALL_CSFB = 1; // 0x1 field public static final int PROCESS_CALL_IMS = 0; // 0x0 } diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt index fffec3e739ae..c64e3d884a70 100644 --- a/api/system-lint-baseline.txt +++ b/api/system-lint-baseline.txt @@ -127,6 +127,12 @@ MissingNullability: android.view.contentcapture.ViewNode#getTextLineCharOffsets( +MutableBareField: android.net.wifi.WifiConfiguration#allowAutojoin: + +MutableBareField: android.net.wifi.WifiConfiguration#carrierId: + + + NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: diff --git a/api/test-current.txt b/api/test-current.txt index 716f0c68dbc3..18d9f75b5aae 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -707,6 +707,7 @@ package android.content.pm { method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS", "android.permission.GET_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @NonNull public abstract String getServicesSystemSharedLibraryPackageName(); method @NonNull public abstract String getSharedSystemSharedLibraryPackageName(); + method @Nullable public String[] getTelephonyPackageNames(); method @Nullable public String getWellbeingPackageName(); method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); @@ -739,6 +740,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 + field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000 field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; @@ -793,8 +795,8 @@ package android.content.rollback { public final class RollbackManager { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; @@ -1078,7 +1080,7 @@ package android.location { method @NonNull public android.location.LocationRequest setExpireIn(long); method @NonNull public android.location.LocationRequest setFastestInterval(long); method @NonNull public android.location.LocationRequest setInterval(long); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean); method @NonNull public android.location.LocationRequest setNumUpdates(int); method @NonNull public android.location.LocationRequest setProvider(@NonNull String); method @NonNull public android.location.LocationRequest setQuality(int); @@ -1654,7 +1656,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } @@ -1852,8 +1855,8 @@ package android.os { method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String); method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports(); method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs); method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener); @@ -2376,6 +2379,36 @@ package android.provider { field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service"; } + public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns { + field public static final String CID = "cid"; + field public static final String CMAS_CATEGORY = "cmas_category"; + field public static final String CMAS_CERTAINTY = "cmas_certainty"; + field public static final String CMAS_MESSAGE_CLASS = "cmas_message_class"; + field public static final String CMAS_RESPONSE_TYPE = "cmas_response_type"; + field public static final String CMAS_SEVERITY = "cmas_severity"; + field public static final String CMAS_URGENCY = "cmas_urgency"; + field @NonNull public static final android.net.Uri CONTENT_URI; + field public static final String DEFAULT_SORT_ORDER = "date DESC"; + field public static final String DELIVERY_TIME = "date"; + field public static final String ETWS_WARNING_TYPE = "etws_warning_type"; + field public static final String GEOGRAPHICAL_SCOPE = "geo_scope"; + field public static final String GEOMETRIES = "geometries"; + field public static final String LAC = "lac"; + field public static final String LANGUAGE_CODE = "language"; + field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; + field public static final String MESSAGE_BODY = "body"; + field public static final String MESSAGE_BROADCASTED = "message_broadcasted"; + field public static final String MESSAGE_FORMAT = "format"; + field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI; + field public static final String MESSAGE_PRIORITY = "priority"; + field public static final String MESSAGE_READ = "read"; + field public static final String PLMN = "plmn"; + field public static final String RECEIVED_TIME = "received_time"; + field public static final String SERIAL_NUMBER = "serial_number"; + field public static final String SERVICE_CATEGORY = "service_category"; + field public static final String SLOT_INDEX = "slot_index"; + } + public static final class Telephony.Sms.Intents { field public static final String SMS_CARRIER_PROVISION_ACTION = "android.provider.Telephony.SMS_CARRIER_PROVISION"; } @@ -2398,7 +2431,7 @@ package android.security { package android.security.keystore { public abstract class AttestationUtils { - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; + method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException; field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 @@ -2753,7 +2786,36 @@ package android.telecom { } public abstract class Conference extends android.telecom.Conferenceable { + method public final long getConnectionStartElapsedRealTime(); method public android.telecom.Connection getPrimaryConnection(); + method @NonNull public final String getTelecomCallId(); + method public final void setAddress(@NonNull android.net.Uri, int); + method public final void setCallerDisplayName(@NonNull String, int); + method public void setConferenceState(boolean); + } + + public abstract class Connection extends android.telecom.Conferenceable { + method public final long getConnectElapsedTimeMillis(); + method public final long getConnectTimeMillis(); + method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle(); + method @Nullable public final String getTelecomCallId(); + method public final void resetConnectionTime(); + method public void setCallDirection(int); + method public final void setConnectTimeMillis(long); + method public final void setConnectionStartElapsedRealTime(long); + method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle); + method public void setTelecomCallId(@NonNull String); + field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000 + field public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 262144; // 0x40000 + field public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL"; + field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1; // 0x1 + field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 + field public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 64; // 0x40 + field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800 + } + + public static class PhoneAccount.Builder { + method @NonNull public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String); } public class PhoneAccountSuggestionService extends android.app.Service { @@ -2766,6 +2828,7 @@ package android.telecom { public class TelecomManager { method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCurrentTtyMode(); + method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDefaultDialerPackage(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle); field public static final int TTY_MODE_FULL = 1; // 0x1 @@ -2779,10 +2842,35 @@ package android.telecom { package android.telephony { public final class AccessNetworkConstants { + field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2 field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1 } + public final class CallQuality implements android.os.Parcelable { + ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); + method public int describeContents(); + method public int getAverageRelativeJitter(); + method public int getAverageRoundTripTime(); + method public int getCallDuration(); + method public int getCodecType(); + method public int getDownlinkCallQualityLevel(); + method public int getMaxRelativeJitter(); + method public int getNumRtpPacketsNotReceived(); + method public int getNumRtpPacketsReceived(); + method public int getNumRtpPacketsTransmitted(); + method public int getNumRtpPacketsTransmittedLost(); + method public int getUplinkCallQualityLevel(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_QUALITY_BAD = 4; // 0x4 + field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0 + field public static final int CALL_QUALITY_FAIR = 2; // 0x2 + field public static final int CALL_QUALITY_GOOD = 1; // 0x1 + field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5 + field public static final int CALL_QUALITY_POOR = 3; // 0x3 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR; + } + public class CarrierConfigManager { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); } @@ -2864,6 +2952,9 @@ package android.telephony { public class PhoneNumberUtils { method public static int getMinMatchForTest(); + method @NonNull public static String getUsernameFromUriNumber(@NonNull String); + method public static boolean isUriNumber(@Nullable String); + method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String); method public static void setMinMatchForTest(int); } @@ -2887,6 +2978,7 @@ package android.telephony { public final class SmsManager { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int checkSmsShortCodeDestination(String, String); + method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String); field public static final int SMS_CATEGORY_FREE_SHORT_CODE = 1; // 0x1 field public static final int SMS_CATEGORY_NOT_SHORT_CODE = 0; // 0x0 field public static final int SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE = 3; // 0x3 @@ -2894,10 +2986,23 @@ package android.telephony { field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2 } + public class SubscriptionManager { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int); + field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI; + } + public class TelephonyManager { method public int checkCarrierPrivilegesForPackage(String); method public int getCarrierIdListVersion(); + method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); + method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag(); + method @NonNull public String getNetworkCountryIso(int); method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile(); method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String); @@ -2919,6 +3024,963 @@ package android.telephony.emergency { } +package android.telephony.ims { + + public final class ImsCallForwardInfo implements android.os.Parcelable { + ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int); + method public int describeContents(); + method public int getCondition(); + method public String getNumber(); + method public int getServiceClass(); + method public int getStatus(); + method public int getTimeSeconds(); + method public int getToA(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CDIV_CF_REASON_ALL = 4; // 0x4 + field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5 + field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1 + field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6 + field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3 + field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2 + field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR; + field public static final int STATUS_ACTIVE = 1; // 0x1 + field public static final int STATUS_NOT_ACTIVE = 0; // 0x0 + field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91 + field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81 + } + + public final class ImsCallProfile implements android.os.Parcelable { + ctor public ImsCallProfile(); + ctor public ImsCallProfile(int, int); + ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile); + method public int describeContents(); + method public String getCallExtra(String); + method public String getCallExtra(String, String); + method public boolean getCallExtraBoolean(String); + method public boolean getCallExtraBoolean(String, boolean); + method public int getCallExtraInt(String); + method public int getCallExtraInt(String, int); + method public android.os.Bundle getCallExtras(); + method public int getCallType(); + method public static int getCallTypeFromVideoState(int); + method public int getCallerNumberVerificationStatus(); + method public int getEmergencyCallRouting(); + method public int getEmergencyServiceCategories(); + method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); + method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); + method public int getRestrictCause(); + method public int getServiceType(); + method public static int getVideoStateFromCallType(int); + method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); + method public boolean hasKnownUserIntentEmergency(); + method public boolean isEmergencyCallTesting(); + method public boolean isVideoCall(); + method public boolean isVideoPaused(); + method public static int presentationToOir(int); + method public void setCallExtra(String, String); + method public void setCallExtraBoolean(String, boolean); + method public void setCallExtraInt(String, int); + method public void setCallRestrictCause(int); + method public void setCallerNumberVerificationStatus(int); + method public void setEmergencyCallRouting(int); + method public void setEmergencyCallTesting(boolean); + method public void setEmergencyServiceCategories(int); + method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>); + method public void setHasKnownUserIntentEmergency(boolean); + method public void updateCallExtras(android.telephony.ims.ImsCallProfile); + method public void updateCallType(android.telephony.ims.ImsCallProfile); + method public void updateMediaProfile(android.telephony.ims.ImsCallProfile); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2 + field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3 + field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0 + field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1 + field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3 + field public static final int CALL_TYPE_VOICE = 2; // 0x2 + field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1 + field public static final int CALL_TYPE_VS = 8; // 0x8 + field public static final int CALL_TYPE_VS_RX = 10; // 0xa + field public static final int CALL_TYPE_VS_TX = 9; // 0x9 + field public static final int CALL_TYPE_VT = 4; // 0x4 + field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7 + field public static final int CALL_TYPE_VT_RX = 6; // 0x6 + field public static final int CALL_TYPE_VT_TX = 5; // 0x5 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR; + field public static final int DIALSTRING_NORMAL = 0; // 0x0 + field public static final int DIALSTRING_SS_CONF = 1; // 0x1 + field public static final int DIALSTRING_USSD = 2; // 0x2 + field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo"; + field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS"; + field public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech"; + field public static final String EXTRA_CHILD_NUMBER = "ChildNum"; + field public static final String EXTRA_CNA = "cna"; + field public static final String EXTRA_CNAP = "cnap"; + field public static final String EXTRA_CODEC = "Codec"; + field public static final String EXTRA_DIALSTRING = "dialstring"; + field public static final String EXTRA_DISPLAY_TEXT = "DisplayText"; + field public static final String EXTRA_EMERGENCY_CALL = "e_call"; + field public static final String EXTRA_IS_CALL_PULL = "CallPull"; + field public static final String EXTRA_OI = "oi"; + field public static final String EXTRA_OIR = "oir"; + field public static final String EXTRA_REMOTE_URI = "remote_uri"; + field public static final String EXTRA_USSD = "ussd"; + field public static final int OIR_DEFAULT = 0; // 0x0 + field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2 + field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4 + field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1 + field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3 + field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2 + field public static final int SERVICE_TYPE_NONE = 0; // 0x0 + field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1 + field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2 + field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0 + field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1 + } + + public class ImsCallSessionListener { + method public void callQualityChanged(@NonNull android.telephony.CallQuality); + method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState); + method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo); + method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo); + method public void callSessionHeld(android.telephony.ims.ImsCallProfile); + method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiated(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionInviteParticipantsRequestDelivered(); + method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionMayHandover(int, int); + method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase); + method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionMultipartyStateChanged(boolean); + method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile); + method public void callSessionRemoveParticipantsRequestDelivered(); + method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionResumed(android.telephony.ims.ImsCallProfile); + method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile); + method public void callSessionRttMessageReceived(String); + method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionRttModifyResponseReceived(int); + method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification); + method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo); + method public void callSessionTtyModeReceived(int); + method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionUpdated(android.telephony.ims.ImsCallProfile); + method public void callSessionUssdMessageReceived(int, String); + } + + public final class ImsConferenceState implements android.os.Parcelable { + method public int describeContents(); + method public static int getConnectionStateForStatus(String); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR; + field public static final String DISPLAY_TEXT = "display-text"; + field public static final String ENDPOINT = "endpoint"; + field public static final String SIP_STATUS_CODE = "sipstatuscode"; + field public static final String STATUS = "status"; + field public static final String STATUS_ALERTING = "alerting"; + field public static final String STATUS_CONNECTED = "connected"; + field public static final String STATUS_CONNECT_FAIL = "connect-fail"; + field public static final String STATUS_DIALING_IN = "dialing-in"; + field public static final String STATUS_DIALING_OUT = "dialing-out"; + field public static final String STATUS_DISCONNECTED = "disconnected"; + field public static final String STATUS_DISCONNECTING = "disconnecting"; + field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus"; + field public static final String STATUS_ON_HOLD = "on-hold"; + field public static final String STATUS_PENDING = "pending"; + field public static final String STATUS_SEND_ONLY = "sendonly"; + field public static final String STATUS_SEND_RECV = "sendrecv"; + field public static final String USER = "user"; + field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants; + } + + public final class ImsException extends java.lang.Exception { + ctor public ImsException(@Nullable String); + ctor public ImsException(@Nullable String, int); + ctor public ImsException(@Nullable String, int, @Nullable Throwable); + method public int getCode(); + field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1 + field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0 + field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2 + } + + public final class ImsExternalCallState implements android.os.Parcelable { + ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean); + method public int describeContents(); + method @NonNull public android.net.Uri getAddress(); + method public int getCallId(); + method public int getCallState(); + method public int getCallType(); + method @Nullable public android.net.Uri getLocalAddress(); + method public boolean isCallHeld(); + method public boolean isCallPullable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_STATE_CONFIRMED = 1; // 0x1 + field public static final int CALL_STATE_TERMINATED = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; + } + + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { + method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAdvancedCallingSettingEnabled(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isTtyOverVolteEnabled(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiRoamingSettingEnabled(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiSettingEnabled(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVtSettingEnabled(); + method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); + method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); + field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 + field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0 + field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2 + } + + public static class ImsMmTelManager.CapabilityCallback { + ctor public ImsMmTelManager.CapabilityCallback(); + method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); + } + + @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { + ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); + } + + public final class ImsReasonInfo implements android.os.Parcelable { + ctor public ImsReasonInfo(int, int, String); + method public int describeContents(); + method public int getCode(); + method public int getExtraCode(); + method public String getExtraMessage(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8 + field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6 + field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa + field public static final int CODE_CALL_BARRED = 240; // 0xf0 + field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c + field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8 + field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7 + field public static final int CODE_DATA_DISABLED = 1406; // 0x57e + field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d + field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6 + field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7 + field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5 + field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb + field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385 + field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c + field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b + field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578 + field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a + field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579 + field public static final int CODE_FDN_BLOCKED = 241; // 0xf1 + field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580 + field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3 + field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514 + field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e + field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92 + field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f + field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d + field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91 + field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94 + field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90 + field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93 + field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c + field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95 + field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65 + field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66 + field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a + field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67 + field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70 + field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c + field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a + field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79 + field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b + field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84 + field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b + field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f + field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83 + field public static final int CODE_LOW_BATTERY = 505; // 0x1f9 + field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b + field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191 + field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193 + field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192 + field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194 + field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386 + field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9 + field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0 + field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df + field public static final int CODE_NO_CSFB_IN_CS_ROAM = 1516; // 0x5ec + field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd + field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001 + field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a + field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b + field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c + field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d + field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e + field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f + field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002 + field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003 + field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004 + field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005 + field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006 + field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007 + field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008 + field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009 + field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1 + field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de + field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2 + field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3 + field public static final int CODE_RADIO_OFF = 1500; // 0x5dc + field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7 + field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6 + field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5 + field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4 + field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8 + field public static final int CODE_REJECTED_ELSEWHERE = 1017; // 0x3f9 + field public static final int CODE_REJECT_1X_COLLISION = 1603; // 0x643 + field public static final int CODE_REJECT_CALL_ON_OTHER_SUB = 1602; // 0x642 + field public static final int CODE_REJECT_CALL_TYPE_NOT_ALLOWED = 1605; // 0x645 + field public static final int CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED = 1617; // 0x651 + field public static final int CODE_REJECT_INTERNAL_ERROR = 1612; // 0x64c + field public static final int CODE_REJECT_MAX_CALL_LIMIT_REACHED = 1608; // 0x648 + field public static final int CODE_REJECT_ONGOING_CALL_SETUP = 1607; // 0x647 + field public static final int CODE_REJECT_ONGOING_CALL_TRANSFER = 1611; // 0x64b + field public static final int CODE_REJECT_ONGOING_CALL_UPGRADE = 1616; // 0x650 + field public static final int CODE_REJECT_ONGOING_CALL_WAITING_DISABLED = 1601; // 0x641 + field public static final int CODE_REJECT_ONGOING_CONFERENCE_CALL = 1618; // 0x652 + field public static final int CODE_REJECT_ONGOING_CS_CALL = 1621; // 0x655 + field public static final int CODE_REJECT_ONGOING_E911_CALL = 1606; // 0x646 + field public static final int CODE_REJECT_ONGOING_ENCRYPTED_CALL = 1620; // 0x654 + field public static final int CODE_REJECT_ONGOING_HANDOVER = 1614; // 0x64e + field public static final int CODE_REJECT_QOS_FAILURE = 1613; // 0x64d + field public static final int CODE_REJECT_SERVICE_NOT_REGISTERED = 1604; // 0x644 + field public static final int CODE_REJECT_UNKNOWN = 1600; // 0x640 + field public static final int CODE_REJECT_UNSUPPORTED_SDP_HEADERS = 1610; // 0x64a + field public static final int CODE_REJECT_UNSUPPORTED_SIP_HEADERS = 1609; // 0x649 + field public static final int CODE_REJECT_VT_AVPF_NOT_ALLOWED = 1619; // 0x653 + field public static final int CODE_REJECT_VT_TTY_NOT_ALLOWED = 1615; // 0x64f + field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c + field public static final int CODE_SESSION_MODIFICATION_FAILED = 1517; // 0x5ed + field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea + field public static final int CODE_SIP_AMBIGUOUS = 376; // 0x178 + field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151 + field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b + field public static final int CODE_SIP_BUSY = 338; // 0x152 + field public static final int CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST = 372; // 0x174 + field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156 + field public static final int CODE_SIP_EXTENSION_REQUIRED = 370; // 0x172 + field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c + field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a + field public static final int CODE_SIP_INTERVAL_TOO_BRIEF = 371; // 0x173 + field public static final int CODE_SIP_LOOP_DETECTED = 373; // 0x175 + field public static final int CODE_SIP_METHOD_NOT_ALLOWED = 366; // 0x16e + field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154 + field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d + field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155 + field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e + field public static final int CODE_SIP_PROXY_AUTHENTICATION_REQUIRED = 367; // 0x16f + field public static final int CODE_SIP_REDIRECTED = 321; // 0x141 + field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153 + field public static final int CODE_SIP_REQUEST_ENTITY_TOO_LARGE = 368; // 0x170 + field public static final int CODE_SIP_REQUEST_PENDING = 377; // 0x179 + field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f + field public static final int CODE_SIP_REQUEST_URI_TOO_LARGE = 369; // 0x171 + field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162 + field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f + field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161 + field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160 + field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150 + field public static final int CODE_SIP_TOO_MANY_HOPS = 374; // 0x176 + field public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343; // 0x157 + field public static final int CODE_SIP_UNDECIPHERABLE = 378; // 0x17a + field public static final int CODE_SIP_USER_MARKED_UNWANTED = 365; // 0x16d + field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169 + field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2 + field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1 + field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3 + field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9 + field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca + field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb + field public static final int CODE_UNSPECIFIED = 0; // 0x0 + field public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512; // 0x200 + field public static final int CODE_USER_DECLINE = 504; // 0x1f8 + field public static final int CODE_USER_IGNORE = 503; // 0x1f7 + field public static final int CODE_USER_NOANSWER = 502; // 0x1f6 + field public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511; // 0x1ff + field public static final int CODE_USER_TERMINATED = 501; // 0x1f5 + field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe + field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335 + field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324 + field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321 + field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323 + field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322 + field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336 + field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339 + field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338 + field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337 + field public static final int CODE_WIFI_LOST = 1407; // 0x57f + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR; + field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3 + field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1 + field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 + field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; + } + + public class ImsService extends android.app.Service { + ctor public ImsService(); + method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); + method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); + method public void disableIms(int); + method public void enableIms(int); + method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; + method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); + method public void readyForFeatureCreation(); + } + + public final class ImsSsData implements android.os.Parcelable { + ctor public ImsSsData(int, int, int, int, int); + method public int describeContents(); + method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo(); + method public int getRequestType(); + method public int getResult(); + method public int getServiceClass(); + method public int getServiceType(); + method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo(); + method public int getTeleserviceType(); + method public boolean isTypeBarring(); + method public boolean isTypeCf(); + method public boolean isTypeClip(); + method public boolean isTypeClir(); + method public boolean isTypeColp(); + method public boolean isTypeColr(); + method public boolean isTypeCw(); + method public boolean isTypeIcb(); + method public boolean isTypeInterrogation(); + method public boolean isTypeUnConditional(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR; + field public static final int RESULT_SUCCESS = 0; // 0x0 + field public static final int SERVICE_CLASS_DATA = 2; // 0x2 + field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20 + field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10 + field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40 + field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80 + field public static final int SERVICE_CLASS_FAX = 4; // 0x4 + field public static final int SERVICE_CLASS_NONE = 0; // 0x0 + field public static final int SERVICE_CLASS_SMS = 8; // 0x8 + field public static final int SERVICE_CLASS_VOICE = 1; // 0x1 + field public static final int SS_ACTIVATION = 0; // 0x0 + field public static final int SS_ALL_BARRING = 18; // 0x12 + field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3 + field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5 + field public static final int SS_ALL_TELESEVICES = 1; // 0x1 + field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0 + field public static final int SS_BAIC = 16; // 0x10 + field public static final int SS_BAIC_ROAMING = 17; // 0x11 + field public static final int SS_BAOC = 13; // 0xd + field public static final int SS_BAOIC = 14; // 0xe + field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf + field public static final int SS_CFU = 0; // 0x0 + field public static final int SS_CFUT = 6; // 0x6 + field public static final int SS_CF_ALL = 4; // 0x4 + field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5 + field public static final int SS_CF_BUSY = 1; // 0x1 + field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3 + field public static final int SS_CF_NO_REPLY = 2; // 0x2 + field public static final int SS_CLIP = 7; // 0x7 + field public static final int SS_CLIR = 8; // 0x8 + field public static final int SS_CNAP = 11; // 0xb + field public static final int SS_COLP = 9; // 0x9 + field public static final int SS_COLR = 10; // 0xa + field public static final int SS_DEACTIVATION = 1; // 0x1 + field public static final int SS_ERASURE = 4; // 0x4 + field public static final int SS_INCOMING_BARRING = 20; // 0x14 + field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16 + field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15 + field public static final int SS_INTERROGATION = 2; // 0x2 + field public static final int SS_OUTGOING_BARRING = 19; // 0x13 + field public static final int SS_REGISTRATION = 3; // 0x3 + field public static final int SS_SMS_SERVICES = 4; // 0x4 + field public static final int SS_TELEPHONY = 2; // 0x2 + field public static final int SS_WAIT = 12; // 0xc + } + + public static final class ImsSsData.Builder { + ctor public ImsSsData.Builder(int, int, int, int, int); + method @NonNull public android.telephony.ims.ImsSsData build(); + method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>); + method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>); + } + + public final class ImsSsInfo implements android.os.Parcelable { + ctor @Deprecated public ImsSsInfo(int, @Nullable String); + method public int describeContents(); + method public int getClirInterrogationStatus(); + method public int getClirOutgoingState(); + method @Deprecated public String getIcbNum(); + method @Nullable public String getIncomingCommunicationBarringNumber(); + method public int getProvisionStatus(); + method public int getStatus(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0 + field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1 + field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2 + field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0 + field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1 + field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4 + field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3 + field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR; + field public static final int DISABLED = 0; // 0x0 + field public static final int ENABLED = 1; // 0x1 + field public static final int NOT_REGISTERED = -1; // 0xffffffff + field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0 + field public static final int SERVICE_PROVISIONED = 1; // 0x1 + field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff + } + + public static final class ImsSsInfo.Builder { + ctor public ImsSsInfo.Builder(int); + method @NonNull public android.telephony.ims.ImsSsInfo build(); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int); + } + + public final class ImsStreamMediaProfile implements android.os.Parcelable { + ctor public ImsStreamMediaProfile(int, int, int, int, int); + method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); + method public int describeContents(); + method public int getAudioDirection(); + method public int getAudioQuality(); + method public int getRttMode(); + method public int getVideoDirection(); + method public int getVideoQuality(); + method public boolean isReceivingRttAudio(); + method public boolean isRttCall(); + method public void setReceivingRttAudio(boolean); + method public void setRttMode(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final int AUDIO_QUALITY_AMR = 1; // 0x1 + field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2 + field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4 + field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5 + field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7 + field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6 + field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14 + field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11 + field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13 + field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12 + field public static final int AUDIO_QUALITY_G711A = 13; // 0xd + field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf + field public static final int AUDIO_QUALITY_G711U = 11; // 0xb + field public static final int AUDIO_QUALITY_G722 = 14; // 0xe + field public static final int AUDIO_QUALITY_G723 = 12; // 0xc + field public static final int AUDIO_QUALITY_G729 = 16; // 0x10 + field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8 + field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9 + field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa + field public static final int AUDIO_QUALITY_NONE = 0; // 0x0 + field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR; + field public static final int DIRECTION_INACTIVE = 0; // 0x0 + field public static final int DIRECTION_INVALID = -1; // 0xffffffff + field public static final int DIRECTION_RECEIVE = 1; // 0x1 + field public static final int DIRECTION_SEND = 2; // 0x2 + field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3 + field public static final int RTT_MODE_DISABLED = 0; // 0x0 + field public static final int RTT_MODE_FULL = 1; // 0x1 + field public static final int VIDEO_QUALITY_NONE = 0; // 0x0 + field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1 + field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2 + field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4 + field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8 + field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10 + } + + public final class ImsSuppServiceNotification implements android.os.Parcelable { + ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR; + field public final int code; + field public final String[] history; + field public final int index; + field public final int notificationType; + field public final String number; + field public final int type; + } + + public class ImsUtListener { + method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo); + method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData); + method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]); + method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]); + method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]); + method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle); + method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdated(int); + field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir"; + field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; + } + + public abstract class ImsVideoCallProvider { + ctor public ImsVideoCallProvider(); + method public void changeCallDataUsage(long); + method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); + method public void changePeerDimensions(int, int); + method public void changeVideoQuality(int); + method public void handleCallSessionEvent(int); + method public abstract void onRequestCallDataUsage(); + method public abstract void onRequestCameraCapabilities(); + method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile); + method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile); + method public abstract void onSetCamera(String); + method public void onSetCamera(String, int); + method public abstract void onSetDeviceOrientation(int); + method public abstract void onSetDisplaySurface(android.view.Surface); + method public abstract void onSetPauseImage(android.net.Uri); + method public abstract void onSetPreviewSurface(android.view.Surface); + method public abstract void onSetZoom(float); + method public void receiveSessionModifyRequest(android.telecom.VideoProfile); + method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile); + } + + public class ProvisioningManager { + method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b + field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a + field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 + field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1 + field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC"; + field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY"; + } + + public static class ProvisioningManager.Callback { + ctor public ProvisioningManager.Callback(); + method public void onProvisioningIntChanged(int, int); + method public void onProvisioningStringChanged(int, @NonNull String); + } + + public interface RegistrationManager { + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0 + field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2 + field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1 + } + + public static class RegistrationManager.RegistrationCallback { + ctor public RegistrationManager.RegistrationCallback(); + method public void onRegistered(int); + method public void onRegistering(int); + method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); + method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); + } + +} + +package android.telephony.ims.feature { + + public final class CapabilityChangeRequest implements android.os.Parcelable { + method public void addCapabilitiesToDisableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method public void addCapabilitiesToEnableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method public int describeContents(); + method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable(); + method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR; + } + + public static class CapabilityChangeRequest.CapabilityPair { + ctor public CapabilityChangeRequest.CapabilityPair(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability public int getCapability(); + method public int getRadioTech(); + } + + public abstract class ImsFeature { + ctor public ImsFeature(); + method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public final int getSlotIndex(); + method public abstract void onFeatureReady(); + method public abstract void onFeatureRemoved(); + method public final void setFeatureState(int); + field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff + field public static final int CAPABILITY_SUCCESS = 0; // 0x0 + field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0 + field public static final int FEATURE_MMTEL = 1; // 0x1 + field public static final int FEATURE_RCS = 2; // 0x2 + field public static final int STATE_INITIALIZING = 1; // 0x1 + field public static final int STATE_READY = 2; // 0x2 + field public static final int STATE_UNAVAILABLE = 0; // 0x0 + } + + @Deprecated public static class ImsFeature.Capabilities { + field @Deprecated protected int mCapabilities; + } + + protected static class ImsFeature.CapabilityCallbackProxy { + method public void onChangeCapabilityConfigurationError(int, int, int); + } + + public class MmTelFeature extends android.telephony.ims.feature.ImsFeature { + ctor public MmTelFeature(); + method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int); + method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile); + method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm(); + method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint(); + method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation(); + method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt(); + method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); + method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle); + method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo); + method public final void notifyVoiceMessageCountUpdate(int); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); + method public void setUiTtyMode(int, @Nullable android.os.Message); + method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]); + field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; + field public static final int PROCESS_CALL_CSFB = 1; // 0x1 + field public static final int PROCESS_CALL_IMS = 0; // 0x0 + } + + public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities { + ctor public MmTelFeature.MmTelCapabilities(); + ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities); + ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); + method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); + method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); + method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); + field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8 + field public static final int CAPABILITY_TYPE_UT = 4; // 0x4 + field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2 + field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 + } + + @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability { + } + + @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_IMS, android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_CSFB}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.ProcessCallResult { + } + + public class RcsFeature extends android.telephony.ims.feature.ImsFeature { + ctor public RcsFeature(); + method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + } + +} + +package android.telephony.ims.stub { + + public class ImsCallSessionImplBase implements java.lang.AutoCloseable { + ctor public ImsCallSessionImplBase(); + method public void accept(int, android.telephony.ims.ImsStreamMediaProfile); + method public void close(); + method public void deflect(String); + method public void extendToConference(String[]); + method public String getCallId(); + method public android.telephony.ims.ImsCallProfile getCallProfile(); + method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider(); + method public android.telephony.ims.ImsCallProfile getLocalCallProfile(); + method public String getProperty(String); + method public android.telephony.ims.ImsCallProfile getRemoteCallProfile(); + method public int getState(); + method public void hold(android.telephony.ims.ImsStreamMediaProfile); + method public void inviteParticipants(String[]); + method public boolean isInCall(); + method public boolean isMultiparty(); + method public void merge(); + method public void reject(int); + method public void removeParticipants(String[]); + method public void resume(android.telephony.ims.ImsStreamMediaProfile); + method public void sendDtmf(char, android.os.Message); + method public void sendRttMessage(String); + method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile); + method public void sendRttModifyResponse(boolean); + method public void sendUssd(String); + method public void setListener(android.telephony.ims.ImsCallSessionListener); + method public void setMute(boolean); + method public void start(String, android.telephony.ims.ImsCallProfile); + method public void startConference(String[], android.telephony.ims.ImsCallProfile); + method public void startDtmf(char); + method public void stopDtmf(); + method public void terminate(int); + method public void update(int, android.telephony.ims.ImsStreamMediaProfile); + field public static final int USSD_MODE_NOTIFY = 0; // 0x0 + field public static final int USSD_MODE_REQUEST = 1; // 0x1 + } + + public static class ImsCallSessionImplBase.State { + method public static String toString(int); + field public static final int ESTABLISHED = 4; // 0x4 + field public static final int ESTABLISHING = 3; // 0x3 + field public static final int IDLE = 0; // 0x0 + field public static final int INITIATED = 1; // 0x1 + field public static final int INVALID = -1; // 0xffffffff + field public static final int NEGOTIATING = 2; // 0x2 + field public static final int REESTABLISHING = 6; // 0x6 + field public static final int RENEGOTIATING = 5; // 0x5 + field public static final int TERMINATED = 8; // 0x8 + field public static final int TERMINATING = 7; // 0x7 + } + + public class ImsConfigImplBase { + ctor public ImsConfigImplBase(); + method public int getConfigInt(int); + method public String getConfigString(int); + method public final void notifyProvisionedValueChanged(int, int); + method public final void notifyProvisionedValueChanged(int, String); + method public int setConfig(int, int); + method public int setConfig(int, String); + field public static final int CONFIG_RESULT_FAILED = 1; // 0x1 + field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0 + field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff + } + + public class ImsEcbmImplBase { + ctor public ImsEcbmImplBase(); + method public final void enteredEcbm(); + method public void exitEmergencyCallbackMode(); + method public final void exitedEcbm(); + } + + public final class ImsFeatureConfiguration implements android.os.Parcelable { + method public int describeContents(); + method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR; + } + + public static class ImsFeatureConfiguration.Builder { + ctor public ImsFeatureConfiguration.Builder(); + method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int); + method public android.telephony.ims.stub.ImsFeatureConfiguration build(); + } + + public static final class ImsFeatureConfiguration.FeatureSlotPair { + ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int); + field public final int featureType; + field public final int slotId; + } + + public class ImsMultiEndpointImplBase { + ctor public ImsMultiEndpointImplBase(); + method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>); + method public void requestImsExternalCallStateInfo(); + } + + public class ImsRegistrationImplBase { + ctor public ImsRegistrationImplBase(); + method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); + method public final void onRegistered(int); + method public final void onRegistering(int); + method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]); + method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); + field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 + field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 + field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff + } + + public class ImsSmsImplBase { + ctor public ImsSmsImplBase(); + method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int); + method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int); + method public String getSmsFormat(); + method public void onReady(); + method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException; + method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException; + method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException; + method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException; + method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException; + method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException; + method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]); + field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2 + field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3 + field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4 + field public static final int DELIVER_STATUS_OK = 1; // 0x1 + field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff + field public static final int SEND_STATUS_ERROR = 2; // 0x2 + field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4 + field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3 + field public static final int SEND_STATUS_OK = 1; // 0x1 + field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2 + field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1 + } + + public class ImsUtImplBase { + ctor public ImsUtImplBase(); + method public void close(); + method public int queryCallBarring(int); + method public int queryCallBarringForServiceClass(int, int); + method public int queryCallForward(int, String); + method public int queryCallWaiting(); + method public int queryClip(); + method public int queryClir(); + method public int queryColp(); + method public int queryColr(); + method public void setListener(android.telephony.ims.ImsUtListener); + method public int transact(android.os.Bundle); + method public int updateCallBarring(int, int, String[]); + method public int updateCallBarringForServiceClass(int, int, String[], int); + method public int updateCallForward(int, int, String, int, int); + method public int updateCallWaiting(boolean, int); + method public int updateClip(boolean); + method public int updateClir(int); + method public int updateColp(boolean); + method public int updateColr(int); + } + +} + package android.telephony.mbms { public static class DownloadRequest.Builder { diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt new file mode 100644 index 000000000000..bf21ce71c9a4 --- /dev/null +++ b/api/test-lint-baseline.txt @@ -0,0 +1,2667 @@ +// Baseline format: 1.0 +AcronymName: android.app.NotificationChannel#isImportanceLockedByOEM(): + +AcronymName: android.app.NotificationChannel#setImportanceLockedByOEM(boolean): + + + +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO: + Inconsistent extra value; expected `android.telephony.ims.extra.ADDITIONAL_CALL_INFO`, was `AdditionalCallInfo` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE: + Inconsistent extra value; expected `android.telephony.ims.extra.CALL_RAT_TYPE`, was `CallRadioTech` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CHILD_NUMBER: + Inconsistent extra value; expected `android.telephony.ims.extra.CHILD_NUMBER`, was `ChildNum` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNA: + Inconsistent extra value; expected `android.telephony.ims.extra.CNA`, was `cna` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNAP: + Inconsistent extra value; expected `android.telephony.ims.extra.CNAP`, was `cnap` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CODEC: + Inconsistent extra value; expected `android.telephony.ims.extra.CODEC`, was `Codec` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DIALSTRING: + Inconsistent extra value; expected `android.telephony.ims.extra.DIALSTRING`, was `dialstring` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DISPLAY_TEXT: + Inconsistent extra value; expected `android.telephony.ims.extra.DISPLAY_TEXT`, was `DisplayText` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_EMERGENCY_CALL: + Inconsistent extra value; expected `android.telephony.ims.extra.EMERGENCY_CALL`, was `e_call` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_IS_CALL_PULL: + Inconsistent extra value; expected `android.telephony.ims.extra.IS_CALL_PULL`, was `CallPull` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OI: + Inconsistent extra value; expected `android.telephony.ims.extra.OI`, was `oi` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OIR: + Inconsistent extra value; expected `android.telephony.ims.extra.OIR`, was `oir` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_REMOTE_URI: + Inconsistent extra value; expected `android.telephony.ims.extra.REMOTE_URI`, was `remote_uri` +ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_USSD: + Inconsistent extra value; expected `android.telephony.ims.extra.USSD`, was `ussd` +ActionValue: android.telephony.ims.ImsReasonInfo#EXTRA_MSG_SERVICE_NOT_AUTHORIZED: + Inconsistent extra value; expected `android.telephony.ims.extra.MSG_SERVICE_NOT_AUTHORIZED`, was `Forbidden. Not Authorized for Service` +ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_CLEANUP: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_FILE_DESCRIPTOR_REQUEST: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FD_COUNT: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FINAL_URI: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FREE_URI_LIST: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_LIST: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_URI_LIST: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_SERVICE_ID: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILES_IN_USE: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILE_ROOT: + +ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_LIST: + + + +ArrayReturn: android.app.UiAutomation#executeShellCommandRw(String): + +ArrayReturn: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1: + +ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10: + +ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11: + +ArrayReturn: android.metrics.LogMaker#LogMaker(Object[]) parameter #0: + +ArrayReturn: android.metrics.LogMaker#deserialize(Object[]) parameter #0: + +ArrayReturn: android.metrics.LogMaker#serialize(): + +ArrayReturn: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]) parameter #0: + +ArrayReturn: android.os.HwBlob#wrapArray(boolean[]): + +ArrayReturn: android.os.HwBlob#wrapArray(byte[]): + +ArrayReturn: android.os.HwBlob#wrapArray(double[]): + +ArrayReturn: android.os.HwBlob#wrapArray(float[]): + +ArrayReturn: android.os.HwBlob#wrapArray(int[]): + +ArrayReturn: android.os.HwBlob#wrapArray(long[]): + +ArrayReturn: android.os.HwBlob#wrapArray(short[]): + +ArrayReturn: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor[], int[], boolean) parameter #0: + +ArrayReturn: android.os.NativeHandle#getFileDescriptors(): + +ArrayReturn: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]): + +ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1: + Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]` +ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1: + Method parameter should be Collection<ImsCallForwardInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsCallForwardInfo[]` +ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1: + Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]` +ArrayReturn: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0: + Method parameter should be Collection<Uri> (or subclass) instead of raw array; was `android.net.Uri[]` +ArrayReturn: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0: + +ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): + +ArrayReturn: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0: + +ArrayReturn: android.view.inspector.InspectableProperty#enumMapping(): + +ArrayReturn: android.view.inspector.InspectableProperty#flagMapping(): + + + +AutoBoxing: android.os.HwBlob#wrapArray(byte[]): + +AutoBoxing: android.os.HwBlob#wrapArray(double[]): + +AutoBoxing: android.os.HwBlob#wrapArray(float[]): + +AutoBoxing: android.os.HwBlob#wrapArray(int[]): + +AutoBoxing: android.os.HwBlob#wrapArray(long[]): + +AutoBoxing: android.os.HwBlob#wrapArray(short[]): + +AutoBoxing: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion(): + + + +BannedThrow: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]): + +BannedThrow: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]): + +BannedThrow: android.app.ActivityTaskManager#resizeStack(int, android.graphics.Rect): + +BannedThrow: android.app.ActivityTaskManager#setTaskWindowingMode(int, int, boolean): + +BannedThrow: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean): + +BannedThrow: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]): + +BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, byte[]): + +BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, int[]): + +BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, short[]): + +BannedThrow: android.media.audiofx.AudioEffect#getParameter(int[], short[]): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, byte[]): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, int): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, short): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], byte[]): + +BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], int[]): + +BannedThrow: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule): + +BannedThrow: android.media.audiopolicy.AudioMix.Builder#build(): + +BannedThrow: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo): + +BannedThrow: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat): + +BannedThrow: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int): + +BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object): + +BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int): + +BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object): + +BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int): + +BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix): + +BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix): + +BannedThrow: android.media.audiopolicy.AudioPolicy#setFocusDuckingBehavior(int): + +BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#addMix(android.media.audiopolicy.AudioMix): + +BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#setLooper(android.os.Looper): + +BannedThrow: android.os.HwBinder#getService(String, String): + +BannedThrow: android.os.HwBinder#getService(String, String, boolean): + +BannedThrow: android.os.Process#getThreadScheduler(int): + + + +CallbackInterface: android.app.prediction.AppPredictor.Callback: + +CallbackInterface: android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback: + +CallbackInterface: android.widget.Magnifier.Callback: + + + +CallbackMethodName: android.os.RemoteCallback: + + + +CompileTimeConstant: android.view.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED: + + + +ConcreteCollection: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill: + +ConcreteCollection: android.content.ContentCaptureOptions#ContentCaptureOptions(int, int, int, int, int, android.util.ArraySet<android.content.ComponentName>) parameter #5: + +ConcreteCollection: android.content.ContentCaptureOptions#whitelistedComponents: + +ConcreteCollection: android.database.sqlite.SQLiteDebug.PagerStats#dbStats: + +ConcreteCollection: android.os.HwParcel#readBoolVector(): + +ConcreteCollection: android.os.HwParcel#readDoubleVector(): + +ConcreteCollection: android.os.HwParcel#readFloatVector(): + +ConcreteCollection: android.os.HwParcel#readInt16Vector(): + +ConcreteCollection: android.os.HwParcel#readInt32Vector(): + +ConcreteCollection: android.os.HwParcel#readInt64Vector(): + +ConcreteCollection: android.os.HwParcel#readInt8Vector(): + +ConcreteCollection: android.os.HwParcel#readNativeHandleVector(): + +ConcreteCollection: android.os.HwParcel#readStringVector(): + +ConcreteCollection: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>) parameter #0: + +ConcreteCollection: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0: + +ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms(): + +ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationArgs(): + +ConcreteCollection: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>) parameter #2: + +ConcreteCollection: android.service.autofill.UserData#getFieldClassificationAlgorithms(): + +ConcreteCollection: android.telephony.ims.ImsConferenceState#mParticipants: + Field type is concrete collection (`java.util.HashMap`); must be higher-level interface + + +ContextFirst: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1: + + + +ContextNameSuffix: android.telephony.mbms.vendor.MbmsGroupCallServiceBase: + + + +EndsWithImpl: android.view.contentcapture.ViewNode.ViewStructureImpl: + + + +Enum: android.view.inspector.InspectableProperty.ValueType: + + + +EqualsAndHashCode: android.app.prediction.AppPredictionContext#equals(Object): + +EqualsAndHashCode: android.app.prediction.AppTarget#equals(Object): + +EqualsAndHashCode: android.app.prediction.AppTargetEvent#equals(Object): + +EqualsAndHashCode: android.net.apf.ApfCapabilities#equals(Object): + +EqualsAndHashCode: android.net.metrics.ApfProgramEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.ApfStats#equals(Object): + +EqualsAndHashCode: android.net.metrics.DhcpClientEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.IpManagerEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.IpReachabilityEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.NetworkEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.RaEvent#equals(Object): + +EqualsAndHashCode: android.net.metrics.ValidationProbeEvent#equals(Object): + +EqualsAndHashCode: android.os.IncidentManager.PendingReport#equals(Object): + +EqualsAndHashCode: android.os.StrictMode.ViolationInfo#hashCode(): + + + +ExecutorRegistration: android.app.AppOpsManager#startWatchingActive(int[], android.app.AppOpsManager.OnOpActiveChangedListener): + +ExecutorRegistration: android.app.AppOpsManager#stopWatchingActive(android.app.AppOpsManager.OnOpActiveChangedListener): + +ExecutorRegistration: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler): + +ExecutorRegistration: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper): + +ExecutorRegistration: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener): + +ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener): + +ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener): + +ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyVolumeCallback(android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback): + +ExecutorRegistration: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener): + +ExecutorRegistration: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener): + +ExecutorRegistration: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener, android.os.Handler): + +ExecutorRegistration: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler): + +ExecutorRegistration: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener): + Registration methods should have overload that accepts delivery Executor: `setListener` +ExecutorRegistration: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener): + Registration methods should have overload that accepts delivery Executor: `setListener` +ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int): + +ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback): + + + +ForbiddenSuperClass: android.app.AppDetailsActivity: + + + +GenericException: android.app.ActivityView#finalize(): + +GenericException: android.app.prediction.AppPredictor#finalize(): + +GenericException: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +GenericException: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +GenericException: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +GenericException: android.service.autofill.augmented.FillWindow#finalize(): + + + +GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByCriticalDeviceFunction(): + +GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByOEM(): + +GetterSetterNames: android.location.GnssClock#setBiasNanos(double): + +GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double): + +GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double): + +GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double): + +GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long): + +GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double): + +GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long): + +GetterSetterNames: android.location.GnssClock#setLeapSecond(int): + +GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double): + +GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float): + +GetterSetterNames: android.location.GnssMeasurement#setCodeType(String): + +GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double): + +GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored(): + +GetterSetterNames: android.os.IncidentReportArgs#isAll(): + +GetterSetterNames: android.service.notification.NotificationStats#setDirectReplied(): + +GetterSetterNames: android.service.notification.NotificationStats#setExpanded(): + +GetterSetterNames: android.service.notification.NotificationStats#setSeen(): + +GetterSetterNames: android.service.notification.NotificationStats#setSnoozed(): + +GetterSetterNames: android.service.notification.NotificationStats#setViewedSettings(): + +GetterSetterNames: android.view.View#isAutofilled(): + +GetterSetterNames: android.view.View#isDefaultFocusHighlightEnabled(): + + + +IllegalStateException: android.media.audiopolicy.AudioMix.Builder#build(): + + + +IntentBuilderName: android.app.backup.BackupManager#getConfigurationIntent(String): + +IntentBuilderName: android.app.backup.BackupManager#getDataManagementIntent(String): + + + +IntentName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE: + +IntentName: android.provider.Telephony.Sms.Intents#SMS_CARRIER_PROVISION_ACTION: + +IntentName: android.service.notification.Adjustment#KEY_CONTEXTUAL_ACTIONS: + + + +InterfaceConstant: android.service.autofill.AutofillFieldClassificationService#SERVICE_INTERFACE: + +InterfaceConstant: android.service.autofill.augmented.AugmentedAutofillService#SERVICE_INTERFACE: + +InterfaceConstant: android.service.contentcapture.ContentCaptureService#SERVICE_INTERFACE: + +InterfaceConstant: android.service.notification.NotificationAssistantService#SERVICE_INTERFACE: + +InterfaceConstant: android.telecom.PhoneAccountSuggestionService#SERVICE_INTERFACE: + + + +InternalField: android.telephony.ims.ImsConferenceState#mParticipants: + Internal field mParticipants must not be exposed + + +KotlinOperator: android.os.WorkSource#get(int): + + + +ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener: + +ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener: + +ListenerInterface: android.os.IncidentManager.AuthListener: + +ListenerInterface: android.telephony.ims.ImsCallSessionListener: + Listeners should be an interface, or otherwise renamed Callback: ImsCallSessionListener +ListenerInterface: android.telephony.ims.ImsUtListener: + Listeners should be an interface, or otherwise renamed Callback: ImsUtListener + + +ListenerLast: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #4: + +ListenerLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper) parameter #2: + +ListenerLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler) parameter #2: + +ListenerLast: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) parameter #1: + +ListenerLast: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #1: + + + +ManagerConstructor: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context): + + + +ManagerLookup: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int): + Managers must always be obtained from Context (`createForSubscriptionId`) +ManagerLookup: android.telephony.ims.ProvisioningManager#createForSubscriptionId(int): + Managers must always be obtained from Context (`createForSubscriptionId`) + + +MethodNameTense: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable(): + Unexpected tense; probably meant `enabled`, was `getCapabilitiesToEnable` + + +MethodNameUnits: android.telephony.ims.ImsCallForwardInfo#getTimeSeconds(): + Returned time values must be in milliseconds, was `getTimeSeconds` + + +MinMaxConstant: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS: + + + +MissingNullability: android.app.Activity#onMovedToDisplay(int, android.content.res.Configuration) parameter #1: + +MissingNullability: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int) parameter #0: + +MissingNullability: android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName) parameter #0: + +MissingNullability: android.app.ActivityManager#forceStopPackage(String) parameter #0: + +MissingNullability: android.app.ActivityManager#getPackageImportance(String) parameter #0: + +MissingNullability: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener) parameter #0: + +MissingNullability: android.app.ActivityManager#scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int) parameter #0: + +MissingNullability: android.app.ActivityManager.TaskDescription#getIconFilename(): + +MissingNullability: android.app.ActivityTaskManager#clearLaunchParamsForPackages(java.util.List<java.lang.String>) parameter #0: + +MissingNullability: android.app.ActivityTaskManager#listAllStacks(): + +MissingNullability: android.app.ActivityTaskManager#moveTopActivityToPinnedStack(int, android.graphics.Rect) parameter #1: + +MissingNullability: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]) parameter #0: + +MissingNullability: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]) parameter #0: + +MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #0: + +MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #1: + +MissingNullability: android.app.ActivityTaskManager#resizeStack(int, android.graphics.Rect) parameter #1: + +MissingNullability: android.app.ActivityTaskManager#resizeStack(int, android.graphics.Rect, boolean) parameter #1: + +MissingNullability: android.app.ActivityTaskManager#resizeTask(int, android.graphics.Rect) parameter #1: + +MissingNullability: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) parameter #4: + +MissingNullability: android.app.ActivityTaskManager#supportsMultiWindow(android.content.Context) parameter #0: + +MissingNullability: android.app.ActivityTaskManager#supportsSplitScreenMultiWindow(android.content.Context) parameter #0: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context) parameter #0: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #0: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #1: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #0: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #1: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #0: + +MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #1: + +MissingNullability: android.app.ActivityView#gatherTransparentRegion(android.graphics.Region) parameter #0: + +MissingNullability: android.app.ActivityView#onVisibilityChanged(android.view.View, int) parameter #0: + +MissingNullability: android.app.ActivityView#setCallback(android.app.ActivityView.StateCallback) parameter #0: + +MissingNullability: android.app.ActivityView#setForwardedInsets(android.graphics.Insets) parameter #0: + +MissingNullability: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle) parameter #1: + +MissingNullability: android.app.ActivityView.StateCallback#onActivityViewDestroyed(android.app.ActivityView) parameter #0: + +MissingNullability: android.app.ActivityView.StateCallback#onActivityViewReady(android.app.ActivityView) parameter #0: + +MissingNullability: android.app.ActivityView.StateCallback#onTaskCreated(int, android.content.ComponentName) parameter #1: + +MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0: + +MissingNullability: android.app.AppOpsManager#getOpStrs(): + +MissingNullability: android.app.AppOpsManager#isOperationActive(int, int, String) parameter #2: + +MissingNullability: android.app.AppOpsManager#opToPermission(int): + +MissingNullability: android.app.AppOpsManager#permissionToOpCode(String) parameter #0: + +MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #0: + +MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #2: + +MissingNullability: android.app.AppOpsManager#setMode(int, int, String, int) parameter #2: + +MissingNullability: android.app.AppOpsManager#setUidMode(String, int, int) parameter #0: + +MissingNullability: android.app.AppOpsManager.HistoricalOp#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.AppOpsManager.HistoricalOps#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.AppOpsManager.HistoricalUidOps#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.AppOpsManager.OnOpActiveChangedListener#onOpActiveChanged(int, int, String, boolean) parameter #2: + +MissingNullability: android.app.AppOpsManager.OpEntry#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.NotificationManager#allowAssistantAdjustment(String) parameter #0: + +MissingNullability: android.app.NotificationManager#disallowAssistantAdjustment(String) parameter #0: + +MissingNullability: android.app.NotificationManager#getEffectsSuppressor(): + +MissingNullability: android.app.NotificationManager#matchesCallFilter(android.os.Bundle) parameter #0: + +MissingNullability: android.app.PictureInPictureParams#getActions(): + +MissingNullability: android.app.PictureInPictureParams#getSourceRectHint(): + +MissingNullability: android.app.TimePickerDialog#getTimePicker(): + +MissingNullability: android.app.UiAutomation#executeShellCommandRw(String): + +MissingNullability: android.app.UiAutomation#executeShellCommandRw(String) parameter #0: + +MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #0: + +MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #1: + +MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #2: + +MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #0: + +MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #1: + +MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #2: + +MissingNullability: android.app.WallpaperManager#setWallpaperComponent(android.content.ComponentName) parameter #0: + +MissingNullability: android.app.WindowConfiguration#compareTo(android.app.WindowConfiguration) parameter #0: + +MissingNullability: android.app.WindowConfiguration#getAppBounds(): + +MissingNullability: android.app.WindowConfiguration#getBounds(): + +MissingNullability: android.app.WindowConfiguration#setAppBounds(android.graphics.Rect) parameter #0: + +MissingNullability: android.app.WindowConfiguration#setBounds(android.graphics.Rect) parameter #0: + +MissingNullability: android.app.WindowConfiguration#setTo(android.app.WindowConfiguration) parameter #0: + +MissingNullability: android.app.WindowConfiguration#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle): + +MissingNullability: android.app.admin.SecurityLog.SecurityEvent#SecurityEvent(long, byte[]) parameter #1: + +MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String): + +MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String) parameter #0: + +MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String): + +MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String) parameter #0: + +MissingNullability: android.app.backup.BackupManager#getDestinationString(String): + +MissingNullability: android.app.backup.BackupManager#getDestinationString(String) parameter #0: + +MissingNullability: android.app.prediction.AppPredictionSessionId#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.prediction.AppPredictor#getSessionId(): + +MissingNullability: android.app.prediction.AppTarget#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.prediction.AppTargetEvent#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.app.prediction.AppTargetId#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.content.AutofillOptions#forWhitelistingItself(): + +MissingNullability: android.content.AutofillOptions#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.content.ContentCaptureOptions#forWhitelistingItself(): + +MissingNullability: android.content.ContentCaptureOptions#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int): + +MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int) parameter #0: + +MissingNullability: android.content.Context#createPackageContextAsUser(String, int, android.os.UserHandle): + +MissingNullability: android.content.Context#createPackageContextAsUser(String, int, android.os.UserHandle) parameter #0: + +MissingNullability: android.content.Context#createPackageContextAsUser(String, int, android.os.UserHandle) parameter #2: + +MissingNullability: android.content.Context#getDisplay(): + +MissingNullability: android.content.Context#getUser(): + +MissingNullability: android.content.ContextWrapper#getDisplay(): + +MissingNullability: android.content.ContextWrapper#setContentCaptureOptions(android.content.ContentCaptureOptions) parameter #0: + +MissingNullability: android.content.pm.ActivityInfo#isTranslucentOrFloating(android.content.res.TypedArray) parameter #0: + +MissingNullability: android.content.pm.LauncherApps#LauncherApps(android.content.Context) parameter #0: + +MissingNullability: android.content.pm.PackageInstaller.SessionParams#setGrantedRuntimePermissions(String[]) parameter #0: + +MissingNullability: android.content.pm.PackageManager#getNamesForUids(int[]) parameter #0: + +MissingNullability: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context) parameter #0: + +MissingNullability: android.content.res.AssetManager#getOverlayableMap(String) parameter #0: + +MissingNullability: android.content.res.Configuration#windowConfiguration: + +MissingNullability: android.content.rollback.PackageRollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.content.rollback.RollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #1: + +MissingNullability: android.database.sqlite.SQLiteDebug#getDatabaseInfo(): + +MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#DbStats(String, long, long, int, int, int, int) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#cache: + +MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#dbName: + +MissingNullability: android.database.sqlite.SQLiteDebug.PagerStats#dbStats: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #1: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #2: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #3: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#cursorRequeried(android.database.Cursor) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]): + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #1: + +MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#setBindArguments(String[]) parameter #0: + +MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultJournalMode(): + +MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultSyncMode(): + +MissingNullability: android.database.sqlite.SQLiteGlobal#getWALSyncMode(): + +MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #0: + +MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #1: + +MissingNullability: android.graphics.drawable.AdaptiveIconDrawable#getSafeZone(): + +MissingNullability: android.graphics.drawable.ColorDrawable#getXfermode(): + +MissingNullability: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #0: + +MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getBucketBoundaries(): + +MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getLocalDate(): + +MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getStats(): + +MissingNullability: android.hardware.display.AmbientBrightnessDayStats#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0: + +MissingNullability: android.hardware.display.BrightnessChangeEvent#luxTimestamps: + +MissingNullability: android.hardware.display.BrightnessChangeEvent#luxValues: + +MissingNullability: android.hardware.display.BrightnessChangeEvent#packageName: + +MissingNullability: android.hardware.display.BrightnessChangeEvent#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.hardware.display.BrightnessConfiguration#getCurve(): + +MissingNullability: android.hardware.display.BrightnessConfiguration#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #0: + +MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #1: + +MissingNullability: android.hardware.display.BrightnessCorrection#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.hardware.display.DisplayManager#getAmbientBrightnessStats(): + +MissingNullability: android.hardware.display.DisplayManager#getBrightnessConfiguration(): + +MissingNullability: android.hardware.display.DisplayManager#getBrightnessEvents(): + +MissingNullability: android.hardware.display.DisplayManager#getStableDisplaySize(): + +MissingNullability: android.hardware.display.DisplayManager#setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration) parameter #0: + +MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0: + +MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0: + +MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #0: + +MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1: + +MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0: + +MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0: + +MissingNullability: android.location.LocationManager#getTestProviderCurrentRequests(String) parameter #0: + +MissingNullability: android.location.LocationRequest#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.media.AudioFocusInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #3: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #4: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #6: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #3: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #4: + +MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #6: + +MissingNullability: android.media.PlaybackParams#setAudioStretchMode(int): + +MissingNullability: android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL: + +MissingNullability: android.media.audiofx.AudioEffect#byteArrayToInt(byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, byte[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, int[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, short[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#intToByteArray(int): + +MissingNullability: android.media.audiofx.AudioEffect#isEffectTypeAvailable(java.util.UUID) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(int, byte[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #1: + +MissingNullability: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect#shortToByteArray(short): + +MissingNullability: android.media.audiofx.AudioEffect.Descriptor#Descriptor(android.os.Parcel) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect.Descriptor#writeToParcel(android.os.Parcel) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #0: + +MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #2: + +MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #3: + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#build(): + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo): + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat): + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object) parameter #1: + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#build(): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object) parameter #1: + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int): + +MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix): + +MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix): + +MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy#setRegistration(String) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy#toLogFriendlyString(): + +MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusAbandon(android.media.AudioFocusInfo) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusGrant(android.media.AudioFocusInfo, int) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusLoss(android.media.AudioFocusInfo, boolean) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(android.media.AudioFocusInfo, int) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener#onMixStateUpdate(android.media.audiopolicy.AudioMix) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#Builder(android.content.Context) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener) parameter #0: + +MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener) parameter #0: + +MissingNullability: android.metrics.LogMaker#LogMaker(Object[]) parameter #0: + +MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object): + +MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object) parameter #1: + +MissingNullability: android.metrics.LogMaker#clearCategory(): + +MissingNullability: android.metrics.LogMaker#clearPackageName(): + +MissingNullability: android.metrics.LogMaker#clearSubtype(): + +MissingNullability: android.metrics.LogMaker#clearTaggedData(int): + +MissingNullability: android.metrics.LogMaker#clearType(): + +MissingNullability: android.metrics.LogMaker#deserialize(Object[]) parameter #0: + +MissingNullability: android.metrics.LogMaker#getCounterName(): + +MissingNullability: android.metrics.LogMaker#getPackageName(): + +MissingNullability: android.metrics.LogMaker#getTaggedData(int): + +MissingNullability: android.metrics.LogMaker#isSubsetOf(android.metrics.LogMaker) parameter #0: + +MissingNullability: android.metrics.LogMaker#isValidValue(Object) parameter #0: + +MissingNullability: android.metrics.LogMaker#serialize(): + +MissingNullability: android.metrics.LogMaker#setCategory(int): + +MissingNullability: android.metrics.LogMaker#setPackageName(String): + +MissingNullability: android.metrics.LogMaker#setPackageName(String) parameter #0: + +MissingNullability: android.metrics.LogMaker#setSubtype(int): + +MissingNullability: android.metrics.LogMaker#setType(int): + +MissingNullability: android.metrics.MetricsReader#next(): + +MissingNullability: android.net.NetworkCapabilities#getCapabilities(): + +MissingNullability: android.net.StaticIpConfiguration#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.net.TestNetworkInterface#CREATOR: + +MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #0: + +MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #1: + +MissingNullability: android.net.TestNetworkInterface#getFileDescriptor(): + +MissingNullability: android.net.TestNetworkInterface#getInterfaceName(): + +MissingNullability: android.net.TestNetworkInterface#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.net.TestNetworkManager#createTapInterface(): + +MissingNullability: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]): + +MissingNullability: android.net.apf.ApfCapabilities#CREATOR: + +MissingNullability: android.net.apf.ApfCapabilities#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.net.metrics.DhcpClientEvent.Builder#setMsg(String) parameter #0: + +MissingNullability: android.os.Build#is64BitAbi(String) parameter #0: + +MissingNullability: android.os.Build.VERSION#ACTIVE_CODENAMES: + +MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...): + +MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #0: + +MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #1: + +MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #0: + +MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #1: + +MissingNullability: android.os.HwBinder#getService(String, String): + +MissingNullability: android.os.HwBinder#getService(String, String) parameter #0: + +MissingNullability: android.os.HwBinder#getService(String, String) parameter #1: + +MissingNullability: android.os.HwBinder#getService(String, String, boolean): + +MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #0: + +MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #1: + +MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1: + +MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2: + +MissingNullability: android.os.HwBinder#registerService(String) parameter #0: + +MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1: + +MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2: + +MissingNullability: android.os.HwBlob#copyToBoolArray(long, boolean[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToDoubleArray(long, double[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToFloatArray(long, float[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToInt16Array(long, short[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToInt32Array(long, int[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToInt64Array(long, long[], int) parameter #1: + +MissingNullability: android.os.HwBlob#copyToInt8Array(long, byte[], int) parameter #1: + +MissingNullability: android.os.HwBlob#getString(long): + +MissingNullability: android.os.HwBlob#putBlob(long, android.os.HwBlob) parameter #1: + +MissingNullability: android.os.HwBlob#putBoolArray(long, boolean[]) parameter #1: + +MissingNullability: android.os.HwBlob#putDoubleArray(long, double[]) parameter #1: + +MissingNullability: android.os.HwBlob#putFloatArray(long, float[]) parameter #1: + +MissingNullability: android.os.HwBlob#putInt16Array(long, short[]) parameter #1: + +MissingNullability: android.os.HwBlob#putInt32Array(long, int[]) parameter #1: + +MissingNullability: android.os.HwBlob#putInt64Array(long, long[]) parameter #1: + +MissingNullability: android.os.HwBlob#putInt8Array(long, byte[]) parameter #1: + +MissingNullability: android.os.HwBlob#putString(long, String) parameter #1: + +MissingNullability: android.os.HwBlob#wrapArray(boolean[]): + +MissingNullability: android.os.HwBlob#wrapArray(byte[]): + +MissingNullability: android.os.HwBlob#wrapArray(double[]): + +MissingNullability: android.os.HwBlob#wrapArray(float[]): + +MissingNullability: android.os.HwBlob#wrapArray(int[]): + +MissingNullability: android.os.HwBlob#wrapArray(long[]): + +MissingNullability: android.os.HwBlob#wrapArray(short[]): + +MissingNullability: android.os.HwParcel#enforceInterface(String) parameter #0: + +MissingNullability: android.os.HwParcel#readBoolVector(): + +MissingNullability: android.os.HwParcel#readBuffer(long): + +MissingNullability: android.os.HwParcel#readDoubleVector(): + +MissingNullability: android.os.HwParcel#readEmbeddedBuffer(long, long, long, boolean): + +MissingNullability: android.os.HwParcel#readFloatVector(): + +MissingNullability: android.os.HwParcel#readInt16Vector(): + +MissingNullability: android.os.HwParcel#readInt32Vector(): + +MissingNullability: android.os.HwParcel#readInt64Vector(): + +MissingNullability: android.os.HwParcel#readInt8Vector(): + +MissingNullability: android.os.HwParcel#readString(): + +MissingNullability: android.os.HwParcel#readStringVector(): + +MissingNullability: android.os.HwParcel#readStrongBinder(): + +MissingNullability: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0: + +MissingNullability: android.os.HwParcel#writeBuffer(android.os.HwBlob) parameter #0: + +MissingNullability: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0: + +MissingNullability: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0: + +MissingNullability: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0: + +MissingNullability: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0: + +MissingNullability: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0: + +MissingNullability: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0: + +MissingNullability: android.os.HwParcel#writeInterfaceToken(String) parameter #0: + +MissingNullability: android.os.HwParcel#writeString(String) parameter #0: + +MissingNullability: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0: + +MissingNullability: android.os.HwParcel#writeStrongBinder(android.os.IHwBinder) parameter #0: + +MissingNullability: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long) parameter #0: + +MissingNullability: android.os.IHwBinder#queryLocalInterface(String): + +MissingNullability: android.os.IHwBinder#queryLocalInterface(String) parameter #0: + +MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1: + +MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2: + +MissingNullability: android.os.IHwBinder#unlinkToDeath(android.os.IHwBinder.DeathRecipient) parameter #0: + +MissingNullability: android.os.IHwInterface#asBinder(): + +MissingNullability: android.os.IncidentManager#approveReport(android.net.Uri) parameter #0: + +MissingNullability: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener) parameter #0: + +MissingNullability: android.os.IncidentManager#deleteIncidentReports(android.net.Uri) parameter #0: + +MissingNullability: android.os.IncidentManager#denyReport(android.net.Uri) parameter #0: + +MissingNullability: android.os.IncidentManager#getIncidentReport(android.net.Uri) parameter #0: + +MissingNullability: android.os.IncidentManager#getIncidentReportList(String) parameter #0: + +MissingNullability: android.os.IncidentManager#getPendingReports(): + +MissingNullability: android.os.IncidentManager#reportIncident(android.os.IncidentReportArgs) parameter #0: + +MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #1: + +MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #3: + +MissingNullability: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel) parameter #0: + +MissingNullability: android.os.IncidentManager.IncidentReport#getInputStream(): + +MissingNullability: android.os.IncidentManager.IncidentReport#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel) parameter #0: + +MissingNullability: android.os.IncidentReportArgs#addHeader(byte[]) parameter #0: + +MissingNullability: android.os.IncidentReportArgs#readFromParcel(android.os.Parcel) parameter #0: + +MissingNullability: android.os.IncidentReportArgs#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor): + +MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0: + +MissingNullability: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener) parameter #0: + +MissingNullability: android.os.RemoteCallback#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.StrictMode#setViolationLogger(android.os.StrictMode.ViolationLogger) parameter #0: + +MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel) parameter #0: + +MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel, boolean) parameter #0: + +MissingNullability: android.os.StrictMode.ViolationInfo#broadcastIntentAction: + +MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #0: + +MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #1: + +MissingNullability: android.os.StrictMode.ViolationInfo#getStackTrace(): + +MissingNullability: android.os.StrictMode.ViolationInfo#getViolationClass(): + +MissingNullability: android.os.StrictMode.ViolationInfo#getViolationDetails(): + +MissingNullability: android.os.StrictMode.ViolationInfo#tags: + +MissingNullability: android.os.StrictMode.ViolationInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.StrictMode.ViolationLogger#log(android.os.StrictMode.ViolationInfo) parameter #0: + +MissingNullability: android.os.UserHandle#of(int): + +MissingNullability: android.os.VibrationEffect#RINGTONES: + +MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #0: + +MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1: + +MissingNullability: android.os.VibrationEffect#get(int): + +MissingNullability: android.os.VibrationEffect#get(int, boolean): + +MissingNullability: android.os.VibrationEffect.OneShot#OneShot(android.os.Parcel) parameter #0: + +MissingNullability: android.os.VibrationEffect.OneShot#scale(float, int): + +MissingNullability: android.os.VibrationEffect.OneShot#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.VibrationEffect.Prebaked#Prebaked(android.os.Parcel) parameter #0: + +MissingNullability: android.os.VibrationEffect.Prebaked#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.VibrationEffect.Waveform#Waveform(android.os.Parcel) parameter #0: + +MissingNullability: android.os.VibrationEffect.Waveform#Waveform(long[], int[], int) parameter #0: + +MissingNullability: android.os.VibrationEffect.Waveform#Waveform(long[], int[], int) parameter #1: + +MissingNullability: android.os.VibrationEffect.Waveform#getAmplitudes(): + +MissingNullability: android.os.VibrationEffect.Waveform#getTimings(): + +MissingNullability: android.os.VibrationEffect.Waveform#scale(float, int): + +MissingNullability: android.os.VibrationEffect.Waveform#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.VintfObject#getHalNamesAndVersions(): + +MissingNullability: android.os.VintfObject#getSepolicyVersion(): + +MissingNullability: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion(): + +MissingNullability: android.os.VintfObject#getVndkSnapshots(): + +MissingNullability: android.os.VintfObject#report(): + +MissingNullability: android.os.VintfRuntimeInfo#getCpuInfo(): + +MissingNullability: android.os.VintfRuntimeInfo#getHardwareId(): + +MissingNullability: android.os.VintfRuntimeInfo#getKernelVersion(): + +MissingNullability: android.os.VintfRuntimeInfo#getNodeName(): + +MissingNullability: android.os.VintfRuntimeInfo#getOsName(): + +MissingNullability: android.os.VintfRuntimeInfo#getOsRelease(): + +MissingNullability: android.os.VintfRuntimeInfo#getOsVersion(): + +MissingNullability: android.os.WorkSource#add(int, String) parameter #1: + +MissingNullability: android.os.WorkSource#addReturningNewbs(android.os.WorkSource) parameter #0: + +MissingNullability: android.os.WorkSource#getName(int): + +MissingNullability: android.os.WorkSource#setReturningDiffs(android.os.WorkSource) parameter #0: + +MissingNullability: android.os.health.HealthKeys.Constants#Constants(Class) parameter #0: + +MissingNullability: android.os.health.HealthKeys.Constants#getDataType(): + +MissingNullability: android.os.health.HealthKeys.Constants#getKeys(int): + +MissingNullability: android.os.health.HealthStats#HealthStats(android.os.Parcel) parameter #0: + +MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel) parameter #0: + +MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.health.HealthStatsWriter) parameter #0: + +MissingNullability: android.os.health.HealthStatsParceler#getHealthStats(): + +MissingNullability: android.os.health.HealthStatsParceler#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.os.health.HealthStatsWriter#HealthStatsWriter(android.os.health.HealthKeys.Constants) parameter #0: + +MissingNullability: android.os.health.HealthStatsWriter#addMeasurements(int, String, long) parameter #1: + +MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #1: + +MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #2: + +MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #1: + +MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #2: + +MissingNullability: android.os.health.HealthStatsWriter#flattenToParcel(android.os.Parcel) parameter #0: + +MissingNullability: android.os.storage.StorageVolume#getPath(): + +MissingNullability: android.permission.RuntimePermissionPresentationInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.provider.CalendarContract.Calendars#SYNC_WRITABLE_COLUMNS: + +MissingNullability: android.provider.CalendarContract.Events#SYNC_WRITABLE_COLUMNS: + +MissingNullability: android.provider.ContactsContract.CommonDataKinds.Phone#ENTERPRISE_CONTENT_URI: + +MissingNullability: android.provider.ContactsContract.RawContactsEntity#CORP_CONTENT_URI: + +MissingNullability: android.provider.DeviceConfig#getProperty(String, String): + +MissingNullability: android.provider.DeviceConfig#getString(String, String, String): + +MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #0: + +MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #1: + +MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #2: + +MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #0: + +MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #1: + +MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #2: + +MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File): + +MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #0: + +MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #1: + +MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File): + +MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #0: + +MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #1: + +MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #0: + +MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #1: + +MissingNullability: android.provider.MediaStore#waitForIdle(android.content.Context) parameter #0: + +MissingNullability: android.security.KeyStoreException#KeyStoreException(int, String) parameter #1: + +MissingNullability: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]) parameter #0: + +MissingNullability: android.security.keystore.KeyProtection.Builder#setBoundToSpecificSecureUserId(long): + +MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent): + +MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent) parameter #0: + +MissingNullability: android.service.autofill.CompositeUserData#getCategoryIds(): + +MissingNullability: android.service.autofill.CompositeUserData#getDefaultFieldClassificationArgs(): + +MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms(): + +MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationArgs(): + +MissingNullability: android.service.autofill.CompositeUserData#getValues(): + +MissingNullability: android.service.autofill.CompositeUserData#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.service.autofill.UserData#getFieldClassificationAlgorithms(): + +MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: + +MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1: + +MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2: + +MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0: + +MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: + +MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1: + +MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2: + +MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #0: + +MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #1: + +MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #2: + +MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #3: + +MissingNullability: android.service.notification.Adjustment#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0: + +MissingNullability: android.service.notification.NotificationStats#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #0: + +MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #1: + +MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #2: + +MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel) parameter #0: + +MissingNullability: android.service.notification.SnoozeCriterion#getConfirmation(): + +MissingNullability: android.service.notification.SnoozeCriterion#getExplanation(): + +MissingNullability: android.service.notification.SnoozeCriterion#getId(): + +MissingNullability: android.service.notification.SnoozeCriterion#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.telecom.Call.Details#getTelecomCallId(): + +MissingNullability: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallFurther(boolean): + +MissingNullability: android.telecom.Conference#getPrimaryConnection(): + +MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent): + +MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent) parameter #0: + +MissingNullability: android.telephony.CallQuality#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `dest` in method `writeToParcel` +MissingNullability: android.telephony.DataSpecificRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.telephony.LteVopsSupportInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.telephony.NetworkRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.telephony.ServiceState#addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo) parameter #0: + +MissingNullability: android.telephony.ServiceState#setCellBandwidths(int[]) parameter #0: + +MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #0: + +MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #1: + +MissingNullability: android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage(String) parameter #0: + +MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent): + Missing nullability on method `getCarrierPackageNamesForIntent` return +MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent) parameter #0: + Missing nullability on parameter `intent` in method `getCarrierPackageNamesForIntent` +MissingNullability: android.telephony.TelephonyManager#getLine1AlphaTag(): + +MissingNullability: android.telephony.TelephonyManager#getRadioHalVersion(): + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #0: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #1: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #2: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #3: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #4: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #5: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #6: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #0: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #1: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #2: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #3: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #4: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #5: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #6: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #7: + +MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #8: + +MissingNullability: android.telephony.ims.ImsCallForwardInfo#getNumber(): + Missing nullability on method `getNumber` return +MissingNullability: android.telephony.ims.ImsCallForwardInfo#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #2: + Missing nullability on parameter `callExtras` in method `ImsCallProfile` +MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #3: + Missing nullability on parameter `mediaProfile` in method `ImsCallProfile` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String): + Missing nullability on method `getCallExtra` return +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String) parameter #0: + Missing nullability on parameter `name` in method `getCallExtra` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String): + Missing nullability on method `getCallExtra` return +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #0: + Missing nullability on parameter `name` in method `getCallExtra` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #1: + Missing nullability on parameter `defaultValue` in method `getCallExtra` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String) parameter #0: + Missing nullability on parameter `name` in method `getCallExtraBoolean` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String, boolean) parameter #0: + Missing nullability on parameter `name` in method `getCallExtraBoolean` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String) parameter #0: + Missing nullability on parameter `name` in method `getCallExtraInt` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String, int) parameter #0: + Missing nullability on parameter `name` in method `getCallExtraInt` +MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtras(): + Missing nullability on method `getCallExtras` return +MissingNullability: android.telephony.ims.ImsCallProfile#getMediaProfile(): + Missing nullability on method `getMediaProfile` return +MissingNullability: android.telephony.ims.ImsCallProfile#getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `callProfile` in method `getVideoStateFromImsCallProfile` +MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #0: + Missing nullability on parameter `name` in method `setCallExtra` +MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #1: + Missing nullability on parameter `value` in method `setCallExtra` +MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraBoolean(String, boolean) parameter #0: + Missing nullability on parameter `name` in method `setCallExtraBoolean` +MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraInt(String, int) parameter #0: + Missing nullability on parameter `name` in method `setCallExtraInt` +MissingNullability: android.telephony.ims.ImsCallProfile#updateCallExtras(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `updateCallExtras` +MissingNullability: android.telephony.ims.ImsCallProfile#updateCallType(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `updateCallType` +MissingNullability: android.telephony.ims.ImsCallProfile#updateMediaProfile(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `updateMediaProfile` +MissingNullability: android.telephony.ims.ImsCallProfile#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionConferenceExtendFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `newSession` in method `callSessionConferenceExtendReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1: + Missing nullability on parameter `profile` in method `callSessionConferenceExtendReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `newSession` in method `callSessionConferenceExtended` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1: + Missing nullability on parameter `profile` in method `callSessionConferenceExtended` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState) parameter #0: + Missing nullability on parameter `state` in method `callSessionConferenceStateUpdated` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo) parameter #2: + Missing nullability on parameter `reasonInfo` in method `callSessionHandover` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo) parameter #2: + Missing nullability on parameter `reasonInfo` in method `callSessionHandoverFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHeld(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionHeld` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionHoldFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldReceived(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionHoldReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiated(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionInitiated` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionInitiatedFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionInviteParticipantsRequestFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase) parameter #0: + Missing nullability on parameter `newSession` in method `callSessionMergeComplete` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionMergeFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `newSession` in method `callSessionMergeStarted` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1: + Missing nullability on parameter `profile` in method `callSessionMergeStarted` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionProgressing` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionRemoveParticipantsRequestFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionResumeFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeReceived(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionResumeReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumed(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionResumed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttMessageReceived(String) parameter #0: + Missing nullability on parameter `rttMessage` in method `callSessionRttMessageReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `callProfile` in method `callSessionRttModifyRequestReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification) parameter #0: + Missing nullability on parameter `suppSrvNotification` in method `callSessionSuppServiceReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionTerminated(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionTerminated` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `reasonInfo` in method `callSessionUpdateFailed` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateReceived(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionUpdateReceived` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdated(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `profile` in method `callSessionUpdated` +MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUssdMessageReceived(int, String) parameter #1: + Missing nullability on parameter `ussdMessage` in method `callSessionUssdMessageReceived` +MissingNullability: android.telephony.ims.ImsConferenceState#getConnectionStateForStatus(String) parameter #0: + Missing nullability on parameter `status` in method `getConnectionStateForStatus` +MissingNullability: android.telephony.ims.ImsConferenceState#mParticipants: + Missing nullability on field `mParticipants` in class `class android.telephony.ims.ImsConferenceState` +MissingNullability: android.telephony.ims.ImsConferenceState#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsExternalCallState#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsReasonInfo#ImsReasonInfo(int, int, String) parameter #2: + Missing nullability on parameter `extraMessage` in method `ImsReasonInfo` +MissingNullability: android.telephony.ims.ImsReasonInfo#getExtraMessage(): + Missing nullability on method `getExtraMessage` return +MissingNullability: android.telephony.ims.ImsReasonInfo#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsService#createMmTelFeature(int): + Missing nullability on method `createMmTelFeature` return +MissingNullability: android.telephony.ims.ImsService#createRcsFeature(int): + Missing nullability on method `createRcsFeature` return +MissingNullability: android.telephony.ims.ImsService#getConfig(int): + Missing nullability on method `getConfig` return +MissingNullability: android.telephony.ims.ImsService#getRegistration(int): + Missing nullability on method `getRegistration` return +MissingNullability: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) parameter #0: + Missing nullability on parameter `c` in method `onUpdateSupportedImsFeatures` +MissingNullability: android.telephony.ims.ImsService#querySupportedImsFeatures(): + Missing nullability on method `querySupportedImsFeatures` return +MissingNullability: android.telephony.ims.ImsSsData#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsSsInfo#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsStreamMediaProfile#copyFrom(android.telephony.ims.ImsStreamMediaProfile) parameter #0: + Missing nullability on parameter `profile` in method `copyFrom` +MissingNullability: android.telephony.ims.ImsStreamMediaProfile#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #4: + Missing nullability on parameter `number` in method `ImsSuppServiceNotification` +MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #5: + Missing nullability on parameter `history` in method `ImsSuppServiceNotification` +MissingNullability: android.telephony.ims.ImsSuppServiceNotification#history: + Missing nullability on field `history` in class `class android.telephony.ims.ImsSuppServiceNotification` +MissingNullability: android.telephony.ims.ImsSuppServiceNotification#number: + Missing nullability on field `number` in class `class android.telephony.ims.ImsSuppServiceNotification` +MissingNullability: android.telephony.ims.ImsSuppServiceNotification#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `out` in method `writeToParcel` +MissingNullability: android.telephony.ims.ImsUtListener#onSupplementaryServiceIndication(android.telephony.ims.ImsSsData) parameter #0: + Missing nullability on parameter `ssData` in method `onSupplementaryServiceIndication` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1: + Missing nullability on parameter `cbInfo` in method `onUtConfigurationCallBarringQueried` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1: + Missing nullability on parameter `cfInfo` in method `onUtConfigurationCallForwardQueried` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1: + Missing nullability on parameter `cwInfo` in method `onUtConfigurationCallWaitingQueried` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueried(int, android.os.Bundle) parameter #1: + Missing nullability on parameter `configuration` in method `onUtConfigurationQueried` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1: + Missing nullability on parameter `error` in method `onUtConfigurationQueryFailed` +MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1: + Missing nullability on parameter `error` in method `onUtConfigurationUpdateFailed` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities) parameter #0: + Missing nullability on parameter `CameraCapabilities` in method `changeCameraCapabilities` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #0: + Missing nullability on parameter `fromProfile` in method `onSendSessionModifyRequest` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1: + Missing nullability on parameter `toProfile` in method `onSendSessionModifyRequest` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyResponse(android.telecom.VideoProfile) parameter #0: + Missing nullability on parameter `responseProfile` in method `onSendSessionModifyResponse` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String) parameter #0: + Missing nullability on parameter `cameraId` in method `onSetCamera` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String, int) parameter #0: + Missing nullability on parameter `cameraId` in method `onSetCamera` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetDisplaySurface(android.view.Surface) parameter #0: + Missing nullability on parameter `surface` in method `onSetDisplaySurface` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPauseImage(android.net.Uri) parameter #0: + Missing nullability on parameter `uri` in method `onSetPauseImage` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPreviewSurface(android.view.Surface) parameter #0: + Missing nullability on parameter `surface` in method `onSetPreviewSurface` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyRequest(android.telecom.VideoProfile) parameter #0: + Missing nullability on parameter `VideoProfile` in method `receiveSessionModifyRequest` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1: + Missing nullability on parameter `requestedProfile` in method `receiveSessionModifyResponse` +MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #2: + Missing nullability on parameter `responseProfile` in method `receiveSessionModifyResponse` +MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToDisable(): + Missing nullability on method `getCapabilitiesToDisable` return +MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable(): + Missing nullability on method `getCapabilitiesToEnable` return +MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `dest` in method `writeToParcel` +MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #0: + Missing nullability on parameter `request` in method `changeEnabledCapabilities` +MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #1: + Missing nullability on parameter `c` in method `changeEnabledCapabilities` +MissingNullability: android.telephony.ims.feature.MmTelFeature#queryCapabilityStatus(): + Missing nullability on method `queryCapabilityStatus` return +MissingNullability: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities) parameter #0: + Missing nullability on parameter `c` in method `MmTelCapabilities` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#accept(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1: + Missing nullability on parameter `profile` in method `accept` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#deflect(String) parameter #0: + Missing nullability on parameter `deflectNumber` in method `deflect` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#extendToConference(String[]) parameter #0: + Missing nullability on parameter `participants` in method `extendToConference` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallId(): + Missing nullability on method `getCallId` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallProfile(): + Missing nullability on method `getCallProfile` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getImsVideoCallProvider(): + Missing nullability on method `getImsVideoCallProvider` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getLocalCallProfile(): + Missing nullability on method `getLocalCallProfile` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String): + Missing nullability on method `getProperty` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String) parameter #0: + Missing nullability on parameter `name` in method `getProperty` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getRemoteCallProfile(): + Missing nullability on method `getRemoteCallProfile` return +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#hold(android.telephony.ims.ImsStreamMediaProfile) parameter #0: + Missing nullability on parameter `profile` in method `hold` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#inviteParticipants(String[]) parameter #0: + Missing nullability on parameter `participants` in method `inviteParticipants` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#removeParticipants(String[]) parameter #0: + Missing nullability on parameter `participants` in method `removeParticipants` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#resume(android.telephony.ims.ImsStreamMediaProfile) parameter #0: + Missing nullability on parameter `profile` in method `resume` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendDtmf(char, android.os.Message) parameter #1: + Missing nullability on parameter `result` in method `sendDtmf` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttMessage(String) parameter #0: + Missing nullability on parameter `rttMessage` in method `sendRttMessage` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttModifyRequest(android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `toProfile` in method `sendRttModifyRequest` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendUssd(String) parameter #0: + Missing nullability on parameter `ussdMessage` in method `sendUssd` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener) parameter #0: + Missing nullability on parameter `listener` in method `setListener` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `callee` in method `start` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #1: + Missing nullability on parameter `profile` in method `start` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #0: + Missing nullability on parameter `participants` in method `startConference` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #1: + Missing nullability on parameter `profile` in method `startConference` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#update(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1: + Missing nullability on parameter `profile` in method `update` +MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase.State#toString(int): + Missing nullability on method `toString` return +MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#getConfigString(int): + Missing nullability on method `getConfigString` return +MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#notifyProvisionedValueChanged(int, String) parameter #1: + Missing nullability on parameter `value` in method `notifyProvisionedValueChanged` +MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#setConfig(int, String) parameter #1: + Missing nullability on parameter `value` in method `setConfig` +MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#getServiceFeatures(): + Missing nullability on method `getServiceFeatures` return +MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#writeToParcel(android.os.Parcel, int) parameter #0: + Missing nullability on parameter `dest` in method `writeToParcel` +MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int): + Missing nullability on method `addFeature` return +MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#build(): + Missing nullability on method `build` return +MissingNullability: android.telephony.ims.stub.ImsMultiEndpointImplBase#onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>) parameter #0: + Missing nullability on parameter `externalCallDialogs` in method `onImsExternalCallStateUpdate` +MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onDeregistered(android.telephony.ims.ImsReasonInfo) parameter #0: + Missing nullability on parameter `info` in method `onDeregistered` +MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0: + Missing nullability on parameter `uris` in method `onSubscriberAssociatedUriChanged` +MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1: + Missing nullability on parameter `info` in method `onTechnologyChangeFailed` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#getSmsFormat(): + Missing nullability on method `getSmsFormat` return +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #1: + Missing nullability on parameter `format` in method `onSmsReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #2: + Missing nullability on parameter `pdu` in method `onSmsReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1: + Missing nullability on parameter `format` in method `onSmsStatusReportReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2: + Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #2: + Missing nullability on parameter `format` in method `onSmsStatusReportReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #3: + Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #2: + Missing nullability on parameter `format` in method `sendSms` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #3: + Missing nullability on parameter `smsc` in method `sendSms` +MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #5: + Missing nullability on parameter `pdu` in method `sendSms` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1: + Missing nullability on parameter `number` in method `queryCallForward` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0: + Missing nullability on parameter `listener` in method `setListener` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0: + Missing nullability on parameter `ssInfo` in method `transact` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarring(int, int, String[]) parameter #2: + Missing nullability on parameter `barrList` in method `updateCallBarring` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarringForServiceClass(int, int, String[], int) parameter #2: + Missing nullability on parameter `barrList` in method `updateCallBarringForServiceClass` +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallForward(int, int, String, int, int) parameter #2: + Missing nullability on parameter `number` in method `updateCallForward` +MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String): + +MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0: + +MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #0: + +MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #1: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #0: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #1: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #2: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #3: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #4: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #5: + +MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #6: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #0: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #1: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #2: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #3: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #4: + +MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #5: + +MissingNullability: android.telephony.mbms.UriPathPair#getContentUri(): + +MissingNullability: android.telephony.mbms.UriPathPair#getFilePathUri(): + +MissingNullability: android.telephony.mbms.UriPathPair#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#asBinder(): + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent): + +MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#asBinder(): + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #2: + +MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String) parameter #1: + +MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String): + +MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #0: + +MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #1: + +MissingNullability: android.text.Selection.MemoryTextWatcher#afterTextChanged(android.text.Editable) parameter #0: + +MissingNullability: android.text.Selection.MemoryTextWatcher#beforeTextChanged(CharSequence, int, int, int) parameter #0: + +MissingNullability: android.text.Selection.MemoryTextWatcher#onTextChanged(CharSequence, int, int, int) parameter #0: + +MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene): + +MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene) parameter #0: + +MissingNullability: android.util.FeatureFlagUtils#getAllFeatureFlags(): + +MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #0: + +MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #1: + +MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #0: + +MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #1: + +MissingNullability: android.util.TimeUtils#formatDuration(long): + +MissingNullability: android.util.proto.EncodedBuffer#dumpBuffers(String) parameter #0: + +MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #0: + +MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #1: + +MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #2: + +MissingNullability: android.util.proto.EncodedBuffer#getBytes(int): + +MissingNullability: android.util.proto.EncodedBuffer#getDebugString(): + +MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[]) parameter #0: + +MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[], int, int) parameter #0: + +MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0: + +MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.OutputStream) parameter #0: + +MissingNullability: android.util.proto.ProtoOutputStream#dump(String) parameter #0: + +MissingNullability: android.util.proto.ProtoOutputStream#getBytes(): + +MissingNullability: android.util.proto.ProtoOutputStream#write(long, String) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#write(long, byte[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeBytes(long, byte[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeObject(long, byte[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedBool(long, boolean[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedDouble(long, double[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedEnum(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed32(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed64(long, long[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedFloat(long, float[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt32(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt64(long, long[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed32(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed64(long, long[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt32(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt64(long, long[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt32(long, int[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt64(long, long[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedBytes(long, byte[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedObject(long, byte[]) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedString(long, String) parameter #1: + +MissingNullability: android.util.proto.ProtoOutputStream#writeString(long, String) parameter #1: + +MissingNullability: android.util.proto.ProtoParseException#ProtoParseException(String) parameter #0: + +MissingNullability: android.util.proto.ProtoStream#FIELD_TYPE_NAMES: + +MissingNullability: android.util.proto.ProtoStream#getFieldCountString(long): + +MissingNullability: android.util.proto.ProtoStream#getFieldIdString(long): + +MissingNullability: android.util.proto.ProtoStream#getFieldTypeString(long): + +MissingNullability: android.util.proto.ProtoStream#getWireTypeString(int): + +MissingNullability: android.util.proto.ProtoStream#token2String(long): + +MissingNullability: android.util.proto.WireTypeMismatchException#WireTypeMismatchException(String) parameter #0: + +MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #1: + +MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #2: + +MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #1: + +MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #2: + +MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #1: + +MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #2: + +MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0: + +MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #3: + +MissingNullability: android.view.KeyEvent#actionToString(int): + +MissingNullability: android.view.View#getTooltipView(): + +MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0: + +MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #0: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #1: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #2: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #0: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #1: + +MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #2: + +MissingNullability: android.view.WindowManager.LayoutParams#accessibilityTitle: + +MissingNullability: android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener#onAccessibilityServicesStateChanged(android.view.accessibility.AccessibilityManager) parameter #0: + +MissingNullability: android.view.accessibility.AccessibilityNodeInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0: + +MissingNullability: android.view.accessibility.AccessibilityNodeInfo#writeToParcelNoRecycle(android.os.Parcel, int) parameter #0: + +MissingNullability: android.view.accessibility.AccessibilityWindowInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0: + +MissingNullability: android.view.contentcapture.ContentCaptureEvent#writeToParcel(android.os.Parcel, int) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode#getAutofillId(): + +MissingNullability: android.view.contentcapture.ViewNode#getClassName(): + +MissingNullability: android.view.contentcapture.ViewNode#getContentDescription(): + +MissingNullability: android.view.contentcapture.ViewNode#getExtras(): + +MissingNullability: android.view.contentcapture.ViewNode#getHint(): + +MissingNullability: android.view.contentcapture.ViewNode#getIdEntry(): + +MissingNullability: android.view.contentcapture.ViewNode#getIdPackage(): + +MissingNullability: android.view.contentcapture.ViewNode#getIdType(): + +MissingNullability: android.view.contentcapture.ViewNode#getLocaleList(): + +MissingNullability: android.view.contentcapture.ViewNode#getText(): + +MissingNullability: android.view.contentcapture.ViewNode#getTextIdEntry(): + +MissingNullability: android.view.contentcapture.ViewNode#getTextLineBaselines(): + +MissingNullability: android.view.contentcapture.ViewNode#getTextLineCharOffsets(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#asyncNewChild(int): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getAutofillId(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getExtras(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getHint(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getNode(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getTempRect(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getText(): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newChild(int): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String): + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillHints(String[]) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId, int) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillValue(android.view.autofill.AutofillValue) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setClassName(String) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setContentDescription(CharSequence) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHint(CharSequence) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHtmlInfo(android.view.ViewStructure.HtmlInfo) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #1: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #2: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #3: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setLocaleList(android.os.LocaleList) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence, int, int) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextIdEntry(String) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #1: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTransformation(android.graphics.Matrix) parameter #0: + +MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setWebDomain(String) parameter #0: + +MissingNullability: android.widget.CalendarView#getBoundsForDate(long, android.graphics.Rect) parameter #1: + +MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0: + +MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1: + +MissingNullability: android.widget.Magnifier#getMagnifierDefaultSize(): + +MissingNullability: android.widget.Magnifier#setOnOperationCompleteCallback(android.widget.Magnifier.Callback) parameter #0: + +MissingNullability: android.widget.NumberPicker#getDisplayedValueForCurrentSelection(): + +MissingNullability: android.widget.PopupMenu#getMenuListView(): + +MissingNullability: android.widget.TimePicker#getAmView(): + +MissingNullability: android.widget.TimePicker#getHourView(): + +MissingNullability: android.widget.TimePicker#getMinuteView(): + +MissingNullability: android.widget.TimePicker#getPmView(): + + + +MutableBareField: android.content.AutofillOptions#appDisabledExpiration: + +MutableBareField: android.content.AutofillOptions#augmentedAutofillEnabled: + +MutableBareField: android.content.AutofillOptions#disabledActivities: + +MutableBareField: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill: + +MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#cache: + +MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbName: + +MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbSize: + +MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#lookaside: + +MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#pageSize: + +MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#dbStats: + +MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#largestMemAlloc: + +MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#memoryUsed: + +MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#pageCacheOverflow: + +MutableBareField: android.os.StrictMode.ViolationInfo#broadcastIntentAction: + +MutableBareField: android.os.StrictMode.ViolationInfo#durationMillis: + +MutableBareField: android.os.StrictMode.ViolationInfo#numAnimationsRunning: + +MutableBareField: android.os.StrictMode.ViolationInfo#numInstances: + +MutableBareField: android.os.StrictMode.ViolationInfo#tags: + +MutableBareField: android.os.StrictMode.ViolationInfo#violationNumThisLoop: + +MutableBareField: android.os.StrictMode.ViolationInfo#violationUptimeMillis: + + + +NoByteOrShort: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]): + +NoByteOrShort: android.media.audiofx.AudioEffect#setParameter(int, short) parameter #1: + +NoByteOrShort: android.media.audiofx.AudioEffect#shortToByteArray(short) parameter #0: + +NoByteOrShort: android.os.HwBlob#getInt16(long): + +NoByteOrShort: android.os.HwBlob#getInt8(long): + +NoByteOrShort: android.os.HwBlob#putInt16(long, short) parameter #1: + +NoByteOrShort: android.os.HwBlob#putInt8(long, byte) parameter #1: + +NoByteOrShort: android.os.HwParcel#readInt16(): + +NoByteOrShort: android.os.HwParcel#readInt8(): + +NoByteOrShort: android.os.HwParcel#writeInt16(short) parameter #0: + +NoByteOrShort: android.os.HwParcel#writeInt8(byte) parameter #0: + +NoByteOrShort: android.util.proto.EncodedBuffer#readRawByte(): + +NoByteOrShort: android.util.proto.EncodedBuffer#writeRawByte(byte) parameter #0: + + + +NoClone: android.net.util.SocketUtils#bindSocketToInterface(java.io.FileDescriptor, String) parameter #0: + +NoClone: android.net.util.SocketUtils#closeSocket(java.io.FileDescriptor) parameter #0: + +NoClone: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor, boolean) parameter #0: + +NoClone: android.os.NativeHandle#getFileDescriptor(): + +NoClone: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0: + +NoClone: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: + +NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: + +NoClone: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0: + + + +NotCloseable: android.app.ActivityView: + +NotCloseable: android.app.prediction.AppPredictor: + +NotCloseable: android.os.HwParcel: + +NotCloseable: android.telephony.ims.stub.ImsUtImplBase: + Classes that release resources (close()) should implement AutoClosable and CloseGuard: class android.telephony.ims.stub.ImsUtImplBase + + +OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]): + +OnNameExpected: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): + +OnNameExpected: android.service.notification.ConditionProviderService#isBound(): + +OnNameExpected: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context): + +OnNameExpected: android.service.quicksettings.TileService#isQuickSettingsSupported(): + +OnNameExpected: android.telephony.ims.ImsService#createMmTelFeature(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#createRcsFeature(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#disableIms(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#enableIms(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#getConfig(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#getRegistration(int): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#querySupportedImsFeatures(): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.ims.ImsService#readyForFeatureCreation(): + If implemented by developer, should follow the on<Something> style; otherwise consider marking final +OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int): + +OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int): + +OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback): + +OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#stopGroupCall(int, long): + +OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>): + + + +PackageLayering: android.util.FeatureFlagUtils: + + + +ParcelConstructor: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel): + +ParcelConstructor: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel): + +ParcelConstructor: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel): + +ParcelConstructor: android.os.VibrationEffect.OneShot#OneShot(android.os.Parcel): + +ParcelConstructor: android.os.VibrationEffect.Prebaked#Prebaked(android.os.Parcel): + +ParcelConstructor: android.os.VibrationEffect.Waveform#Waveform(android.os.Parcel): + +ParcelConstructor: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel): + +ParcelConstructor: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel): + + + +ParcelCreator: android.app.WindowConfiguration: + +ParcelCreator: android.net.metrics.ApfProgramEvent: + +ParcelCreator: android.net.metrics.ApfStats: + +ParcelCreator: android.net.metrics.DhcpClientEvent: + +ParcelCreator: android.net.metrics.DhcpErrorEvent: + +ParcelCreator: android.net.metrics.IpConnectivityLog.Event: + +ParcelCreator: android.net.metrics.IpManagerEvent: + +ParcelCreator: android.net.metrics.IpReachabilityEvent: + +ParcelCreator: android.net.metrics.NetworkEvent: + +ParcelCreator: android.net.metrics.RaEvent: + +ParcelCreator: android.net.metrics.ValidationProbeEvent: + +ParcelCreator: android.os.VibrationEffect.OneShot: + +ParcelCreator: android.os.VibrationEffect.Prebaked: + +ParcelCreator: android.os.VibrationEffect.Waveform: + +ParcelCreator: android.service.autofill.InternalOnClickAction: + +ParcelCreator: android.service.autofill.InternalSanitizer: + +ParcelCreator: android.service.autofill.InternalTransformation: + +ParcelCreator: android.service.autofill.InternalValidator: + + + +ParcelNotFinal: android.app.WindowConfiguration: + +ParcelNotFinal: android.net.metrics.IpConnectivityLog.Event: + +ParcelNotFinal: android.os.IncidentManager.IncidentReport: + +ParcelNotFinal: android.os.VibrationEffect.OneShot: + +ParcelNotFinal: android.os.VibrationEffect.Prebaked: + +ParcelNotFinal: android.os.VibrationEffect.Waveform: + +ParcelNotFinal: android.os.health.HealthStatsParceler: + +ParcelNotFinal: android.service.autofill.InternalOnClickAction: + +ParcelNotFinal: android.service.autofill.InternalSanitizer: + +ParcelNotFinal: android.service.autofill.InternalTransformation: + +ParcelNotFinal: android.service.autofill.InternalValidator: + + + +ProtectedMember: android.app.ActivityView#onVisibilityChanged(android.view.View, int): + +ProtectedMember: android.app.AppDetailsActivity#onCreate(android.os.Bundle): + +ProtectedMember: android.os.VibrationEffect#scale(int, float, int): + +ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): + +ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]): + +ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): + +ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context): + +ProtectedMember: android.util.proto.ProtoStream#FIELD_TYPE_NAMES: + +ProtectedMember: android.view.View#resetResolvedDrawables(): + +ProtectedMember: android.view.ViewGroup#resetResolvedDrawables(): + + + +RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase: + +RawAidl: android.telephony.mbms.vendor.MbmsStreamingServiceBase: + + + +RethrowRemoteException: android.app.ActivityManager#resumeAppSwitches(): + +RethrowRemoteException: android.os.HwBinder#getService(String, String): + +RethrowRemoteException: android.os.HwBinder#getService(String, String, boolean): + +RethrowRemoteException: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int): + +RethrowRemoteException: android.os.HwBinder#registerService(String): + +RethrowRemoteException: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int): + +RethrowRemoteException: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int): + +RethrowRemoteException: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration): + Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#dispose(int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#listPendingDownloads(int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#dispose(int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback): + +RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String): + + + +SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int): + +SamShouldBeLast: android.app.role.RoleManager#addOnRoleHoldersChangedListenerAsUser(java.util.concurrent.Executor, android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle): + +SamShouldBeLast: android.app.role.RoleManager#removeOnRoleHoldersChangedListenerAsUser(android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle): + +SamShouldBeLast: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]): + +SamShouldBeLast: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]): + +SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener): + +SamShouldBeLast: android.os.BugreportManager#startBugreport(android.os.ParcelFileDescriptor, android.os.ParcelFileDescriptor, android.os.BugreportParams, java.util.concurrent.Executor, android.os.BugreportManager.BugreportCallback): + +SamShouldBeLast: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long): + +SamShouldBeLast: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String): + +SamShouldBeLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler): + +SamShouldBeLast: android.permission.PermissionControllerManager#revokeRuntimePermissions(java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, java.util.concurrent.Executor, android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback): + +SamShouldBeLast: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +SamShouldBeLast: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +SamShouldBeLast: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int): + +SamShouldBeLast: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>): + +SamShouldBeLast: android.telephony.ims.ImsMmTelManager#getFeatureState(java.util.function.Consumer<java.lang.Integer>, java.util.concurrent.Executor): + SAM-compatible parameters (such as parameter 1, "callback", in android.telephony.ims.ImsMmTelManager.getFeatureState) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions +SamShouldBeLast: android.view.Choreographer#postCallback(int, Runnable, Object): + +SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long): + +SamShouldBeLast: android.view.Choreographer#removeCallbacks(int, Runnable, Object): + +SamShouldBeLast: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>): + +SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, android.os.Handler): + + + +ServiceName: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE: + +ServiceName: android.app.AppOpsManager#OPSTR_BIND_ACCESSIBILITY_SERVICE: + +ServiceName: android.provider.Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE: + +ServiceName: android.provider.Settings.Secure#AUTOFILL_SERVICE: + +ServiceName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE: + + + +SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener): + +SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener): + + + +StaticUtils: android.os.health.HealthKeys: + +StaticUtils: android.service.autofill.InternalTransformation: + +StaticUtils: android.telephony.mbms.vendor.VendorUtils: + +StaticUtils: android.util.FeatureFlagUtils: + +StaticUtils: android.util.proto.ProtoStream: + +StaticUtils: android.view.inputmethod.InputMethodSystemProperty: + + + +StreamFiles: android.os.Environment#buildPath(java.io.File, java.lang.String...): + +StreamFiles: android.os.FileUtils#contains(java.io.File, java.io.File): + +StreamFiles: android.provider.MediaStore#scanFile(android.content.Context, java.io.File): + +StreamFiles: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File): + +StreamFiles: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File): + + + +UseParcelFileDescriptor: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0: + + + +UserHandle: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle): + +UserHandle: android.app.role.RoleManager#addOnRoleHoldersChangedListenerAsUser(java.util.concurrent.Executor, android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle): + +UserHandle: android.app.role.RoleManager#addRoleHolderAsUser(String, String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>): + +UserHandle: android.app.role.RoleManager#clearRoleHoldersAsUser(String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>): + +UserHandle: android.app.role.RoleManager#getRoleHoldersAsUser(String, android.os.UserHandle): + +UserHandle: android.app.role.RoleManager#removeOnRoleHoldersChangedListenerAsUser(android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle): + +UserHandle: android.app.role.RoleManager#removeRoleHolderAsUser(String, String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>): + +UserHandle: android.content.pm.PackageManager#getInstallReason(String, android.os.UserHandle): + +UserHandle: android.content.pm.PackageManager#getPermissionFlags(String, String, android.os.UserHandle): + +UserHandle: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle): + +UserHandle: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle): + +UserHandle: android.content.pm.PackageManager#updatePermissionFlags(String, String, int, int, android.os.UserHandle): + +UserHandle: android.location.LocationManager#setLocationEnabledForUser(boolean, android.os.UserHandle): + + + +UserHandleName: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle): + +UserHandleName: android.content.AutofillOptions: + +UserHandleName: android.content.ContentCaptureOptions: + +UserHandleName: android.os.IncidentReportArgs: + +UserHandleName: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle): + +UserHandleName: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle): + + + +VisiblySynchronized: PsiClassObjectAccessExpression: + +VisiblySynchronized: PsiThisExpression: + +VisiblySynchronized: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int): + +VisiblySynchronized: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener): + +VisiblySynchronized: android.content.ContentProviderClient#setDetectNotResponding(long): + +VisiblySynchronized: android.content.res.AssetManager#getApkPaths(): + +VisiblySynchronized: android.content.res.AssetManager#getOverlayableMap(String): + +VisiblySynchronized: android.os.MessageQueue#removeSyncBarrier(int): + diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 41d546f6d603..22e1d0187f01 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -174,6 +174,8 @@ public class Am extends BaseCommand { instrument.noWindowAnimation = true; } else if (opt.equals("--no-hidden-api-checks")) { instrument.disableHiddenApiChecks = true; + } else if (opt.equals("--no-test-api-checks")) { + instrument.disableTestApiChecks = true; } else if (opt.equals("--no-isolated-storage")) { instrument.disableIsolatedStorage = true; } else if (opt.equals("--user")) { diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java index 4d7b5a79b4f7..6afd7c40c1c1 100644 --- a/cmds/am/src/com/android/commands/am/Instrument.java +++ b/cmds/am/src/com/android/commands/am/Instrument.java @@ -17,6 +17,7 @@ package com.android.commands.am; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; +import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; import android.app.IActivityManager; @@ -85,6 +86,7 @@ public class Instrument { String logPath = null; public boolean noWindowAnimation = false; public boolean disableHiddenApiChecks = false; + public boolean disableTestApiChecks = false; public boolean disableIsolatedStorage = false; public String abi = null; public int userId = UserHandle.USER_CURRENT; @@ -506,6 +508,9 @@ public class Instrument { if (disableHiddenApiChecks) { flags |= INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; } + if (disableTestApiChecks) { + flags |= INSTR_FLAG_DISABLE_TEST_API_CHECKS; + } if (disableIsolatedStorage) { flags |= INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; } diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index f0db1b0128a1..313e16d19b62 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -128,13 +128,13 @@ private: std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers; - std::unordered_map<ConfigKey, long> mLastBroadcastTimes; + std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes; // Last time we sent a broadcast to this uid that the active configs had changed. - std::unordered_map<int, long> mLastActivationBroadcastTimes; + std::unordered_map<int, int64_t> mLastActivationBroadcastTimes; // Tracks when we last checked the bytes consumed for each config key. - std::unordered_map<ConfigKey, long> mLastByteSizeTimes; + std::unordered_map<ConfigKey, int64_t> mLastByteSizeTimes; // Tracks which config keys has metric reports on disk std::set<ConfigKey> mOnDiskDataConfigs; @@ -205,7 +205,7 @@ private: int64_t mLastTimestampSeen = 0; - long mLastPullerCacheClearTimeSec = 0; + int64_t mLastPullerCacheClearTimeSec = 0; // Last time we wrote data to disk. int64_t mLastWriteTimeNs = 0; diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 847c2981ec8d..8a8df38c65b2 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -324,6 +324,8 @@ message Atom { AppCompatibilityChangeReported app_compatibility_change_reported = 228 [(allow_from_any_uid) = true]; + PerfettoUploaded perfetto_uploaded = + 229 [(log_from_module) = "perfetto"]; } // Pulled events will start at field 10000. @@ -6857,3 +6859,37 @@ message AppCompatibilityChangeReported { optional Source source = 4; } + +/** + * Logged from + * external/perfetto/src/perfetto_cmd/perfetto_cmd.cc + */ +message PerfettoUploaded { + enum Event { + PERFETTO_UNDEFINED = 0; + PERFETTO_TRACE_BEGIN = 1; + PERFETTO_BACKGROUND_TRACE_BEGIN = 2; + PERFETTO_ON_CONNECT = 3; + PERFETTO_ON_TRACING_DISABLED = 4; + PERFETTO_UPLOAD_DROPBOX_BEGIN = 5; + PERFETTO_UPLOAD_DROPBOX_SUCCESS = 6; + PERFETTO_UPLOAD_DROPBOX_FAILURE = 7; + PERFETTO_UPLOAD_INCIDENT_BEGIN = 8; + PERFETTO_UPLOAD_INCIDENT_SUCCESS = 9; + PERFETTO_UPLOAD_INCIDENT_FAILURE = 10; + PERFETTO_FINALIZE_TRACE_AND_EXIT = 11; + PERFETTO_TRIGGER_BEGIN = 12; + PERFETTO_TRIGGER_SUCCESS = 13; + PERFETTO_TRIGGER_FAILURE = 14; + PERFETTO_HIT_GUARDRAILS = 15; + PERFETTO_ON_TIMEOUT = 16; + PERFETTO_NOT_UPLOADING_EMPTY_TRACE = 17; + } + + // Which stage of the pipeline we are reporting from. + optional Event event = 1; + + // UUID matching the one set inside the SystemInfo trace packet. + optional int64 trace_uuid_lsb = 2; + optional int64 trace_uuid_msb = 3; +} diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-greylist-max-p.txt index 25d45b0e6570..351e71dd9538 100644 --- a/config/hiddenapi-greylist-max-p.txt +++ b/config/hiddenapi-greylist-max-p.txt @@ -1,57 +1,14 @@ Landroid/app/IInstrumentationWatcher$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IInstrumentationWatcher; Landroid/app/ISearchManager$Stub;-><init>()V Landroid/app/IUiModeManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IUiModeManager; -Landroid/app/IUiModeManager;->disableCarMode(I)V Landroid/bluetooth/IBluetooth$Stub;-><init>()V Landroid/bluetooth/IBluetoothA2dp$Stub;-><init>()V Landroid/content/IIntentReceiver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IIntentReceiver; Landroid/content/IIntentSender$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IIntentSender; -Landroid/net/IConnectivityManager;->getNetworkInfo(I)Landroid/net/NetworkInfo; -Landroid/net/IConnectivityManager;->reportInetCondition(II)V -Landroid/os/BatteryStats$Counter;-><init>()V -Landroid/os/BatteryStats$HistoryItem;->clear()V -Landroid/os/BatteryStats$HistoryItem;->next:Landroid/os/BatteryStats$HistoryItem; -Landroid/os/BatteryStats$HistoryItem;->same(Landroid/os/BatteryStats$HistoryItem;)Z -Landroid/os/BatteryStats$HistoryItem;->setTo(JBLandroid/os/BatteryStats$HistoryItem;)V -Landroid/os/BatteryStats$HistoryItem;->setTo(Landroid/os/BatteryStats$HistoryItem;)V -Landroid/os/BatteryStats$Timer;-><init>()V -Landroid/os/BatteryStats$Uid$Pkg;-><init>()V -Landroid/os/BatteryStats$Uid$Proc;-><init>()V -Landroid/os/BatteryStats$Uid$Sensor;-><init>()V -Landroid/os/BatteryStats$Uid$Wakelock;-><init>()V -Landroid/os/BatteryStats;-><init>()V -Landroid/os/BatteryStats;->getMobileRadioActiveTime(JI)J -Landroid/os/BatteryStats;->getNetworkActivityBytes(II)J -Landroid/os/CancellationSignal;->mCancelInProgress:Z -Landroid/os/CancellationSignal;->mIsCanceled:Z -Landroid/os/CancellationSignal;->mOnCancelListener:Landroid/os/CancellationSignal$OnCancelListener; -Landroid/os/CancellationSignal;->mRemote:Landroid/os/ICancellationSignal; -Landroid/os/CancellationSignal;->waitForCancelFinishedLocked()V -Landroid/os/IPowerManager;->nap(J)V -Landroid/os/Parcel;->mCreators:Ljava/util/HashMap; -Landroid/os/PowerManager;->mHandler:Landroid/os/Handler; -Landroid/os/Process;->sendSignalQuiet(II)V -Landroid/os/Registrant;->getHandler()Landroid/os/Handler; -Landroid/os/RegistrantList;->get(I)Ljava/lang/Object; -Landroid/os/RemoteCallback;->mHandler:Landroid/os/Handler; Landroid/os/storage/IObbActionListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IObbActionListener; -Landroid/os/SystemProperties;->native_add_change_callback()V -Landroid/os/SystemProperties;->native_get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; -Landroid/os/SystemProperties;->native_get_boolean(Ljava/lang/String;Z)Z -Landroid/os/SystemProperties;->native_get_int(Ljava/lang/String;I)I -Landroid/os/SystemProperties;->native_set(Ljava/lang/String;Ljava/lang/String;)V -Landroid/os/UserHandle;->formatUid(Ljava/io/PrintWriter;I)V -Landroid/os/WorkSource;->sGoneWork:Landroid/os/WorkSource; -Landroid/os/WorkSource;->sNewbWork:Landroid/os/WorkSource; -Landroid/os/WorkSource;->sTmpWorkSource:Landroid/os/WorkSource; -Landroid/os/WorkSource;->updateLocked(Landroid/os/WorkSource;ZZ)Z Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V -Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V -Landroid/telephony/CarrierMessagingServiceManager;-><init>()V Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats; -Landroid/view/IWindowManager;->setInTouchMode(Z)V -Landroid/view/IWindowManager;->showStrictModeViolation(Z)V Lcom/android/internal/R$styleable;->AndroidManifestActivityAlias:[I Lcom/android/internal/R$styleable;->AndroidManifestGrantUriPermission:[I Lcom/android/internal/R$styleable;->AndroidManifestInstrumentation:[I @@ -70,10 +27,3 @@ Lcom/android/internal/R$styleable;->MenuView:[I Lcom/android/internal/R$styleable;->Searchable:[I Lcom/android/internal/R$styleable;->SearchableActionKey:[I Lcom/android/internal/telephony/IPhoneSubInfo$Stub;-><init>()V -Lcom/android/internal/telephony/ITelephony;->getDataActivity()I -Lcom/android/internal/telephony/ITelephony;->getDataState()I -Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallForwardingChanged(Z)V -Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCellLocation(Landroid/os/Bundle;)V -Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataActivity(I)V -Lcom/android/internal/telephony/ITelephonyRegistry;->notifyOtaspChanged(II)V -Lcom/android/internal/view/BaseIWindow;-><init>()V diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 3e00bfebbcb4..2d3394be1ad0 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -1,6 +1,4 @@ Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accessibilityservice/IAccessibilityServiceConnection; -Landroid/accounts/AccountManager$AmsTask;-><init>(Landroid/accounts/AccountManager;Landroid/app/Activity;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V -Landroid/accounts/AccountManager$Future2Task;-><init>(Landroid/accounts/AccountManager;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V Landroid/accounts/IAccountAuthenticator$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/accounts/IAccountAuthenticator$Stub;-><init>()V @@ -16,10 +14,6 @@ Landroid/accounts/IAccountManagerResponse$Stub$Proxy;-><init>(Landroid/os/IBinde Landroid/accounts/IAccountManagerResponse$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/accounts/IAccountManagerResponse$Stub;-><init>()V Landroid/accounts/IAccountManagerResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManagerResponse; -Landroid/app/ActivityManagerNative;-><init>()V -Landroid/app/ActivityThread$AppBindData;-><init>()V -Landroid/app/ActivityThread$CreateServiceData;-><init>()V -Landroid/app/ActivityThread$H;-><init>(Landroid/app/ActivityThread;)V Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager; Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I @@ -35,8 +29,6 @@ Landroid/app/IActivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/app/IActivityManager$Stub$Proxy;->setActivityController(Landroid/app/IActivityController;Z)V Landroid/app/IActivityManager$Stub$Proxy;->updatePersistentConfiguration(Landroid/content/res/Configuration;)V Landroid/app/IActivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager; -Landroid/app/IActivityManager;->finishReceiver(Landroid/os/IBinder;ILjava/lang/String;Landroid/os/Bundle;ZI)V -Landroid/app/IActivityManager;->serviceDoneExecuting(Landroid/os/IBinder;III)V Landroid/app/IAlarmManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/app/IAlarmManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IAlarmManager; Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I @@ -73,56 +65,25 @@ Landroid/app/job/IJobService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/app/job/IJobService$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/app/job/IJobService$Stub;-><init>()V Landroid/app/job/IJobService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobService; -Landroid/app/PackageDeleteObserver;-><init>()V -Landroid/app/PackageInstallObserver;-><init>()V -Landroid/app/ResourcesManager$ActivityResources;-><init>()V -Landroid/app/ResourcesManager;-><init>()V -Landroid/app/TaskStackListener;-><init>()V Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -Landroid/app/UiAutomationConnection;-><init>()V Landroid/app/usage/IUsageStatsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/usage/IUsageStatsManager; -Landroid/app/UserSwitchObserver;-><init>()V Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String; Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth; Landroid/bluetooth/IBluetooth$Stub;->TRANSACTION_enable:I -Landroid/bluetooth/IBluetooth;->fetchRemoteUuids(Landroid/bluetooth/BluetoothDevice;)Z -Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String; -Landroid/bluetooth/IBluetooth;->getRemoteAlias(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String; -Landroid/bluetooth/IBluetooth;->isEnabled()Z -Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V Landroid/bluetooth/IBluetoothA2dp$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothA2dp; -Landroid/bluetooth/IBluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z -Landroid/bluetooth/IBluetoothA2dp;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z -Landroid/bluetooth/IBluetoothA2dp;->getConnectedDevices()Ljava/util/List; -Landroid/bluetooth/IBluetoothA2dp;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I -Landroid/bluetooth/IBluetoothA2dp;->getDevicesMatchingConnectionStates([I)Ljava/util/List; -Landroid/bluetooth/IBluetoothA2dp;->getPriority(Landroid/bluetooth/BluetoothDevice;)I Landroid/bluetooth/IBluetoothCallback$Stub;-><init>()V -Landroid/bluetooth/IBluetoothGatt;->registerClient(Landroid/os/ParcelUuid;Landroid/bluetooth/IBluetoothGattCallback;)V -Landroid/bluetooth/IBluetoothGatt;->unregisterClient(I)V Landroid/bluetooth/IBluetoothGattCallback$Stub;-><init>()V Landroid/bluetooth/IBluetoothGattCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothGattCallback; Landroid/bluetooth/IBluetoothHeadset$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothHeadset; -Landroid/bluetooth/IBluetoothHeadset;->connect(Landroid/bluetooth/BluetoothDevice;)Z -Landroid/bluetooth/IBluetoothHeadset;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z -Landroid/bluetooth/IBluetoothHeadset;->getConnectedDevices()Ljava/util/List; -Landroid/bluetooth/IBluetoothHeadset;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I -Landroid/bluetooth/IBluetoothHeadset;->getPriority(Landroid/bluetooth/BluetoothDevice;)I -Landroid/bluetooth/IBluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothDevice;I)Z Landroid/bluetooth/IBluetoothHidDeviceCallback$Stub;-><init>()V Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/bluetooth/IBluetoothManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothManager; Landroid/bluetooth/IBluetoothManager$Stub;->TRANSACTION_enable:I -Landroid/bluetooth/IBluetoothManager;->getBluetoothGatt()Landroid/bluetooth/IBluetoothGatt; -Landroid/bluetooth/IBluetoothManager;->registerStateChangeCallback(Landroid/bluetooth/IBluetoothStateChangeCallback;)V -Landroid/bluetooth/IBluetoothManager;->unregisterStateChangeCallback(Landroid/bluetooth/IBluetoothStateChangeCallback;)V Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap; Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V -Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V -Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard; Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -189,14 +150,8 @@ Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver; Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService; -Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V -Landroid/content/res/DrawableCache;-><init>()V -Landroid/content/UndoManager;-><init>()V Landroid/database/IContentObserver$Stub;-><init>()V Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver; -Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V -Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z -Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager; Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService; @@ -221,7 +176,6 @@ Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager; Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I Landroid/location/INetInitiatedListener$Stub;-><init>()V -Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String; Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String; Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String; @@ -232,13 +186,9 @@ Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/me Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService; Landroid/media/IMediaScannerListener$Stub;-><init>()V Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService; -Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController; -Landroid/media/MediaFile;-><init>()V -Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager; Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V -Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties; Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfo()Landroid/net/NetworkInfo; @@ -256,12 +206,8 @@ Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landro Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String; Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService; -Landroid/net/InterfaceConfiguration;-><init>()V -Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange; -Landroid/net/MobileLinkQualityInfo;-><init>()V Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager; Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession; -Landroid/net/SntpClient;-><init>()V Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager; Landroid/net/wifi/IWifiManager$Stub;->TRANSACTION_getScanResults:I @@ -271,16 +217,11 @@ Landroid/net/wifi/IWifiScanner$Stub;-><init>()V Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner; Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager; Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I -Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;-><init>()V -Landroid/os/BatteryStats$Uid;-><init>()V Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/IDeviceIdentifiersPolicyService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdentifiersPolicyService; Landroid/os/IDeviceIdleController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdleController; -Landroid/os/IDeviceIdleController;->getAppIdTempWhitelist()[I -Landroid/os/IDeviceIdleController;->getFullPowerWhitelistExceptIdle()[Ljava/lang/String; Landroid/os/INetworkManagementService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService; -Landroid/os/INetworkManagementService;->listTetheredInterfaces()[Ljava/lang/String; Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController; Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -291,17 +232,12 @@ Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem; Landroid/os/IRemoteCallback$Stub;-><init>()V Landroid/os/IUpdateEngine$Stub;-><init>()V -Landroid/os/IUpdateEngineCallback;->onStatusUpdate(IF)V Landroid/os/IUserManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/IUserManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IUserManager; Landroid/os/IVibratorService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IVibratorService; -Landroid/os/Parcel$ReadWriteHelper;-><init>()V -Landroid/os/RegistrantList;-><init>()V -Landroid/os/ServiceManager;-><init>()V Landroid/os/storage/IObbActionListener$Stub;-><init>()V Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager; -Landroid/os/storage/StorageEventListener;-><init>()V Landroid/R$styleable;->ActionBar:[I Landroid/R$styleable;->ActionBar_background:I Landroid/R$styleable;->ActionBar_backgroundSplit:I @@ -568,18 +504,7 @@ Landroid/R$styleable;->Window_windowBackground:I Landroid/R$styleable;->Window_windowFrame:I Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService; Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService; -Landroid/security/keystore/IKeystoreService;->clear_uid(J)I -Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I -Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I -Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B -Landroid/security/keystore/IKeystoreService;->getState(I)I -Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I -Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I -Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String; -Landroid/security/keystore/IKeystoreService;->reset()I -Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager; -Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName; Landroid/service/euicc/IEuiccService$Stub;-><init>()V Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks; Landroid/service/notification/INotificationListener$Stub;-><init>()V @@ -587,18 +512,11 @@ Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(L Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager; Landroid/service/wallpaper/IWallpaperConnection$Stub;-><init>()V Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService; -Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V -Landroid/telephony/ims/compat/ImsService;-><init>()V -Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V -Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService; -Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants; -Landroid/util/Singleton;-><init>()V Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager; -Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;-><init>()V Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager; Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V @@ -617,30 +535,10 @@ Landroid/view/IWindowManager$Stub$Proxy;->watchRotation(Landroid/view/IRotationW Landroid/view/IWindowManager$Stub;-><init>()V Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager; Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowSession; -Landroid/view/View$AttachInfo$InvalidateInfo;-><init>()V -Landroid/view/View$CheckForLongPress;-><init>(Landroid/view/View;)V -Landroid/view/View$ListenerInfo;-><init>()V -Landroid/view/ViewTreeObserver$InternalInsetsInfo;-><init>()V -Landroid/webkit/CacheManager$CacheResult;-><init>()V Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse; Landroid/webkit/IWebViewUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/webkit/IWebViewUpdateService; -Landroid/widget/DigitalClock$FormatChangeObserver;-><init>(Landroid/widget/DigitalClock;)V -Landroid/widget/QuickContactBadge$QueryHandler;-><init>(Landroid/widget/QuickContactBadge;Landroid/content/ContentResolver;)V -Landroid/widget/RelativeLayout$DependencyGraph$Node;-><init>()V -Landroid/widget/ScrollBarDrawable;-><init>()V -Lcom/android/ims/ImsCall;->deflect(Ljava/lang/String;)V -Lcom/android/ims/ImsCall;->isMultiparty()Z -Lcom/android/ims/ImsCall;->reject(I)V -Lcom/android/ims/ImsCall;->terminate(I)V Lcom/android/ims/ImsConfigListener$Stub;-><init>()V -Lcom/android/ims/ImsEcbm;->exitEmergencyCallbackMode()V -Lcom/android/ims/ImsManager;->getConfigInterface()Lcom/android/ims/ImsConfig; -Lcom/android/ims/ImsManager;->getInstance(Landroid/content/Context;I)Lcom/android/ims/ImsManager; -Lcom/android/ims/ImsManager;->isEnhanced4gLteModeSettingEnabledByUser(Landroid/content/Context;)Z -Lcom/android/ims/ImsManager;->isNonTtyOrTtyOnVolteEnabled(Landroid/content/Context;)Z -Lcom/android/ims/ImsManager;->isVolteEnabledByPlatform(Landroid/content/Context;)Z -Lcom/android/ims/ImsUtInterface;->queryCallForward(ILjava/lang/String;Landroid/os/Message;)V Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession; Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V @@ -649,13 +547,10 @@ Lcom/android/ims/internal/IImsService$Stub;-><init>()V Lcom/android/ims/internal/IImsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsService; Lcom/android/ims/internal/IImsUt$Stub;-><init>()V Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V -Lcom/android/ims/internal/ImsVideoCallProviderWrapper;-><init>(Lcom/android/ims/internal/IImsVideoCallProvider;)V Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V -Lcom/android/internal/app/AlertActivity;-><init>()V -Lcom/android/internal/app/ChooserActivity;-><init>()V Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I @@ -684,35 +579,16 @@ Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;) Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService; Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService; -Lcom/android/internal/app/ResolverActivity;-><init>()V Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService; Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V -Lcom/android/internal/content/PackageMonitor;-><init>()V -Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;-><init>()V -Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorId:Ljava/lang/String; -Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorIdEncoding:I -Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->text:Ljava/lang/String; -Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->textEncoding:I -Lcom/android/internal/location/GpsNetInitiatedHandler;->decodeString(Ljava/lang/String;ZI)Ljava/lang/String; -Lcom/android/internal/location/GpsNetInitiatedHandler;->handleNiNotification(Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;)V -Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider; -Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)V -Lcom/android/internal/location/ILocationProvider;->setLocationProviderManager(Lcom/android/internal/location/ILocationProviderManager;)V -Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager; -Lcom/android/internal/logging/MetricsLogger;-><init>()V -Lcom/android/internal/net/LegacyVpnInfo;-><init>()V -Lcom/android/internal/net/VpnConfig;-><init>()V -Lcom/android/internal/os/BaseCommand;-><init>()V -Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType; Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService; Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService; Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback; -Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V Lcom/android/internal/R$anim;->fade_in:I Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I Lcom/android/internal/R$array;->config_autoBrightnessLevels:I @@ -1157,208 +1033,9 @@ Lcom/android/internal/statusbar/IStatusBar$Stub;->asInterface(Landroid/os/IBinde Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService; Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService; -Lcom/android/internal/telephony/Call$State;->ALERTING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->DIALING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->DISCONNECTED:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->DISCONNECTING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->HOLDING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->IDLE:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->INCOMING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->values()[Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call$State;->WAITING:Lcom/android/internal/telephony/Call$State; -Lcom/android/internal/telephony/Call;-><init>()V -Lcom/android/internal/telephony/CallForwardInfo;-><init>()V -Lcom/android/internal/telephony/CallTracker;-><init>()V -Lcom/android/internal/telephony/cat/AppInterface$CommandType;->values()[Lcom/android/internal/telephony/cat/AppInterface$CommandType; -Lcom/android/internal/telephony/cat/ResponseData;-><init>()V -Lcom/android/internal/telephony/cat/ResultCode;->values()[Lcom/android/internal/telephony/cat/ResultCode; -Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCurrentRilMessage:Lcom/android/internal/telephony/cat/RilMessage; -Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendCmdForExecution(Lcom/android/internal/telephony/cat/RilMessage;)V -Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendStartDecodingMessageParams(Lcom/android/internal/telephony/cat/RilMessage;)V -Lcom/android/internal/telephony/cat/ValueObject;-><init>()V -Lcom/android/internal/telephony/cat/ValueParser;->retrieveDeviceIdentities(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Lcom/android/internal/telephony/cat/DeviceIdentities; -Lcom/android/internal/telephony/cdma/sms/BearerData$CodingException;-><init>(Ljava/lang/String;)V -Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;-><init>()V -Lcom/android/internal/telephony/cdma/sms/BearerData;-><init>()V -Lcom/android/internal/telephony/cdma/sms/BearerData;->countAsciiSeptets(Ljava/lang/CharSequence;Z)I -Lcom/android/internal/telephony/cdma/sms/BearerData;->decodeUserDataPayload(Lcom/android/internal/telephony/cdma/sms/UserData;Z)V -Lcom/android/internal/telephony/cdma/sms/BearerData;->displayMode:I -Lcom/android/internal/telephony/cdma/sms/BearerData;->encode(Lcom/android/internal/telephony/cdma/sms/BearerData;)[B -Lcom/android/internal/telephony/cdma/sms/BearerData;->encode7bitAscii(Ljava/lang/String;Z)[B -Lcom/android/internal/telephony/cdma/sms/BearerData;->getBitsForNumFields(II)I -Lcom/android/internal/telephony/cdma/sms/BearerData;->hasUserDataHeader:Z -Lcom/android/internal/telephony/cdma/sms/BearerData;->messageId:I -Lcom/android/internal/telephony/cdma/sms/BearerData;->msgCenterTimeStamp:Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp; -Lcom/android/internal/telephony/cdma/sms/BearerData;->priority:I -Lcom/android/internal/telephony/cdma/sms/BearerData;->priorityIndicatorSet:Z -Lcom/android/internal/telephony/cdma/sms/BearerData;->userData:Lcom/android/internal/telephony/cdma/sms/UserData; -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;-><init>()V -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->digitMode:I -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberMode:I -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberOfDigits:I -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberPlan:I -Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->parse(Ljava/lang/String;)Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress; -Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;-><init>()V -Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->bearerData:[B -Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->serviceCategory:I -Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->teleService:I -Lcom/android/internal/telephony/cdma/sms/UserData;-><init>()V -Lcom/android/internal/telephony/cdma/sms/UserData;->charToAscii:Landroid/util/SparseIntArray; -Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncoding:I -Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncodingSet:Z -Lcom/android/internal/telephony/cdma/sms/UserData;->numFields:I -Lcom/android/internal/telephony/cdma/sms/UserData;->payload:[B -Lcom/android/internal/telephony/cdma/sms/UserData;->payloadStr:Ljava/lang/String; -Lcom/android/internal/telephony/cdma/sms/UserData;->userDataHeader:Lcom/android/internal/telephony/SmsHeader; -Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;-><init>()V -Lcom/android/internal/telephony/cdma/SmsMessage;-><init>()V -Lcom/android/internal/telephony/cdma/SmsMessage;->calculateLength(Ljava/lang/CharSequence;ZZ)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails; -Lcom/android/internal/telephony/cdma/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/cdma/SmsMessage; -Lcom/android/internal/telephony/cdma/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/cdma/SmsMessage; -Lcom/android/internal/telephony/cdma/SmsMessage;->getIncomingSmsFingerprint()[B -Lcom/android/internal/telephony/cdma/SmsMessage;->getMessageType()I -Lcom/android/internal/telephony/cdma/SmsMessage;->getNextMessageId()I -Lcom/android/internal/telephony/cdma/SmsMessage;->getNumOfVoicemails()I -Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;Z)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;ZI)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;I[BZ)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;I)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/cdma/SmsMessage;->getTeleService()I -Lcom/android/internal/telephony/cdma/SmsMessage;->isStatusReportMessage()Z -Lcom/android/internal/telephony/cdma/SmsMessage;->mBearerData:Lcom/android/internal/telephony/cdma/sms/BearerData; -Lcom/android/internal/telephony/cdma/SmsMessage;->mEnvelope:Lcom/android/internal/telephony/cdma/sms/SmsEnvelope; -Lcom/android/internal/telephony/cdma/SmsMessage;->parseSms()V -Lcom/android/internal/telephony/cdma/SmsMessage;->privateGetSubmitPdu(Ljava/lang/String;ZLcom/android/internal/telephony/cdma/sms/UserData;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity; -Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity; -Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity; -Lcom/android/internal/telephony/DctConstants$Activity;->DORMANT:Lcom/android/internal/telephony/DctConstants$Activity; -Lcom/android/internal/telephony/DctConstants$Activity;->values()[Lcom/android/internal/telephony/DctConstants$Activity; -Lcom/android/internal/telephony/DctConstants$State;->CONNECTED:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->CONNECTING:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->DISCONNECTING:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->FAILED:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State; -Lcom/android/internal/telephony/DriverCall$State;->values()[Lcom/android/internal/telephony/DriverCall$State; -Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;-><init>(Lcom/android/internal/telephony/gsm/SmsCbHeader;Landroid/telephony/SmsCbLocation;)V -Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;->matchesLocation(Ljava/lang/String;II)Z -Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler;->mSmsCbPageMap:Ljava/util/HashMap; -Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V -Lcom/android/internal/telephony/gsm/GsmMmiCode;-><init>(Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)V -Lcom/android/internal/telephony/gsm/GsmMmiCode;->getCLIRMode()I -Lcom/android/internal/telephony/gsm/GsmMmiCode;->getScString()Ljava/lang/CharSequence; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isActivate()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isDeactivate()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isErasure()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isInterrogate()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isRegister()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallBarring(Ljava/lang/String;)Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallForwarding(Ljava/lang/String;)Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->isTemporaryModeCLIR()Z -Lcom/android/internal/telephony/gsm/GsmMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mContext:Landroid/content/Context; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mDialingNumber:Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSc:Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSia:Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSib:Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSic:Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)Lcom/android/internal/telephony/gsm/GsmMmiCode; -Lcom/android/internal/telephony/gsm/GsmMmiCode;->processCode()V -Lcom/android/internal/telephony/gsm/GsmMmiCode;->siToServiceClass(Ljava/lang/String;)I -Lcom/android/internal/telephony/gsm/GsmMmiCode;->sPatternSuppService:Ljava/util/regex/Pattern; -Lcom/android/internal/telephony/gsm/GsmSmsAddress;-><init>([BII)V -Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageClear()Z -Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageSet()Z -Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->getFormat()Ljava/lang/String; -Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->mGsmInboundSmsHandler:Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler; -Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V -Lcom/android/internal/telephony/gsm/SimTlv;-><init>([BII)V -Lcom/android/internal/telephony/gsm/SimTlv;->getData()[B -Lcom/android/internal/telephony/gsm/SimTlv;->getTag()I -Lcom/android/internal/telephony/gsm/SimTlv;->isValidObject()Z -Lcom/android/internal/telephony/gsm/SimTlv;->mHasValidTlvObject:Z -Lcom/android/internal/telephony/gsm/SimTlv;->nextObject()Z -Lcom/android/internal/telephony/gsm/SmsCbHeader;-><init>([B)V -Lcom/android/internal/telephony/gsm/SmsCbHeader;->getGeographicalScope()I -Lcom/android/internal/telephony/gsm/SmsCbHeader;->getNumberOfPages()I -Lcom/android/internal/telephony/gsm/SmsCbHeader;->getPageIndex()I -Lcom/android/internal/telephony/gsm/SmsCbHeader;->getSerialNumber()I -Lcom/android/internal/telephony/gsm/SmsCbHeader;->getServiceCategory()I -Lcom/android/internal/telephony/gsm/SmsCbHeader;->mMessageIdentifier:I -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;-><init>([B)V -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getByte()I -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserData()[B -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserDataUCS2(I)Ljava/lang/String; -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mCur:I -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mPdu:[B -Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mUserDataSeptetPadding:I -Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;-><init>()V -Lcom/android/internal/telephony/gsm/SmsMessage;-><init>()V -Lcom/android/internal/telephony/gsm/SmsMessage;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails; -Lcom/android/internal/telephony/gsm/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/gsm/SmsMessage; -Lcom/android/internal/telephony/gsm/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/gsm/SmsMessage; -Lcom/android/internal/telephony/gsm/SmsMessage;->encodeUCS2(Ljava/lang/String;[B)[B -Lcom/android/internal/telephony/gsm/SmsMessage;->getStatus()I -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[B)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu; -Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPduHead(Ljava/lang/String;Ljava/lang/String;BZLcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;)Ljava/io/ByteArrayOutputStream; -Lcom/android/internal/telephony/gsm/SmsMessage;->isMWIClearMessage()Z -Lcom/android/internal/telephony/gsm/SmsMessage;->isMwiDontStore()Z -Lcom/android/internal/telephony/gsm/SmsMessage;->isMWISetMessage()Z -Lcom/android/internal/telephony/gsm/SmsMessage;->isStatusReportMessage()Z -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->loadEfFilesFromUsim()Ljava/util/ArrayList; -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->log(Ljava/lang/String;)V -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler; -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mLock:Ljava/lang/Object; -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mPhoneBookRecords:Ljava/util/ArrayList; -Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V -Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V -Lcom/android/internal/telephony/GsmCdmaConnection$MyHandler;-><init>(Lcom/android/internal/telephony/GsmCdmaConnection;Landroid/os/Looper;)V -Lcom/android/internal/telephony/IccCardConstants$State;->ABSENT:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->CARD_IO_ERROR:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->NETWORK_LOCKED:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->NOT_READY:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->PERM_DISABLED:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->PIN_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->PUK_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->READY:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->UNKNOWN:Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccCardConstants$State;->values()[Lcom/android/internal/telephony/IccCardConstants$State; -Lcom/android/internal/telephony/IccProvider;-><init>()V Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder; Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook; -Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEf(I)Ljava/util/List; -Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEfForSubscriber(II)Ljava/util/List; -Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSize(I)[I -Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSizeForSubscriber(II)[I -Lcom/android/internal/telephony/IIccPhoneBook;->updateAdnRecordsInEfBySearch(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms; -Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalCallStateListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V -Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalConnectionListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V -Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyCallForwardingIndicator()V -Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyPreciseCallStateChanged()V -Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getImsCall()Lcom/android/ims/ImsCall; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->findConnection(Lcom/android/ims/ImsCall;)Lcom/android/internal/telephony/imsphone/ImsPhoneConnection; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getEcbmInterface()Lcom/android/ims/ImsEcbm; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mCallExpectedToResume:Lcom/android/ims/ImsCall; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsCallListener:Lcom/android/ims/ImsCall$Listener; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsManager:Lcom/android/ims/ImsManager; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mUssdSession:Lcom/android/ims/ImsCall; -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;I)V -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;IZ)V -Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->setVideoCallProvider(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Lcom/android/ims/ImsCall;)V -Lcom/android/internal/telephony/imsphone/ImsPhoneConnection$MyHandler;-><init>(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Landroid/os/Looper;)V -Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mImsCall:Lcom/android/ims/ImsCall; -Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->update(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;)Z -Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;-><init>(Lcom/android/internal/telephony/InboundSmsHandler;Lcom/android/internal/telephony/InboundSmsTracker;)V Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener; Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String; @@ -1380,371 +1057,9 @@ Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry; Lcom/android/internal/telephony/IWapPushManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IWapPushManager; -Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState; -Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTING:Lcom/android/internal/telephony/PhoneConstants$DataState; -Lcom/android/internal/telephony/PhoneConstants$DataState;->DISCONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState; -Lcom/android/internal/telephony/PhoneConstants$DataState;->SUSPENDED:Lcom/android/internal/telephony/PhoneConstants$DataState; -Lcom/android/internal/telephony/PhoneConstants$DataState;->values()[Lcom/android/internal/telephony/PhoneConstants$DataState; -Lcom/android/internal/telephony/PhoneConstants$State;->IDLE:Lcom/android/internal/telephony/PhoneConstants$State; -Lcom/android/internal/telephony/PhoneConstants$State;->OFFHOOK:Lcom/android/internal/telephony/PhoneConstants$State; -Lcom/android/internal/telephony/PhoneConstants$State;->RINGING:Lcom/android/internal/telephony/PhoneConstants$State; -Lcom/android/internal/telephony/PhoneConstants$State;->values()[Lcom/android/internal/telephony/PhoneConstants$State; -Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_ALLOWED:I -Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_PAYPHONE:I -Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_RESTRICTED:I -Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_UNKNOWN:I -Lcom/android/internal/telephony/RILConstants;->PREFERRED_NETWORK_MODE:I -Lcom/android/internal/telephony/sip/SipPhone$SipCall;->hold()V -Lcom/android/internal/telephony/sip/SipPhone$SipCall;->switchWith(Lcom/android/internal/telephony/sip/SipPhone$SipCall;)V -Lcom/android/internal/telephony/sip/SipPhone$SipCall;->unhold()V -Lcom/android/internal/telephony/sip/SipPhone;->log(Ljava/lang/String;)V -Lcom/android/internal/telephony/sip/SipPhone;->loge(Ljava/lang/String;)V -Lcom/android/internal/telephony/sip/SipPhone;->mBackgroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall; -Lcom/android/internal/telephony/sip/SipPhone;->mForegroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall; -Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->DBG:Z -Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCDMA:Landroid/util/SparseIntArray; -Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCommon:Landroid/util/SparseIntArray; -Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableGSM:Landroid/util/SparseIntArray; -Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;->mApplicationName:Ljava/lang/String; -Lcom/android/internal/telephony/SmsApplication;->configurePreferredActivity(Landroid/content/pm/PackageManager;Landroid/content/ComponentName;I)V -Lcom/android/internal/telephony/SmsApplication;->getApplicationCollection(Landroid/content/Context;)Ljava/util/Collection; -Lcom/android/internal/telephony/SmsApplication;->getDefaultMmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName; -Lcom/android/internal/telephony/SmsApplication;->getDefaultRespondViaMessageApplication(Landroid/content/Context;Z)Landroid/content/ComponentName; -Lcom/android/internal/telephony/SmsApplication;->getDefaultSmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName; -Lcom/android/internal/telephony/SmsApplication;->getSmsApplicationData(Ljava/lang/String;Landroid/content/Context;)Lcom/android/internal/telephony/SmsApplication$SmsApplicationData; -Lcom/android/internal/telephony/SmsApplication;->isDefaultSmsApplication(Landroid/content/Context;Ljava/lang/String;)Z -Lcom/android/internal/telephony/SmsApplication;->setDefaultApplication(Ljava/lang/String;Landroid/content/Context;)V -Lcom/android/internal/telephony/SmsApplication;->shouldWriteMessageForPackage(Ljava/lang/String;Landroid/content/Context;)Z -Lcom/android/internal/telephony/SMSDispatcher$DataSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V -Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Ljava/util/ArrayList;[Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V -Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;)V -Lcom/android/internal/telephony/SMSDispatcher$SmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsSender;)V -Lcom/android/internal/telephony/SMSDispatcher$TextSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V -Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V -Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V -Lcom/android/internal/telephony/SmsMessageBase;-><init>()V -Lcom/android/internal/telephony/TelephonyProperties;->PROPERTY_ICC_OPERATOR_NUMERIC:Ljava/lang/String; -Lcom/android/internal/telephony/test/InterpreterEx;-><init>(Ljava/lang/String;)V -Lcom/android/internal/telephony/test/SimulatedCommands;->acceptCall(Landroid/os/Message;)V -Lcom/android/internal/telephony/test/SimulatedCommands;->mDcSuccess:Z -Lcom/android/internal/telephony/test/SimulatedCommands;->resultFail(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)V -Lcom/android/internal/telephony/test/SimulatedCommands;->resultSuccess(Landroid/os/Message;Ljava/lang/Object;)V -Lcom/android/internal/telephony/test/SimulatedCommands;->simulatedCallState:Lcom/android/internal/telephony/test/SimulatedGsmCallState; -Lcom/android/internal/telephony/test/SimulatedCommands;->unimplemented(Landroid/os/Message;)V -Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->getInstance()Lcom/android/internal/telephony/test/SimulatedCommandsVerifier; -Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->conference()Z -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->onChld(CC)Z -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseActiveAcceptHeldOrWaiting()Z -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseHeldOrUDUB()Z -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->separateCall(I)Z -Lcom/android/internal/telephony/test/SimulatedGsmCallState;->switchActiveAndHeldOrWaiting()Z -Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState; -Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType; -Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState; -Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;-><init>()V -Lcom/android/internal/telephony/uicc/IccRefreshResponse;-><init>()V -Lcom/android/internal/telephony/uicc/IccUtils;->adnStringFieldToString([BII)Ljava/lang/String; -Lcom/android/internal/telephony/uicc/IccUtils;->bcdToString([BII)Ljava/lang/String; -Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String; -Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdByteToInt(B)I -Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdToString([BII)Ljava/lang/String; -Lcom/android/internal/telephony/uicc/IccUtils;->gsmBcdByteToInt(B)I -Lcom/android/internal/telephony/uicc/IccUtils;->hexCharToInt(C)I -Lcom/android/internal/telephony/uicc/IccUtils;->hexStringToBytes(Ljava/lang/String;)[B -Lcom/android/internal/telephony/uicc/IccUtils;->networkNameToString([BII)Ljava/lang/String; -Lcom/android/internal/telephony/uicc/IccUtils;->parseToBnW([BI)Landroid/graphics/Bitmap; -Lcom/android/internal/telephony/uicc/IccUtils;->parseToRGB([BIZ)Landroid/graphics/Bitmap; -Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState; Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -Lcom/android/internal/util/MemInfoReader;-><init>()V Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager; Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession; Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings; Lcom/android/internal/widget/IRemoteViewsFactory$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/IRemoteViewsFactory; -Lcom/android/internal/widget/PointerLocationView$PointerState;-><init>()V -Lcom/android/server/net/BaseNetworkObserver;-><init>()V -Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V -Lcom/google/android/gles_jni/EGLImpl;-><init>()V -Lcom/google/android/gles_jni/GLImpl;-><init>()V -Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList; -Lcom/google/android/mms/ContentType;->getImageTypes()Ljava/util/ArrayList; -Lcom/google/android/mms/ContentType;->getVideoTypes()Ljava/util/ArrayList; -Lcom/google/android/mms/ContentType;->isAudioType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isDrmType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isImageType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isSupportedAudioType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isSupportedImageType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isSupportedType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isSupportedVideoType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isTextType(Ljava/lang/String;)Z -Lcom/google/android/mms/ContentType;->isVideoType(Ljava/lang/String;)Z -Lcom/google/android/mms/InvalidHeaderValueException;-><init>(Ljava/lang/String;)V -Lcom/google/android/mms/MmsException;-><init>()V -Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;)V -Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V -Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/Throwable;)V -Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(I[B)V -Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/AcknowledgeInd;->setReportAllowed(I)V -Lcom/google/android/mms/pdu/AcknowledgeInd;->setTransactionId([B)V -Lcom/google/android/mms/pdu/Base64;->decodeBase64([B)[B -Lcom/google/android/mms/pdu/CharacterSets;->getMibEnumValue(Ljava/lang/String;)I -Lcom/google/android/mms/pdu/CharacterSets;->getMimeName(I)Ljava/lang/String; -Lcom/google/android/mms/pdu/DeliveryInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/DeliveryInd;->getDate()J -Lcom/google/android/mms/pdu/DeliveryInd;->getMessageId()[B -Lcom/google/android/mms/pdu/DeliveryInd;->getStatus()I -Lcom/google/android/mms/pdu/DeliveryInd;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(I[B)V -Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(Ljava/lang/String;)V -Lcom/google/android/mms/pdu/EncodedStringValue;-><init>([B)V -Lcom/google/android/mms/pdu/EncodedStringValue;->appendTextString([B)V -Lcom/google/android/mms/pdu/EncodedStringValue;->concat([Lcom/google/android/mms/pdu/EncodedStringValue;)Ljava/lang/String; -Lcom/google/android/mms/pdu/EncodedStringValue;->copy(Lcom/google/android/mms/pdu/EncodedStringValue;)Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/EncodedStringValue;->encodeStrings([Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/EncodedStringValue;->extract(Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/EncodedStringValue;->getCharacterSet()I -Lcom/google/android/mms/pdu/EncodedStringValue;->getString()Ljava/lang/String; -Lcom/google/android/mms/pdu/EncodedStringValue;->getTextString()[B -Lcom/google/android/mms/pdu/EncodedStringValue;->setCharacterSet(I)V -Lcom/google/android/mms/pdu/EncodedStringValue;->setTextString([B)V -Lcom/google/android/mms/pdu/GenericPdu;-><init>()V -Lcom/google/android/mms/pdu/GenericPdu;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/GenericPdu;->getMessageType()I -Lcom/google/android/mms/pdu/GenericPdu;->getPduHeaders()Lcom/google/android/mms/pdu/PduHeaders; -Lcom/google/android/mms/pdu/GenericPdu;->mPduHeaders:Lcom/google/android/mms/pdu/PduHeaders; -Lcom/google/android/mms/pdu/GenericPdu;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/GenericPdu;->setMessageType(I)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>()V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->addTo(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getBody()Lcom/google/android/mms/pdu/PduBody; -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getDate()J -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getPriority()I -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setBody(Lcom/google/android/mms/pdu/PduBody;)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setDate(J)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setPriority(I)V -Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/NotificationInd;-><init>()V -Lcom/google/android/mms/pdu/NotificationInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/NotificationInd;->getContentClass()I -Lcom/google/android/mms/pdu/NotificationInd;->getContentLocation()[B -Lcom/google/android/mms/pdu/NotificationInd;->getDeliveryReport()I -Lcom/google/android/mms/pdu/NotificationInd;->getExpiry()J -Lcom/google/android/mms/pdu/NotificationInd;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/NotificationInd;->getMessageClass()[B -Lcom/google/android/mms/pdu/NotificationInd;->getMessageSize()J -Lcom/google/android/mms/pdu/NotificationInd;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/NotificationInd;->getTransactionId()[B -Lcom/google/android/mms/pdu/NotificationInd;->setContentClass(I)V -Lcom/google/android/mms/pdu/NotificationInd;->setContentLocation([B)V -Lcom/google/android/mms/pdu/NotificationInd;->setDeliveryReport(I)V -Lcom/google/android/mms/pdu/NotificationInd;->setExpiry(J)V -Lcom/google/android/mms/pdu/NotificationInd;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/NotificationInd;->setMessageClass([B)V -Lcom/google/android/mms/pdu/NotificationInd;->setMessageSize(J)V -Lcom/google/android/mms/pdu/NotificationInd;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/NotificationInd;->setTransactionId([B)V -Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(I[BI)V -Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/NotifyRespInd;->setReportAllowed(I)V -Lcom/google/android/mms/pdu/NotifyRespInd;->setStatus(I)V -Lcom/google/android/mms/pdu/NotifyRespInd;->setTransactionId([B)V -Lcom/google/android/mms/pdu/PduBody;-><init>()V -Lcom/google/android/mms/pdu/PduBody;->addPart(ILcom/google/android/mms/pdu/PduPart;)V -Lcom/google/android/mms/pdu/PduBody;->addPart(Lcom/google/android/mms/pdu/PduPart;)Z -Lcom/google/android/mms/pdu/PduBody;->getPart(I)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduBody;->getPartByContentId(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduBody;->getPartByContentLocation(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduBody;->getPartByFileName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduBody;->getPartByName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduBody;->getPartIndex(Lcom/google/android/mms/pdu/PduPart;)I -Lcom/google/android/mms/pdu/PduBody;->getPartsNum()I -Lcom/google/android/mms/pdu/PduBody;->removePart(I)Lcom/google/android/mms/pdu/PduPart; -Lcom/google/android/mms/pdu/PduComposer$BufferStack;->copy()V -Lcom/google/android/mms/pdu/PduComposer$BufferStack;->mark()Lcom/google/android/mms/pdu/PduComposer$PositionMarker; -Lcom/google/android/mms/pdu/PduComposer$BufferStack;->newbuf()V -Lcom/google/android/mms/pdu/PduComposer$BufferStack;->pop()V -Lcom/google/android/mms/pdu/PduComposer$PositionMarker;->getLength()I -Lcom/google/android/mms/pdu/PduComposer;-><init>(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)V -Lcom/google/android/mms/pdu/PduComposer;->appendEncodedString(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/PduComposer;->appendHeader(I)I -Lcom/google/android/mms/pdu/PduComposer;->appendLongInteger(J)V -Lcom/google/android/mms/pdu/PduComposer;->appendOctet(I)V -Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString(Ljava/lang/String;)V -Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString([B)V -Lcom/google/android/mms/pdu/PduComposer;->appendShortInteger(I)V -Lcom/google/android/mms/pdu/PduComposer;->appendTextString(Ljava/lang/String;)V -Lcom/google/android/mms/pdu/PduComposer;->appendTextString([B)V -Lcom/google/android/mms/pdu/PduComposer;->appendUintvarInteger(J)V -Lcom/google/android/mms/pdu/PduComposer;->appendValueLength(J)V -Lcom/google/android/mms/pdu/PduComposer;->arraycopy([BII)V -Lcom/google/android/mms/pdu/PduComposer;->make()[B -Lcom/google/android/mms/pdu/PduComposer;->mContentTypeMap:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduComposer;->mMessage:Ljava/io/ByteArrayOutputStream; -Lcom/google/android/mms/pdu/PduComposer;->mPdu:Lcom/google/android/mms/pdu/GenericPdu; -Lcom/google/android/mms/pdu/PduComposer;->mPduHeader:Lcom/google/android/mms/pdu/PduHeaders; -Lcom/google/android/mms/pdu/PduComposer;->mPosition:I -Lcom/google/android/mms/pdu/PduComposer;->mResolver:Landroid/content/ContentResolver; -Lcom/google/android/mms/pdu/PduComposer;->mStack:Lcom/google/android/mms/pdu/PduComposer$BufferStack; -Lcom/google/android/mms/pdu/PduContentTypes;->contentTypes:[Ljava/lang/String; -Lcom/google/android/mms/pdu/PduHeaders;-><init>()V -Lcom/google/android/mms/pdu/PduHeaders;->appendEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V -Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValue(I)Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValues(I)[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/PduHeaders;->getLongInteger(I)J -Lcom/google/android/mms/pdu/PduHeaders;->getOctet(I)I -Lcom/google/android/mms/pdu/PduHeaders;->getTextString(I)[B -Lcom/google/android/mms/pdu/PduHeaders;->setEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V -Lcom/google/android/mms/pdu/PduHeaders;->setLongInteger(JI)V -Lcom/google/android/mms/pdu/PduHeaders;->setOctet(II)V -Lcom/google/android/mms/pdu/PduParser;->$assertionsDisabled:Z -Lcom/google/android/mms/pdu/PduParser;-><init>([BZ)V -Lcom/google/android/mms/pdu/PduParser;->checkPartPosition(Lcom/google/android/mms/pdu/PduPart;)I -Lcom/google/android/mms/pdu/PduParser;->log(Ljava/lang/String;)V -Lcom/google/android/mms/pdu/PduParser;->parse()Lcom/google/android/mms/pdu/GenericPdu; -Lcom/google/android/mms/pdu/PduParser;->parseContentType(Ljava/io/ByteArrayInputStream;Ljava/util/HashMap;)[B -Lcom/google/android/mms/pdu/PduParser;->parsePartHeaders(Ljava/io/ByteArrayInputStream;Lcom/google/android/mms/pdu/PduPart;I)Z -Lcom/google/android/mms/pdu/PduParser;->parseShortInteger(Ljava/io/ByteArrayInputStream;)I -Lcom/google/android/mms/pdu/PduParser;->parseUnsignedInt(Ljava/io/ByteArrayInputStream;)I -Lcom/google/android/mms/pdu/PduParser;->parseValueLength(Ljava/io/ByteArrayInputStream;)I -Lcom/google/android/mms/pdu/PduParser;->parseWapString(Ljava/io/ByteArrayInputStream;I)[B -Lcom/google/android/mms/pdu/PduPart;-><init>()V -Lcom/google/android/mms/pdu/PduPart;->generateLocation()Ljava/lang/String; -Lcom/google/android/mms/pdu/PduPart;->getCharset()I -Lcom/google/android/mms/pdu/PduPart;->getContentDisposition()[B -Lcom/google/android/mms/pdu/PduPart;->getContentId()[B -Lcom/google/android/mms/pdu/PduPart;->getContentLocation()[B -Lcom/google/android/mms/pdu/PduPart;->getContentTransferEncoding()[B -Lcom/google/android/mms/pdu/PduPart;->getContentType()[B -Lcom/google/android/mms/pdu/PduPart;->getData()[B -Lcom/google/android/mms/pdu/PduPart;->getDataLength()I -Lcom/google/android/mms/pdu/PduPart;->getDataUri()Landroid/net/Uri; -Lcom/google/android/mms/pdu/PduPart;->getFilename()[B -Lcom/google/android/mms/pdu/PduPart;->getName()[B -Lcom/google/android/mms/pdu/PduPart;->setCharset(I)V -Lcom/google/android/mms/pdu/PduPart;->setContentDisposition([B)V -Lcom/google/android/mms/pdu/PduPart;->setContentId([B)V -Lcom/google/android/mms/pdu/PduPart;->setContentLocation([B)V -Lcom/google/android/mms/pdu/PduPart;->setContentTransferEncoding([B)V -Lcom/google/android/mms/pdu/PduPart;->setContentType([B)V -Lcom/google/android/mms/pdu/PduPart;->setData([B)V -Lcom/google/android/mms/pdu/PduPart;->setDataUri(Landroid/net/Uri;)V -Lcom/google/android/mms/pdu/PduPart;->setFilename([B)V -Lcom/google/android/mms/pdu/PduPart;->setName([B)V -Lcom/google/android/mms/pdu/PduPersister;->ADDRESS_FIELDS:[I -Lcom/google/android/mms/pdu/PduPersister;->CHARSET_COLUMN_NAME_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->ENCODED_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->getByteArrayFromPartColumn(Landroid/database/Cursor;I)[B -Lcom/google/android/mms/pdu/PduPersister;->getBytes(Ljava/lang/String;)[B -Lcom/google/android/mms/pdu/PduPersister;->getIntegerFromPartColumn(Landroid/database/Cursor;I)Ljava/lang/Integer; -Lcom/google/android/mms/pdu/PduPersister;->getPartContentType(Lcom/google/android/mms/pdu/PduPart;)Ljava/lang/String; -Lcom/google/android/mms/pdu/PduPersister;->getPduPersister(Landroid/content/Context;)Lcom/google/android/mms/pdu/PduPersister; -Lcom/google/android/mms/pdu/PduPersister;->getPendingMessages(J)Landroid/database/Cursor; -Lcom/google/android/mms/pdu/PduPersister;->load(Landroid/net/Uri;)Lcom/google/android/mms/pdu/GenericPdu; -Lcom/google/android/mms/pdu/PduPersister;->loadRecipients(ILjava/util/HashSet;Ljava/util/HashMap;Z)V -Lcom/google/android/mms/pdu/PduPersister;->LONG_COLUMN_NAME_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->mContentResolver:Landroid/content/ContentResolver; -Lcom/google/android/mms/pdu/PduPersister;->mContext:Landroid/content/Context; -Lcom/google/android/mms/pdu/PduPersister;->MESSAGE_BOX_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->move(Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri; -Lcom/google/android/mms/pdu/PduPersister;->mTelephonyManager:Landroid/telephony/TelephonyManager; -Lcom/google/android/mms/pdu/PduPersister;->OCTET_COLUMN_NAME_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->PART_PROJECTION:[Ljava/lang/String; -Lcom/google/android/mms/pdu/PduPersister;->PDU_CACHE_INSTANCE:Lcom/google/android/mms/util/PduCache; -Lcom/google/android/mms/pdu/PduPersister;->persist(Lcom/google/android/mms/pdu/GenericPdu;Landroid/net/Uri;ZZLjava/util/HashMap;)Landroid/net/Uri; -Lcom/google/android/mms/pdu/PduPersister;->persistAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/PduPersister;->persistPart(Lcom/google/android/mms/pdu/PduPart;JLjava/util/HashMap;)Landroid/net/Uri; -Lcom/google/android/mms/pdu/PduPersister;->TEXT_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap; -Lcom/google/android/mms/pdu/PduPersister;->toIsoString([B)Ljava/lang/String; -Lcom/google/android/mms/pdu/PduPersister;->updateAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/PduPersister;->updateHeaders(Landroid/net/Uri;Lcom/google/android/mms/pdu/SendReq;)V -Lcom/google/android/mms/pdu/PduPersister;->updateParts(Landroid/net/Uri;Lcom/google/android/mms/pdu/PduBody;Ljava/util/HashMap;)V -Lcom/google/android/mms/pdu/QuotedPrintable;->decodeQuotedPrintable([B)[B -Lcom/google/android/mms/pdu/ReadOrigInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/ReadOrigInd;->getMessageId()[B -Lcom/google/android/mms/pdu/ReadOrigInd;->getReadStatus()I -Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/EncodedStringValue;[BII[Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/ReadRecInd;->getMessageId()[B -Lcom/google/android/mms/pdu/ReadRecInd;->setDate(J)V -Lcom/google/android/mms/pdu/RetrieveConf;-><init>()V -Lcom/google/android/mms/pdu/RetrieveConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V -Lcom/google/android/mms/pdu/RetrieveConf;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/RetrieveConf;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/RetrieveConf;->getContentType()[B -Lcom/google/android/mms/pdu/RetrieveConf;->getDeliveryReport()I -Lcom/google/android/mms/pdu/RetrieveConf;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/RetrieveConf;->getMessageClass()[B -Lcom/google/android/mms/pdu/RetrieveConf;->getMessageId()[B -Lcom/google/android/mms/pdu/RetrieveConf;->getReadReport()I -Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveStatus()I -Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveText()Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/RetrieveConf;->getTransactionId()[B -Lcom/google/android/mms/pdu/RetrieveConf;->setContentType([B)V -Lcom/google/android/mms/pdu/RetrieveConf;->setDeliveryReport(I)V -Lcom/google/android/mms/pdu/RetrieveConf;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/RetrieveConf;->setMessageClass([B)V -Lcom/google/android/mms/pdu/RetrieveConf;->setMessageId([B)V -Lcom/google/android/mms/pdu/RetrieveConf;->setReadReport(I)V -Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveStatus(I)V -Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveText(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/RetrieveConf;->setTransactionId([B)V -Lcom/google/android/mms/pdu/SendConf;-><init>()V -Lcom/google/android/mms/pdu/SendConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V -Lcom/google/android/mms/pdu/SendConf;->getMessageId()[B -Lcom/google/android/mms/pdu/SendConf;->getResponseStatus()I -Lcom/google/android/mms/pdu/SendConf;->getTransactionId()[B -Lcom/google/android/mms/pdu/SendReq;-><init>()V -Lcom/google/android/mms/pdu/SendReq;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V -Lcom/google/android/mms/pdu/SendReq;->addBcc(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/SendReq;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/SendReq;->getBcc()[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/SendReq;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue; -Lcom/google/android/mms/pdu/SendReq;->getContentType()[B -Lcom/google/android/mms/pdu/SendReq;->getDeliveryReport()I -Lcom/google/android/mms/pdu/SendReq;->getExpiry()J -Lcom/google/android/mms/pdu/SendReq;->getMessageClass()[B -Lcom/google/android/mms/pdu/SendReq;->getMessageSize()J -Lcom/google/android/mms/pdu/SendReq;->getReadReport()I -Lcom/google/android/mms/pdu/SendReq;->getTransactionId()[B -Lcom/google/android/mms/pdu/SendReq;->setBcc([Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/SendReq;->setCc([Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/SendReq;->setContentType([B)V -Lcom/google/android/mms/pdu/SendReq;->setDeliveryReport(I)V -Lcom/google/android/mms/pdu/SendReq;->setExpiry(J)V -Lcom/google/android/mms/pdu/SendReq;->setMessageClass([B)V -Lcom/google/android/mms/pdu/SendReq;->setMessageSize(J)V -Lcom/google/android/mms/pdu/SendReq;->setReadReport(I)V -Lcom/google/android/mms/pdu/SendReq;->setTo([Lcom/google/android/mms/pdu/EncodedStringValue;)V -Lcom/google/android/mms/pdu/SendReq;->setTransactionId([B)V -Lcom/google/android/mms/util/AbstractCache;-><init>()V -Lcom/google/android/mms/util/AbstractCache;->get(Ljava/lang/Object;)Ljava/lang/Object; -Lcom/google/android/mms/util/AbstractCache;->purge(Ljava/lang/Object;)Ljava/lang/Object; -Lcom/google/android/mms/util/AbstractCache;->purgeAll()V -Lcom/google/android/mms/util/AbstractCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Z -Lcom/google/android/mms/util/DownloadDrmHelper;->isDrmConvertNeeded(Ljava/lang/String;)Z -Lcom/google/android/mms/util/DownloadDrmHelper;->modifyDrmFwLockFileExtension(Ljava/lang/String;)Ljava/lang/String; -Lcom/google/android/mms/util/DrmConvertSession;->close(Ljava/lang/String;)I -Lcom/google/android/mms/util/DrmConvertSession;->convert([BI)[B -Lcom/google/android/mms/util/DrmConvertSession;->open(Landroid/content/Context;Ljava/lang/String;)Lcom/google/android/mms/util/DrmConvertSession; -Lcom/google/android/mms/util/PduCache;-><init>()V -Lcom/google/android/mms/util/PduCache;->getInstance()Lcom/google/android/mms/util/PduCache; -Lcom/google/android/mms/util/PduCache;->isUpdating(Landroid/net/Uri;)Z -Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/android/mms/util/PduCacheEntry; -Lcom/google/android/mms/util/PduCache;->purgeAll()V -Lcom/google/android/mms/util/PduCacheEntry;-><init>(Lcom/google/android/mms/pdu/GenericPdu;IJ)V -Lcom/google/android/mms/util/PduCacheEntry;->getMessageBox()I -Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu; -Lcom/google/android/mms/util/PduCacheEntry;->getThreadId()J -Lcom/google/android/mms/util/SqliteWrapper;->checkSQLiteException(Landroid/content/Context;Landroid/database/sqlite/SQLiteException;)V -Lcom/google/android/mms/util/SqliteWrapper;->delete(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I -Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri; -Lcom/google/android/mms/util/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; -Lcom/google/android/mms/util/SqliteWrapper;->requery(Landroid/content/Context;Landroid/database/Cursor;)Z -Lcom/google/android/mms/util/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I -Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type; diff --git a/config/preloaded-classes b/config/preloaded-classes index 5d97c85c95e6..eb3879fdb50e 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -4835,7 +4835,6 @@ com.android.internal.telephony.PhoneConstantConversions com.android.internal.telephony.PhoneConstants$DataState com.android.internal.telephony.PhoneConstants$State com.android.internal.telephony.PhoneFactory -com.android.internal.telephony.PhoneInternalInterface$DataActivityState com.android.internal.telephony.PhoneInternalInterface com.android.internal.telephony.PhoneNotifier com.android.internal.telephony.PhoneStateIntentReceiver diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index 25cd342cb5e9..6470a04aefd6 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -103,8 +103,6 @@ import java.util.Arrays; * When writing an activity to satisfy these requests one must pass in the AccountManagerResponse * and return the result via that response when the activity finishes (or whenever else the * activity author deems it is the correct time to respond). - * The {@link AccountAuthenticatorActivity} handles this, so one may wish to extend that when - * writing activities to handle these requests. */ public abstract class AbstractAccountAuthenticator { private static final String TAG = "AccountAuthenticator"; diff --git a/core/java/android/accounts/AccountAuthenticatorActivity.java b/core/java/android/accounts/AccountAuthenticatorActivity.java index 967aa0424b1d..65ba35ff9e8d 100644 --- a/core/java/android/accounts/AccountAuthenticatorActivity.java +++ b/core/java/android/accounts/AccountAuthenticatorActivity.java @@ -32,7 +32,11 @@ import android.os.Bundle; * This result will be sent as the result of the request when the activity finishes. If this * is never set or if it is set to null then error {@link AccountManager#ERROR_CODE_CANCELED} * will be called on the response. + * + * @deprecated Applications should extend Activity themselves. This class is not compatible with + * AppCompat, and the functionality it provides is not complex. */ +@Deprecated public class AccountAuthenticatorActivity extends Activity { private AccountAuthenticatorResponse mAccountAuthenticatorResponse = null; private Bundle mResultBundle = null; diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 26c2c0cfdd5d..c80be8e5c3fa 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -2226,6 +2226,8 @@ public class AccountManager { } private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> { + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) final IAccountManagerResponse mResponse; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index ebb03e765a47..764e5992fbd9 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -296,6 +296,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio /** * @hide */ + @UnsupportedAppUsage @TestApi public static void setDurationScale(float durationScale) { sDurationScale = durationScale; @@ -304,6 +305,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio /** * @hide */ + @UnsupportedAppUsage @TestApi public static float getDurationScale() { return sDurationScale; diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 4828c742a7ff..151c03f1fb06 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2797,6 +2797,7 @@ public class Activity extends ContextThemeWrapper * @see View#onMovedToDisplay(int, Configuration) * @hide */ + @UnsupportedAppUsage @TestApi public void onMovedToDisplay(int displayId, Configuration config) { } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 91b98c71a613..e8e4085f731d 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -153,6 +153,12 @@ public class ActivityManager { */ public static final int INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL = 1 << 1; + /** + * Disable test API access for the newly started instrumentation. + * @hide + */ + public static final int INSTR_FLAG_DISABLE_TEST_API_CHECKS = 1 << 2; + static final class UidObserver extends IUidObserver.Stub { final OnUidImportanceListener mListener; final Context mContext; @@ -2893,6 +2899,7 @@ public class ActivityManager { * * @hide */ + @UnsupportedAppUsage @TestApi public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 37509e18ba6f..607ef185ae60 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -25,6 +25,11 @@ import android.os.IBinder; */ @Deprecated public abstract class ActivityManagerNative { + + @UnsupportedAppUsage + public ActivityManagerNative() { + } + /** * Cast a Binder object into an activity manager interface, generating * a proxy if needed. diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f0dcc51c746a..4e8bee24052e 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -714,6 +714,9 @@ public final class ActivityThread extends ClientTransactionHandler { static final class CreateServiceData { @UnsupportedAppUsage + CreateServiceData() { + } + @UnsupportedAppUsage IBinder token; @UnsupportedAppUsage ServiceInfo info; @@ -755,6 +758,9 @@ public final class ActivityThread extends ClientTransactionHandler { static final class AppBindData { @UnsupportedAppUsage + AppBindData() { + } + @UnsupportedAppUsage LoadedApk info; @UnsupportedAppUsage String processName; diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java index 37565298c8cb..37be90160d9a 100644 --- a/core/java/android/app/AliasActivity.java +++ b/core/java/android/app/AliasActivity.java @@ -39,7 +39,10 @@ import java.io.IOException; * To use this activity, you should include in the manifest for the associated * component an entry named "android.app.alias". It is a reference to an XML * resource describing an intent that launches the real application. + * + * @deprecated Use {@code <activity-alias>} or subclass Activity directly. */ +@Deprecated public class AliasActivity extends Activity { /** * This is the name under which you should store in your component the diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index da4c0386a76f..aedf4b54fd3f 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -570,6 +570,7 @@ public class AppOpsManager { @UnsupportedAppUsage public static final int OP_NONE = -1; /** @hide Access to coarse location information. */ + @UnsupportedAppUsage @TestApi public static final int OP_COARSE_LOCATION = 0; /** @hide Access to fine location information. */ @@ -642,6 +643,7 @@ public class AppOpsManager { @UnsupportedAppUsage public static final int OP_WRITE_SETTINGS = 23; /** @hide Required to draw on top of other apps. */ + @UnsupportedAppUsage @TestApi public static final int OP_SYSTEM_ALERT_WINDOW = 24; /** @hide */ @@ -651,6 +653,7 @@ public class AppOpsManager { @UnsupportedAppUsage public static final int OP_CAMERA = 26; /** @hide */ + @UnsupportedAppUsage @TestApi public static final int OP_RECORD_AUDIO = 27; /** @hide */ @@ -798,6 +801,7 @@ public class AppOpsManager { @UnsupportedAppUsage public static final int OP_MANAGE_IPSEC_TUNNELS = 75; /** @hide Any app start foreground service. */ + @UnsupportedAppUsage @TestApi public static final int OP_START_FOREGROUND = 76; /** @hide */ @@ -2058,6 +2062,7 @@ public class AppOpsManager { * Retrieve the permission associated with an operation, or null if there is not one. * @hide */ + @UnsupportedAppUsage @TestApi public static String opToPermission(int op) { return sOpPerms[op]; @@ -2090,6 +2095,7 @@ public class AppOpsManager { * to the corresponding app op. * @hide */ + @UnsupportedAppUsage @TestApi public static int permissionToOpCode(String permission) { Integer boxedOpCode = sPermToOp.get(permission); @@ -4578,6 +4584,7 @@ public class AppOpsManager { } /** @hide */ + @UnsupportedAppUsage @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(int code, int uid, String packageName, @Mode int mode) { @@ -4905,6 +4912,7 @@ public class AppOpsManager { /** * {@hide} */ + @UnsupportedAppUsage @TestApi public static int strOpToOp(@NonNull String op) { Integer val = sOpStrToOp.get(op); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 360be350601d..835769f69951 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -3121,6 +3121,15 @@ public class ApplicationPackageManager extends PackageManager { } @Override + public String[] getTelephonyPackageNames() { + try { + return mPM.getTelephonyPackageNames(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + @Override public String getSystemCaptionsServicePackageName() { try { return mPM.getSystemCaptionsServicePackageName(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index b915473cf34e..9902f6aa0fe3 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -72,6 +72,7 @@ import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructStat; +import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.Log; @@ -1330,6 +1331,19 @@ class ContextImpl extends Context { } @Override + public void sendOrderedBroadcast(Intent intent, String receiverPermission, + String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler, + int initialCode, String initialData, @Nullable Bundle initialExtras) { + int intAppOp = AppOpsManager.OP_NONE; + if (!TextUtils.isEmpty(receiverAppOp)) { + intAppOp = AppOpsManager.strOpToOp(receiverAppOp); + } + sendOrderedBroadcastAsUser(intent, getUser(), + receiverPermission, intAppOp, resultReceiver, scheduler, initialCode, initialData, + initialExtras); + } + + @Override @Deprecated public void sendStickyBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); @@ -2307,6 +2321,7 @@ class ContextImpl extends Context { return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0; } + @UnsupportedAppUsage @TestApi @Override public Display getDisplay() { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 48ca71690a1b..feaddda044c4 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -122,6 +122,7 @@ interface IActivityManager { in String resultData, in Bundle map, in String[] requiredPermissions, int appOp, in Bundle options, boolean serialized, boolean sticky, int userId); void unbroadcastIntent(in IApplicationThread caller, in Intent intent, int userId); + @UnsupportedAppUsage oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map, boolean abortBroadcast, int flags); void attachApplication(in IApplicationThread app, long startSeq); @@ -211,6 +212,7 @@ interface IActivityManager { @UnsupportedAppUsage ParceledListSlice getRecentTasks(int maxNum, int flags, int userId); + @UnsupportedAppUsage oneway void serviceDoneExecuting(in IBinder token, int type, int startId, int res); @UnsupportedAppUsage IIntentSender getIntentSender(int type, in String packageName, in IBinder token, diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl index cae54b6c0611..f2c9f615c03f 100644 --- a/core/java/android/app/IUiModeManager.aidl +++ b/core/java/android/app/IUiModeManager.aidl @@ -30,6 +30,7 @@ interface IUiModeManager { /** * Disables the car mode. */ + @UnsupportedAppUsage(maxTargetSdk = 28) void disableCarMode(int flags); /** diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index dd39376f80ca..903dd493d187 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1638,7 +1638,7 @@ public class NotificationManager { @Override public int hashCode() { return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders, - suppressedVisualEffects); + suppressedVisualEffects, state); } @Override @@ -1650,10 +1650,10 @@ public class NotificationManager { && other.priorityCallSenders == priorityCallSenders && other.priorityMessageSenders == priorityMessageSenders && suppressedVisualEffectsEqual(suppressedVisualEffects, - other.suppressedVisualEffects); + other.suppressedVisualEffects) + && other.state == this.state; } - private boolean suppressedVisualEffectsEqual(int suppressedEffects, int otherSuppressedVisualEffects) { if (suppressedEffects == otherSuppressedVisualEffects) { diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java index 20ae84ca8c39..b7b0b192e7ae 100644 --- a/core/java/android/app/PackageDeleteObserver.java +++ b/core/java/android/app/PackageDeleteObserver.java @@ -22,6 +22,11 @@ import android.content.pm.IPackageDeleteObserver2; /** {@hide} */ public class PackageDeleteObserver { + + @UnsupportedAppUsage + public PackageDeleteObserver() { + } + private final IPackageDeleteObserver2.Stub mBinder = new IPackageDeleteObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java index 507ebe566d46..50031e0e4d35 100644 --- a/core/java/android/app/PackageInstallObserver.java +++ b/core/java/android/app/PackageInstallObserver.java @@ -23,6 +23,11 @@ import android.os.Bundle; /** {@hide} */ public class PackageInstallObserver { + + @UnsupportedAppUsage + public PackageInstallObserver() { + } + private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 40cb29fc80ab..e9ae60f23cf2 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -145,6 +145,9 @@ public class ResourcesManager { * Resources and base configuration override associated with an Activity. */ private static class ActivityResources { + @UnsupportedAppUsage + private ActivityResources() { + } public final Configuration overrideConfig = new Configuration(); public final ArrayList<WeakReference<Resources>> activityResources = new ArrayList<>(); } @@ -164,6 +167,10 @@ public class ResourcesManager { mAdjustedDisplays = new ArrayMap<>(); @UnsupportedAppUsage + public ResourcesManager() { + } + + @UnsupportedAppUsage public static ResourcesManager getInstance() { synchronized (ResourcesManager.class) { if (sResourcesManager == null) { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index cfe2cf09ae19..587d7b132c10 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -157,6 +157,7 @@ import android.os.health.SystemHealthManager; import android.os.image.DynamicSystemManager; import android.os.image.IDynamicSystemService; import android.os.storage.StorageManager; +import android.telephony.TelephonyRegistryManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; @@ -172,7 +173,6 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccCardManager; import android.telephony.euicc.EuiccManager; -import android.telephony.ims.RcsMessageManager; import android.util.ArrayMap; import android.util.Log; import android.view.ContextThemeWrapper; @@ -607,6 +607,13 @@ final class SystemServiceRegistry { return new TelephonyManager(ctx.getOuterContext()); }}); + registerService(Context.TELEPHONY_REGISTRY_SERVICE, TelephonyRegistryManager.class, + new CachedServiceFetcher<TelephonyRegistryManager>() { + @Override + public TelephonyRegistryManager createService(ContextImpl ctx) { + return new TelephonyRegistryManager(ctx); + }}); + registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class, new CachedServiceFetcher<SubscriptionManager>() { @Override @@ -614,14 +621,6 @@ final class SystemServiceRegistry { return new SubscriptionManager(ctx.getOuterContext()); }}); - registerService(Context.TELEPHONY_RCS_MESSAGE_SERVICE, RcsMessageManager.class, - new CachedServiceFetcher<RcsMessageManager>() { - @Override - public RcsMessageManager createService(ContextImpl ctx) { - return new RcsMessageManager(ctx.getOuterContext()); - } - }); - registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class, new CachedServiceFetcher<CarrierConfigManager>() { @Override diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index b63feb590ad1..02ab25a1e4aa 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -30,6 +30,11 @@ import android.os.RemoteException; * @hide */ public abstract class TaskStackListener extends ITaskStackListener.Stub { + + @UnsupportedAppUsage + public TaskStackListener() { + } + @Override @UnsupportedAppUsage public void onTaskStackChanged() throws RemoteException { diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index dc07df8d7a87..f251b3eb4a15 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -40,6 +40,8 @@ import android.view.WindowContentFrameStats; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.IAccessibilityManager; +import dalvik.annotation.compat.UnsupportedAppUsage; + import libcore.io.IoUtils; import java.io.FileInputStream; @@ -87,6 +89,10 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { private int mOwningUid; + @UnsupportedAppUsage + public UiAutomationConnection() { + } + @Override public void connect(IAccessibilityServiceClient client, int flags) { if (client == null) { diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java index 25b243d95fa1..2f8ee744bfd6 100644 --- a/core/java/android/app/UserSwitchObserver.java +++ b/core/java/android/app/UserSwitchObserver.java @@ -24,6 +24,11 @@ import android.os.RemoteException; * @hide */ public class UserSwitchObserver extends IUserSwitchObserver.Stub { + + @UnsupportedAppUsage + public UserSwitchObserver() { + } + @Override public void onUserSwitching(int newUserId, IRemoteCallback reply) throws RemoteException { if (reply != null) { diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java index affc8b9283fb..74237b4bfcb1 100644 --- a/core/java/android/app/WindowConfiguration.java +++ b/core/java/android/app/WindowConfiguration.java @@ -35,6 +35,8 @@ import android.util.proto.ProtoOutputStream; import android.util.proto.WireTypeMismatchException; import android.view.DisplayInfo; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.io.IOException; /** @@ -199,6 +201,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu /** @hide */ public static final int PINNED_WINDOWING_MODE_ELEVATION_IN_DIP = 5; + @UnsupportedAppUsage public WindowConfiguration() { unset(); } diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 8e40449fa546..6bade901826a 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -146,6 +146,7 @@ public class NetworkStatsManager { } /** @hide */ + @UnsupportedAppUsage @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e7ba85ad5d9e..9d152a7faf44 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1189,13 +1189,11 @@ public final class BluetoothAdapter { /** * Factory reset bluetooth settings. * - * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} - * permission - * * @return true to indicate that the config file was successfully cleared * @hide */ - @UnsupportedAppUsage + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean factoryReset() { try { mServiceLock.readLock().lock(); @@ -1214,13 +1212,12 @@ public final class BluetoothAdapter { /** * Get the UUIDs supported by the local Bluetooth adapter. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} - * * @return the UUIDs supported by the local Bluetooth Adapter. * @hide */ @UnsupportedAppUsage - public ParcelUuid[] getUuids() { + @RequiresPermission(Manifest.permission.BLUETOOTH) + public @NonNull ParcelUuid[] getUuids() { if (getState() != STATE_ON) { return null; } @@ -1476,7 +1473,6 @@ public final class BluetoothAdapter { * will return false. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} * <p>Applications cannot set the scan mode. They should use * <code>startActivityForResult( * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) @@ -1488,8 +1484,8 @@ public final class BluetoothAdapter { * @return true if the scan mode was set, false otherwise * @hide */ - @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which " - + "shows UI that confirms the user wants to go into discoverable mode.") + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH) public boolean setScanMode(@ScanMode int mode, int duration) { if (getState() != STATE_ON) { return false; @@ -1507,9 +1503,34 @@ public final class BluetoothAdapter { return false; } - /** @hide */ - @UnsupportedAppUsage - public boolean setScanMode(int mode) { + /** + * Set the Bluetooth scan mode of the local Bluetooth adapter. + * <p>The Bluetooth scan mode determines if the local adapter is + * connectable and/or discoverable from remote Bluetooth devices. + * <p>For privacy reasons, discoverable mode is automatically turned off + * after <code>duration</code> seconds. For example, 120 seconds should be + * enough for a remote device to initiate and complete its discovery + * process. + * <p>Valid scan mode values are: + * {@link #SCAN_MODE_NONE}, + * {@link #SCAN_MODE_CONNECTABLE}, + * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. + * <p>Applications cannot set the scan mode. They should use + * <code>startActivityForResult( + * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) + * </code>instead. + * + * @param mode valid scan mode + * @return true if the scan mode was set, false otherwise + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH) + public boolean setScanMode(@ScanMode int mode) { if (getState() != STATE_ON) { return false; } @@ -1562,6 +1583,8 @@ public final class BluetoothAdapter { * been called recently. * @hide */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH) public long getDiscoveryEndMillis() { try { mServiceLock.readLock().lock(); @@ -1711,6 +1734,56 @@ public final class BluetoothAdapter { } /** + * Connects all enabled and supported bluetooth profiles between the local and remote device + * + * @param device is the remote device with which to connect these profiles + * @return true if all profiles successfully connected, false if an error occurred + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.connectAllEnabledProfiles(device); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + return false; + } + + /** + * Disconnects all enabled and supported bluetooth profiles between the local and remote device + * + * @param device is the remote device with which to disconnect these profiles + * @return true if all profiles successfully disconnected, false if an error occurred + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.disconnectAllEnabledProfiles(device); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + return false; + } + + /** * Return true if the multi advertisement is supported by the chipset * * @return true if Multiple Advertisement feature is supported @@ -2060,7 +2133,7 @@ public final class BluetoothAdapter { * BluetoothProfile}. * @hide */ - public List<Integer> getSupportedProfiles() { + public @NonNull List<Integer> getSupportedProfiles() { final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>(); try { diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index c6160446c798..0be3eca8239e 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -173,13 +173,10 @@ public final class BluetoothDevice implements Parcelable { * changed. * <p>Always contains the extra field {@link #EXTRA_DEVICE}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. - * - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @UnsupportedAppUsage public static final String ACTION_ALIAS_CHANGED = - "android.bluetooth.device.action.ALIAS_CHANGED"; + "android.bluetooth.action.ALIAS_CHANGED"; /** * Broadcast Action: Indicates a change in the bond state of a remote @@ -1048,10 +1045,11 @@ public final class BluetoothDevice implements Parcelable { * Get the Bluetooth alias of the remote device. * <p>Alias is the locally modified name of a remote device. * - * @return the Bluetooth alias, or null if no alias or there was a problem - * @hide + * @return the Bluetooth alias, the friendly device name if no alias, or + * null if there was a problem */ - @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.") + @Nullable + @RequiresPermission(Manifest.permission.BLUETOOTH) public String getAlias() { final IBluetooth service = sService; if (service == null) { @@ -1059,7 +1057,11 @@ public final class BluetoothDevice implements Parcelable { return null; } try { - return service.getRemoteAlias(this); + String alias = service.getRemoteAlias(this); + if (alias == null) { + return getName(); + } + return alias; } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1076,8 +1078,9 @@ public final class BluetoothDevice implements Parcelable { * @return true on success, false on error * @hide */ - @UnsupportedAppUsage - public boolean setAlias(String alias) { + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH) + public boolean setAlias(@NonNull String alias) { final IBluetooth service = sService; if (service == null) { Log.e(TAG, "BT not enabled. Cannot set Remote Device name"); @@ -1092,24 +1095,6 @@ public final class BluetoothDevice implements Parcelable { } /** - * Get the Bluetooth alias of the remote device. - * If Alias is null, get the Bluetooth name instead. - * - * @return the Bluetooth alias, or null if no alias or there was a problem - * @hide - * @see #getAlias() - * @see #getName() - */ - @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.") - public String getAliasName() { - String name = getAlias(); - if (name == null) { - name = getName(); - } - return name; - } - - /** * Get the most recent identified battery level of this Bluetooth device * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index dabe0fdac39a..f5aa01458481 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -324,4 +324,54 @@ public interface BluetoothProfile { return "STATE_UNKNOWN"; } } + + /** + * Convert an integer value of profile ID into human readable string + * + * @param profile profile ID + * @return profile name as String, UNKOWN_PROFILE if the profile ID is not defined. + * @hide + */ + static String getProfileName(int profile) { + switch(profile) { + case HEADSET: + return "HEADSET"; + case A2DP: + return "A2DP"; + case HID_HOST: + return "HID_HOST"; + case PAN: + return "PAN"; + case PBAP: + return "PBAP"; + case GATT: + return "GATT"; + case GATT_SERVER: + return "GATT_SERVER"; + case MAP: + return "MAP"; + case SAP: + return "SAP"; + case A2DP_SINK: + return "A2DP_SINK"; + case AVRCP_CONTROLLER: + return "AVRCP_CONTROLLER"; + case AVRCP: + return "AVRCP"; + case HEADSET_CLIENT: + return "HEADSET_CLIENT"; + case PBAP_CLIENT: + return "PBAP_CLIENT"; + case MAP_CLIENT: + return "MAP_CLIENT"; + case HID_DEVICE: + return "HID_DEVICE"; + case OPP: + return "OPP"; + case HEARING_AID: + return "HEARING_AID"; + default: + return "UNKNOWN_PROFILE"; + } + } } diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java index 75e726bfad0d..0f67f6b50251 100644 --- a/core/java/android/companion/BluetoothDeviceFilterUtils.java +++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java @@ -129,7 +129,7 @@ public class BluetoothDeviceFilterUtils { @UnsupportedAppUsage public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) { - return firstNotEmpty(device.getAliasName(), device.getAddress()); + return firstNotEmpty(device.getAlias(), device.getAddress()); } @UnsupportedAppUsage diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl index 5f73e551d57c..c9dc019bd2f2 100644 --- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl +++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl @@ -18,6 +18,8 @@ package android.companion; /** @hide */ interface ICompanionDeviceDiscoveryServiceCallback { + @UnsupportedAppUsage oneway void onDeviceSelected(String packageName, int userId, String deviceAddress); + @UnsupportedAppUsage oneway void onDeviceSelectionCancel(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 51bb85a7fe8e..a12e4da6e23e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -63,6 +63,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.MediaStore; +import android.telephony.TelephonyRegistryManager; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayAdjustments; @@ -2393,6 +2394,44 @@ public abstract class Context { @Nullable String initialData, @Nullable Bundle initialExtras); /** + * Version of + * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, + * Bundle)} that allows you to specify the App Op to enforce restrictions on which receivers + * the broadcast will be sent to. + * + * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param receiverPermission String naming a permissions that + * a receiver must hold in order to receive your broadcast. + * If null, no permission is required. + * @param receiverAppOp The app op associated with the broadcast. If null, no appOp is + * required. If both receiverAppOp and receiverPermission are non-null, + * a receiver must have both of them to + * receive the broadcast + * @param resultReceiver Your own BroadcastReceiver to treat as the final + * receiver of the broadcast. + * @param scheduler A custom Handler with which to schedule the + * resultReceiver callback; if null it will be + * scheduled in the Context's main thread. + * @param initialCode An initial value for the result code. Often + * Activity.RESULT_OK. + * @param initialData An initial value for the result data. Often + * null. + * @param initialExtras An initial value for the result extras. Often + * null. + * + * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) + */ + public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, + @Nullable String receiverPermission, @Nullable String receiverAppOp, + @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, + int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the * Intent you are sending stays around after the broadcast is complete, * so that others can quickly retrieve that data through the return @@ -4688,6 +4727,13 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve an + * {@link android.telephony.ims.ImsManager}. + * @hide + */ + public static final String TELEPHONY_IMS_SERVICE = "telephony_ims"; + + /** + * Use with {@link #getSystemService(String)} to retrieve an * {@link android.telephony.ims.RcsMessageManager}. * @hide */ @@ -4701,6 +4747,14 @@ public abstract class Context { public static final String DYNAMIC_SYSTEM_SERVICE = "dynamic_system"; /** + * Use with {@link #getSystemService(String)} to retrieve an + * {@link TelephonyRegistryManager}. + * @hide + */ + @SystemApi + public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * @@ -5247,6 +5301,7 @@ public abstract class Context { * Get the user associated with this context * @hide */ + @UnsupportedAppUsage @TestApi public @UserIdInt int getUserId() { return android.os.UserHandle.myUserId(); @@ -5363,6 +5418,7 @@ public abstract class Context { * @return Returns the {@link Display} object this context is associated with. * @hide */ + @UnsupportedAppUsage @TestApi public abstract Display getDisplay(); diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 0859f97e81a1..2b1b8eb183ab 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -16,6 +16,9 @@ package android.content; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -61,12 +64,12 @@ public class ContextWrapper extends Context { public ContextWrapper(Context base) { mBase = base; } - + /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. - * + * * @param base The new base context for this wrapper. */ protected void attachBaseContext(Context base) { @@ -117,7 +120,7 @@ public class ContextWrapper extends Context { public Context getApplicationContext() { return mBase.getApplicationContext(); } - + @Override public void setTheme(int resid) { mBase.setTheme(resid); @@ -162,7 +165,7 @@ public class ContextWrapper extends Context { public ApplicationInfo getApplicationInfo() { return mBase.getApplicationInfo(); } - + @Override public String getPackageResourcePath() { return mBase.getPackageResourcePath(); @@ -202,13 +205,13 @@ public class ContextWrapper extends Context { @Override public FileInputStream openFileInput(String name) - throws FileNotFoundException { + throws FileNotFoundException { return mBase.openFileInput(name); } @Override public FileOutputStream openFileOutput(String name, int mode) - throws FileNotFoundException { + throws FileNotFoundException { return mBase.openFileOutput(name, mode); } @@ -442,7 +445,7 @@ public class ContextWrapper extends Context { mBase.startIntentSender(intent, fillInIntent, flagsMask, flagsValues, extraFlags, options); } - + @Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); @@ -487,9 +490,9 @@ public class ContextWrapper extends Context { @Override public void sendOrderedBroadcast( - Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { + Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { mBase.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras); @@ -499,7 +502,8 @@ public class ContextWrapper extends Context { @SystemApi @Override public void sendOrderedBroadcast( - Intent intent, String receiverPermission, Bundle options, BroadcastReceiver resultReceiver, + Intent intent, String receiverPermission, Bundle options, + BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { mBase.sendOrderedBroadcast(intent, receiverPermission, @@ -510,9 +514,9 @@ public class ContextWrapper extends Context { /** @hide */ @Override public void sendOrderedBroadcast( - Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { + Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { mBase.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver, scheduler, initialCode, initialData, initialExtras); @@ -570,6 +574,15 @@ public class ContextWrapper extends Context { } @Override + public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, + @Nullable String receiverPermission, @Nullable String receiverAppOp, + @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, + int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) { + mBase.sendOrderedBroadcast(intent, receiverPermission, receiverAppOp, resultReceiver, + scheduler, initialCode, initialData, initialExtras); + } + + @Override @Deprecated public void sendStickyBroadcast(Intent intent) { mBase.sendStickyBroadcast(intent); @@ -926,6 +939,7 @@ public class ContextWrapper extends Context { } /** @hide */ + @UnsupportedAppUsage @TestApi @Override public Display getDisplay() { diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java index f6a0d771bf4c..f9c58d624a2f 100644 --- a/core/java/android/content/UndoManager.java +++ b/core/java/android/content/UndoManager.java @@ -18,8 +18,6 @@ package android.content; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; -import android.os.Parcelable; -import android.os.ParcelableParcel; import android.text.TextUtils; import android.util.ArrayMap; @@ -88,6 +86,10 @@ public class UndoManager { public static final int MERGE_MODE_ANY = 2; @UnsupportedAppUsage + public UndoManager() { + } + + @UnsupportedAppUsage public UndoOwner getOwner(String tag, Object data) { if (tag == null) { throw new NullPointerException("tag can't be null"); diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 415c2428405f..95e5f6b322ad 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -1237,6 +1237,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { * Determines whether the {@link Activity} is considered translucent or floating. * @hide */ + @UnsupportedAppUsage @TestApi public static boolean isTranslucentOrFloating(TypedArray attributes) { final boolean isTranslucent = diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index d6b70e0d80e3..0ea1845b6c2d 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -470,6 +470,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * * {@hide} */ + @UnsupportedAppUsage @TestApi public static final int PRIVATE_FLAG_PRIVILEGED = 1<<3; @@ -733,6 +734,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants. * @hide */ + @UnsupportedAppUsage @TestApi public @ApplicationInfoPrivateFlags int privateFlags; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a7eecd7f4306..7538dca76d18 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -753,6 +753,8 @@ interface IPackageManager { String getWellbeingPackageName(); + String[] getTelephonyPackageNames(); + String getAppPredictionServicePackageName(); String getSystemCaptionsServicePackageName(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 1a44aa1ee46c..81670cd0d2b8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3285,6 +3285,7 @@ public abstract class PackageManager { * * @hide */ + @UnsupportedAppUsage @TestApi public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services"; @@ -3297,6 +3298,7 @@ public abstract class PackageManager { * * @hide */ + @UnsupportedAppUsage @TestApi public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared"; @@ -3919,6 +3921,7 @@ public abstract class PackageManager { * * @hide */ + @UnsupportedAppUsage @NonNull @TestApi public abstract String getPermissionControllerPackageName(); @@ -4625,6 +4628,7 @@ public abstract class PackageManager { * * @hide */ + @UnsupportedAppUsage @TestApi public abstract @NonNull String getServicesSystemSharedLibraryPackageName(); @@ -4635,6 +4639,7 @@ public abstract class PackageManager { * * @hide */ + @UnsupportedAppUsage @TestApi public abstract @NonNull String getSharedSystemSharedLibraryPackageName(); @@ -7363,6 +7368,18 @@ public abstract class PackageManager { } /** + * @return the system defined telephony package names, or null if there's none. + * + * @hide + */ + @Nullable + @TestApi + public String[] getTelephonyPackageNames() { + throw new UnsupportedOperationException( + "getTelephonyPackageNames not implemented in subclass"); + } + + /** * @return the system defined content capture service package name, or null if there's none. * * @hide diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 672994e79134..30a3bd4d0738 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -59,6 +59,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_CONFIGURATOR = 9; public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10; public static final int PACKAGE_APP_PREDICTOR = 11; + public static final int PACKAGE_TELEPHONY = 12; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, @@ -72,6 +73,7 @@ public abstract class PackageManagerInternal { PACKAGE_CONFIGURATOR, PACKAGE_INCIDENT_REPORT_APPROVER, PACKAGE_APP_PREDICTOR, + PACKAGE_TELEPHONY, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} @@ -413,6 +415,17 @@ public abstract class PackageManagerInternal { @ResolveInfoFlags int flags, int filterCallingUid, int userId); /** + * Retrieve all activities that can be performed for the given intent. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#queryIntentActivities(Intent, int) + */ + public abstract List<ResolveInfo> queryIntentActivities( + Intent intent, @Nullable String resolvedType, @ResolveInfoFlags int flags, + int filterCallingUid, int userId); + + + /** * Retrieve all services that can be performed for the given intent. * @see PackageManager#queryIntentServices(Intent, int) */ @@ -715,10 +728,11 @@ public abstract class PackageManagerInternal { */ public abstract boolean isResolveActivityComponent(@NonNull ComponentInfo component); + /** - * Returns the package name for a known package. + * Returns a list of package names for a known package */ - public abstract @Nullable String getKnownPackageName( + public abstract @NonNull String[] getKnownPackageNames( @KnownPackage int knownPackage, int userId); /** diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index f15b5d75d616..5c5c13d566c5 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -618,21 +618,6 @@ public class PackageParser { } /** - * Generate and return the {@link PackageInfo} for a parsed package. - * - * @param p the parsed package. - * @param flags indicating which optional information is included. - */ - @UnsupportedAppUsage - public static PackageInfo generatePackageInfo(PackageParser.Package p, - int gids[], int flags, long firstInstallTime, long lastUpdateTime, - Set<String> grantedPermissions, PackageUserState state) { - - return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, - grantedPermissions, state, UserHandle.getCallingUserId()); - } - - /** * Returns true if the package is installed and not hidden, or if the caller * explicitly wanted all uninstalled and hidden packages as well. * @param appInfo The applicationInfo of the app being checked. @@ -658,8 +643,45 @@ public class PackageParser { return checkUseInstalledOrHidden(0, state, null); } + /** + * Generate and return the {@link PackageInfo} for a parsed package. + * + * @param p the parsed package. + * @param flags indicating which optional information is included. + */ + @UnsupportedAppUsage + public static PackageInfo generatePackageInfo(PackageParser.Package p, + int[] gids, int flags, long firstInstallTime, long lastUpdateTime, + Set<String> grantedPermissions, PackageUserState state) { + + return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, + grantedPermissions, state, UserHandle.getCallingUserId()); + } + @UnsupportedAppUsage public static PackageInfo generatePackageInfo(PackageParser.Package p, + int[] gids, int flags, long firstInstallTime, long lastUpdateTime, + Set<String> grantedPermissions, PackageUserState state, int userId) { + + return generatePackageInfo(p, null, gids, flags, firstInstallTime, lastUpdateTime, + grantedPermissions, state, userId); + } + + /** + * PackageInfo generator specifically for apex files. + * + * @param pkg Package to generate info from. Should be derived from an apex. + * @param apexInfo Apex info relating to the package. + * @return PackageInfo + * @throws PackageParserException + */ + public static PackageInfo generatePackageInfo( + PackageParser.Package pkg, ApexInfo apexInfo, int flags) { + return generatePackageInfo(pkg, apexInfo, EmptyArray.INT, flags, 0, 0, + Collections.emptySet(), new PackageUserState(), UserHandle.getCallingUserId()); + } + + private static PackageInfo generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo, int gids[], int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId) { if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) { @@ -806,8 +828,27 @@ public class PackageParser { } } } + + if (apexInfo != null) { + File apexFile = new File(apexInfo.modulePath); + + pi.applicationInfo.sourceDir = apexFile.getPath(); + pi.applicationInfo.publicSourceDir = apexFile.getPath(); + if (apexInfo.isFactory) { + pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; + } else { + pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; + } + if (apexInfo.isActive) { + pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; + } else { + pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; + } + pi.isApex = true; + } + // deprecated method of getting signing certificates - if ((flags&PackageManager.GET_SIGNATURES) != 0) { + if ((flags & PackageManager.GET_SIGNATURES) != 0) { if (p.mSigningDetails.hasPastSigningCertificates()) { // Package has included signing certificate rotation information. Return the oldest // cert so that programmatic checks keep working even if unaware of key rotation. @@ -8379,61 +8420,4 @@ public class PackageParser { } } - // TODO(b/129261524): Clean up API - /** - * PackageInfo parser specifically for apex files. - * NOTE: It will collect certificates - * - * @param apexInfo - * @return PackageInfo - * @throws PackageParserException - */ - public static PackageInfo generatePackageInfoFromApex(ApexInfo apexInfo, int flags) - throws PackageParserException { - PackageParser pp = new PackageParser(); - File apexFile = new File(apexInfo.modulePath); - final Package p = pp.parsePackage(apexFile, flags, false); - PackageUserState state = new PackageUserState(); - PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0, - Collections.emptySet(), state); - pi.applicationInfo.sourceDir = apexFile.getPath(); - pi.applicationInfo.publicSourceDir = apexFile.getPath(); - if (apexInfo.isFactory) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; - } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; - } - if (apexInfo.isActive) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; - } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; - } - pi.isApex = true; - - // Collect certificates - if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { - collectCertificates(p, apexFile, false); - // Keep legacy mechanism for handling signatures. While this is deprecated, it's - // still part of the public API and needs to be maintained - if (p.mSigningDetails.hasPastSigningCertificates()) { - // Package has included signing certificate rotation information. Return - // the oldest cert so that programmatic checks keep working even if unaware - // of key rotation. - pi.signatures = new Signature[1]; - pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0]; - } else if (p.mSigningDetails.hasSignatures()) { - // otherwise keep old behavior - int numberOfSigs = p.mSigningDetails.signatures.length; - pi.signatures = new Signature[numberOfSigs]; - System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs); - } - if (p.mSigningDetails != SigningDetails.UNKNOWN) { - // only return a valid SigningInfo if there is signing information to report - pi.signingInfo = new SigningInfo(p.mSigningDetails); - } else { - pi.signingInfo = null; - } - } - return pi; - } } diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index dd5c6a53cc20..c77c53f387e2 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -237,6 +237,17 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @TestApi public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000; + /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the <code>telephony</code> value of + * {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + @TestApi + public static final int PROTECTION_FLAG_TELEPHONY = 0x400000; + /** @hide */ @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { PROTECTION_FLAG_PRIVILEGED, @@ -258,6 +269,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_CONFIGURATOR, PROTECTION_FLAG_INCIDENT_REPORT_APPROVER, PROTECTION_FLAG_APP_PREDICTOR, + PROTECTION_FLAG_TELEPHONY, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionFlags {} @@ -501,6 +513,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) { protLevel += "|appPredictor"; } + if ((level & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0) { + protLevel += "|telephony"; + } return protLevel; } diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 1abfe7000221..46044242aef0 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -799,6 +799,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration * {@link ActivityInfo#CONFIG_ASSETS_PATHS}. * @hide */ + @UnsupportedAppUsage @TestApi public int assetsSeq; diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java index 3af395a4fc19..848790f46734 100644 --- a/core/java/android/content/res/ConfigurationBoundResourceCache.java +++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java @@ -26,6 +26,11 @@ import android.content.pm.ActivityInfo.Config; * @hide For internal use only. */ public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> { + + @UnsupportedAppUsage + public ConfigurationBoundResourceCache() { + } + /** * If the resource is cached, creates and returns a new instance of it. * diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java index d4f0ca5f8ebf..90604b8d536a 100644 --- a/core/java/android/content/res/DrawableCache.java +++ b/core/java/android/content/res/DrawableCache.java @@ -23,6 +23,11 @@ import android.graphics.drawable.Drawable; * Class which can be used to cache Drawable resources against a theme. */ class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> { + + @UnsupportedAppUsage + DrawableCache() { + } + /** * If the resource is cached, creates and returns a new instance of it. * diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl index 22dc9fed59c4..623556695341 100644 --- a/core/java/android/database/IContentObserver.aidl +++ b/core/java/android/database/IContentObserver.aidl @@ -29,5 +29,6 @@ interface IContentObserver * observed. selfUpdate is true if the update was caused by a call to * commit on the cursor that is being observed. */ + @UnsupportedAppUsage oneway void onChange(boolean selfUpdate, in Uri uri, int userId); } diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java index a231a920a29b..3d0ac611b2df 100644 --- a/core/java/android/database/sqlite/SQLiteDebug.java +++ b/core/java/android/database/sqlite/SQLiteDebug.java @@ -23,6 +23,8 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Printer; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.util.ArrayList; /** @@ -116,9 +118,15 @@ public final class SQLiteDebug { * @see #nativeGetPagerStats(PagerStats) */ public static class PagerStats { + + @UnsupportedAppUsage + public PagerStats() { + } + /** the current amount of memory checked out by sqlite using sqlite3_malloc(). * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html */ + @UnsupportedAppUsage public int memoryUsed; /** the number of bytes of page cache allocation which could not be sattisfied by the @@ -128,16 +136,19 @@ public final class SQLiteDebug { * that overflowed because no space was left in the page cache. * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html */ + @UnsupportedAppUsage public int pageCacheOverflow; /** records the largest memory allocation request handed to sqlite3. * documented at http://www.sqlite.org/c3ref/c_status_malloc_size.html */ + @UnsupportedAppUsage public int largestMemAlloc; /** a list of {@link DbStats} - one for each main database opened by the applications * running on the android device */ + @UnsupportedAppUsage public ArrayList<DbStats> dbStats; } @@ -146,16 +157,20 @@ public final class SQLiteDebug { */ public static class DbStats { /** name of the database */ + @UnsupportedAppUsage public String dbName; /** the page size for the database */ + @UnsupportedAppUsage public long pageSize; /** the database size */ + @UnsupportedAppUsage public long dbSize; /** * Number of lookaside slots: http://www.sqlite.org/c3ref/c_dbstatus_lookaside_used.html */ + @UnsupportedAppUsage public int lookaside; /** statement cache stats: hits/misses/cachesize */ @@ -175,6 +190,7 @@ public final class SQLiteDebug { * return all pager and database stats for the current process. * @return {@link PagerStats} */ + @UnsupportedAppUsage public static PagerStats getDatabaseInfo() { PagerStats stats = new PagerStats(); nativeGetPagerStats(stats); diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index cfa3934b0cae..75af41cb2b54 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1763,6 +1763,10 @@ public class ConnectivityManager { /** @hide */ public static class PacketKeepaliveCallback { + @UnsupportedAppUsage + public PacketKeepaliveCallback() { + } + /** The requested keepalive was successfully started. */ @UnsupportedAppUsage public void onStarted() {} diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 61648dc7f1d8..5f662f914919 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -52,6 +52,7 @@ interface IConnectivityManager @UnsupportedAppUsage NetworkInfo getActiveNetworkInfo(); NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked); + @UnsupportedAppUsage(maxTargetSdk = 28) NetworkInfo getNetworkInfo(int networkType); NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked); @UnsupportedAppUsage @@ -112,6 +113,7 @@ interface IConnectivityManager int setUsbTethering(boolean enable, String callerPkg); + @UnsupportedAppUsage(maxTargetSdk = 28) void reportInetCondition(int networkType, int percentage); void reportNetworkConnectivity(in Network network, boolean hasConnectivity); diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java index c97b37b55c78..c9a999cfdf17 100644 --- a/core/java/android/net/InterfaceConfiguration.java +++ b/core/java/android/net/InterfaceConfiguration.java @@ -40,6 +40,10 @@ public class InterfaceConfiguration implements Parcelable { private static final String[] EMPTY_STRING_ARRAY = new String[0]; + @UnsupportedAppUsage + public InterfaceConfiguration() { + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 3ec0aeac472b..0706e755d133 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -111,6 +111,8 @@ public final class LinkProperties implements Parcelable { /** * @hide */ + @UnsupportedAppUsage(implicitMember = + "values()[Landroid/net/LinkProperties$ProvisioningChange;") public enum ProvisioningChange { @UnsupportedAppUsage STILL_NOT_PROVISIONED, diff --git a/core/java/android/net/MobileLinkQualityInfo.java b/core/java/android/net/MobileLinkQualityInfo.java index 06c739d6cf95..a10a14d750d8 100644 --- a/core/java/android/net/MobileLinkQualityInfo.java +++ b/core/java/android/net/MobileLinkQualityInfo.java @@ -40,6 +40,10 @@ public class MobileLinkQualityInfo extends LinkQualityInfo { private int mLteRssnr = UNKNOWN_INT; private int mLteCqi = UNKNOWN_INT; + @UnsupportedAppUsage + public MobileLinkQualityInfo() { + } + /** * Implement the Parcelable interface. * @hide diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 43ea5891d7f7..ff4bf2d3474c 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; @@ -418,7 +419,16 @@ public abstract class NetworkAgent extends Handler { if (score < 0) { throw new IllegalArgumentException("Score must be >= 0"); } - queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score, 0); + final NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, score); + updateScore(ns); + } + + /** + * Called by the bearer code when it has a new NetworkScore for this network. + */ + public void updateScore(@NonNull NetworkScore ns) { + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); } /** diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index e3259ffa9d47..88877e254787 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -478,6 +478,7 @@ public final class NetworkCapabilities implements Parcelable { * @return an array of capability values for this instance. * @hide */ + @UnsupportedAppUsage @TestApi public @NetCapability int[] getCapabilities() { return BitUtils.unpackBits(mNetworkCapabilities); diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java new file mode 100644 index 000000000000..1ab63352401c --- /dev/null +++ b/core/java/android/net/NetworkScore.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Object representing the quality of a network as perceived by the user. + * + * A NetworkScore object represents the characteristics of a network that affects how good the + * network is considered for a particular use. + * @hide + */ +public final class NetworkScore implements Parcelable { + + // The key of bundle which is used to get the legacy network score of NetworkAgentInfo. + // TODO: Remove this when the transition to NetworkScore is over. + public static final String LEGACY_SCORE = "LEGACY_SCORE"; + @NonNull + private final Bundle mExtensions; + + public NetworkScore() { + mExtensions = new Bundle(); + } + + public NetworkScore(@NonNull NetworkScore source) { + mExtensions = new Bundle(source.mExtensions); + } + + /** + * Put the value of parcelable inside the bundle by key. + */ + public void putExtension(@Nullable String key, @Nullable Parcelable value) { + mExtensions.putParcelable(key, value); + } + + /** + * Put the value of int inside the bundle by key. + */ + public void putIntExtension(@Nullable String key, int value) { + mExtensions.putInt(key, value); + } + + /** + * Get the value of non primitive type by key. + */ + public <T extends Parcelable> T getExtension(@Nullable String key) { + return mExtensions.getParcelable(key); + } + + /** + * Get the value of int by key. + */ + public int getIntExtension(@Nullable String key) { + return mExtensions.getInt(key); + } + + /** + * Remove the entry by given key. + */ + public void removeExtension(@Nullable String key) { + mExtensions.remove(key); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + synchronized (this) { + dest.writeBundle(mExtensions); + } + } + + public static final @NonNull Creator<NetworkScore> CREATOR = new Creator<NetworkScore>() { + @Override + public NetworkScore createFromParcel(@NonNull Parcel in) { + return new NetworkScore(in); + } + + @Override + public NetworkScore[] newArray(int size) { + return new NetworkScore[size]; + } + }; + + private NetworkScore(@NonNull Parcel in) { + mExtensions = in.readBundle(); + } + + // TODO: Modify this method once new fields are added into this class. + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof NetworkScore)) { + return false; + } + final NetworkScore other = (NetworkScore) obj; + return bundlesEqual(mExtensions, other.mExtensions); + } + + @Override + public int hashCode() { + int result = 29; + for (String key : mExtensions.keySet()) { + final Object value = mExtensions.get(key); + // The key may be null, so call Objects.hash() is safer. + result += 31 * value.hashCode() + 37 * Objects.hash(key); + } + return result; + } + + // mExtensions won't be null since the constructor will create it. + private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) { + if (bundle1 == bundle2) { + return true; + } + + // This is unlikely but it's fine to add this clause here. + if (null == bundle1 || null == bundle2) { + return false; + } + + if (bundle1.size() != bundle2.size()) { + return false; + } + + for (String key : bundle1.keySet()) { + final Object value1 = bundle1.get(key); + final Object value2 = bundle2.get(key); + if (!Objects.equals(value1, value2)) { + return false; + } + } + return true; + } +} diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java index 95d66bb87064..39cb323d0662 100644 --- a/core/java/android/net/SSLCertificateSocketFactory.java +++ b/core/java/android/net/SSLCertificateSocketFactory.java @@ -304,7 +304,8 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory { } /** - * Sets the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next + * Sets the + * <a class="external" href="https://tools.ietf.org/id/draft-agl-tls-nextprotoneg-03.html">Next * Protocol Negotiation (NPN)</a> protocols that this peer is interested in. * * <p>For servers this is the sequence of protocols to advertise as diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java index a55d9d00414f..f9c2defc0377 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -78,6 +78,10 @@ public class SntpClient { } } + @UnsupportedAppUsage + public SntpClient() { + } + /** * Sends an SNTP request to the given host and processes the response. * diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 5bc9953e0d05..990c1142284c 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -25,6 +25,8 @@ import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + import java.net.InetAddress; import java.util.ArrayList; import java.util.List; @@ -152,6 +154,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) { + Preconditions.checkNotNull(dnsServers); mDnsServers = dnsServers; return this; } @@ -175,8 +178,10 @@ public final class StaticIpConfiguration implements Parcelable { final StaticIpConfiguration config = new StaticIpConfiguration(); config.ipAddress = mIpAddress; config.gateway = mGateway; - for (InetAddress server : mDnsServers) { - config.dnsServers.add(server); + if (mDnsServers != null) { + for (InetAddress server : mDnsServers) { + config.dnsServers.add(server); + } } config.domains = mDomains; return config; diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java index 4e88149b8095..aa0f6220036c 100644 --- a/core/java/android/net/util/MultinetworkPolicyTracker.java +++ b/core/java/android/net/util/MultinetworkPolicyTracker.java @@ -94,7 +94,8 @@ public class MultinetworkPolicyTracker { } }; - TelephonyManager.from(ctx).listen(new PhoneStateListener(handler.getLooper()) { + ctx.getSystemService(TelephonyManager.class).listen( + new PhoneStateListener(handler.getLooper()) { @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveSubId = subId; diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java index 489a2922f70e..e9ea99f84f90 100644 --- a/core/java/android/net/util/SocketUtils.java +++ b/core/java/android/net/util/SocketUtils.java @@ -77,7 +77,9 @@ public final class SocketUtils { /** * Make a socket address that packet socket can send packets to. + * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. */ + @Deprecated @NonNull public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { return new PacketSocketAddress( @@ -87,6 +89,18 @@ public final class SocketUtils { } /** + * Make a socket address that packet socket can send packets to. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, + @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) */ public static void closeSocket(@Nullable FileDescriptor fd) throws IOException { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index d259f386ea77..b37e176ddb6e 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -38,9 +38,11 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** - * <p>AsyncTask enables proper and easy use of the UI thread. This class allows you - * to perform background operations and publish results on the UI thread without - * having to manipulate threads and/or handlers.</p> + * <p>AsyncTask was intended to enable proper and easy use of the UI thread. However, the most + * common use case was for integrating into UI, and that would cause Context leaks, missed + * callbacks, or crashes on configuration changes. It also has inconsistent behavior on different + * versions of the platform, swallows exceptions from {@code doInBackground}, and does not provide + * much utility over using {@link Executor}s directly.</p> * * <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} * and does not constitute a generic threading framework. AsyncTasks should ideally be @@ -188,7 +190,12 @@ import java.util.concurrent.atomic.AtomicInteger; * <p>If you truly want parallel execution, you can invoke * {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with * {@link #THREAD_POOL_EXECUTOR}.</p> + * + * @deprecated Use the standard <code>java.util.concurrent</code> or + * <a href="https://developer.android.com/topic/libraries/architecture/coroutines"> + * Kotlin concurrency utilities</a> instead. */ +@Deprecated public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; @@ -240,7 +247,13 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * An {@link Executor} that can be used to execute tasks in parallel. + * + * @deprecated Using a single thread pool for a general purpose results in suboptimal behavior + * for different tasks. Small, CPU-bound tasks benefit from a bounded pool and queueing, and + * long-running blocking tasks, such as network operations, benefit from many threads. Use or + * create an {@link Executor} configured for your use case. */ + @Deprecated public static final Executor THREAD_POOL_EXECUTOR; static { @@ -254,7 +267,10 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * An {@link Executor} that executes tasks one at a time in serial * order. This serialization is global to a particular process. + * + * @deprecated Globally serializing tasks results in excessive queuing for unrelated operations. */ + @Deprecated public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static final int MESSAGE_POST_RESULT = 0x1; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 00d522bae27f..59e9972abde8 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -66,6 +66,10 @@ import java.util.Map; public abstract class BatteryStats implements Parcelable { private static final String TAG = "BatteryStats"; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public BatteryStats() { + } + private static final boolean LOCAL_LOGV = false; /** Fetching RPM stats is too slow to do each time screen changes, so disable it. */ protected static final boolean SCREEN_OFF_RPM_STATS_ENABLED = false; @@ -404,6 +408,10 @@ public abstract class BatteryStats implements Parcelable { */ public static abstract class Counter { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Counter() { + } + /** * Returns the count associated with this Counter for the * selected type of statistics. @@ -513,6 +521,10 @@ public abstract class BatteryStats implements Parcelable { */ public static abstract class Timer { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Timer() { + } + /** * Returns the count associated with this Timer for the * selected type of statistics. @@ -628,6 +640,10 @@ public abstract class BatteryStats implements Parcelable { */ public static abstract class Uid { + @UnsupportedAppUsage + public Uid() { + } + /** * Returns a mapping containing wakelock statistics. * @@ -668,6 +684,11 @@ public abstract class BatteryStats implements Parcelable { * The statistics associated with a particular wake lock. */ public static abstract class Wakelock { + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Wakelock(){ + } + @UnsupportedAppUsage public abstract Timer getWakeTime(int type); } @@ -945,6 +966,11 @@ public abstract class BatteryStats implements Parcelable { public abstract void getDeferredJobsLineLocked(StringBuilder sb, int which); public static abstract class Sensor { + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Sensor() { + } + /* * FIXME: it's not correct to use this magic value because it * could clash with a sensor handle (which are defined by @@ -975,7 +1001,16 @@ public abstract class BatteryStats implements Parcelable { */ public static abstract class Proc { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Proc() { + } + public static class ExcessivePower { + + @UnsupportedAppUsage + public ExcessivePower() { + } + public static final int TYPE_WAKE = 1; public static final int TYPE_CPU = 2; @@ -1050,6 +1085,10 @@ public abstract class BatteryStats implements Parcelable { */ public static abstract class Pkg { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public Pkg() { + } + /** * Returns information about all wakeup alarms that have been triggered for this * package. The mapping keys are tag names for the alarms, the counter contains @@ -1552,6 +1591,7 @@ public abstract class BatteryStats implements Parcelable { } public final static class HistoryItem implements Parcelable { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public HistoryItem next; // The time of this event in milliseconds, as per SystemClock.elapsedRealtime(). @@ -1874,6 +1914,7 @@ public abstract class BatteryStats implements Parcelable { numReadInts += (src.dataPosition()-start)/4; } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void clear() { time = 0; cmd = CMD_NULL; @@ -1894,12 +1935,14 @@ public abstract class BatteryStats implements Parcelable { eventTag = null; } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void setTo(HistoryItem o) { time = o.time; cmd = o.cmd; setToCommon(o); } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void setTo(long time, byte cmd, HistoryItem o) { this.time = time; this.cmd = cmd; @@ -1955,6 +1998,7 @@ public abstract class BatteryStats implements Parcelable { && currentTime == o.currentTime; } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public boolean same(HistoryItem o) { if (!sameNonEvent(o) || eventCode != o.eventCode) { return false; @@ -2337,6 +2381,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which); /** @@ -2694,6 +2739,7 @@ public abstract class BatteryStats implements Parcelable { public static final int NETWORK_WIFI_BG_TX_DATA = 9; public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_BG_TX_DATA + 1; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public abstract long getNetworkActivityBytes(int type, int which); public abstract long getNetworkActivityPackets(int type, int which); diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index 97c0a13e7a2b..c35b05f10498 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -241,31 +241,36 @@ public final class BinderProxy implements IBinder { } 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(); - if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) { - key = "<proxy to dead node>"; - } - } 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); + final ArrayList<WeakReference<BinderProxy>> proxiesToQuery = + new ArrayList<WeakReference<BinderProxy>>(); + synchronized (sProxyMap) { + for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) { + if (a != null) { + proxiesToQuery.addAll(a); + } + } + } + for (WeakReference<BinderProxy> weakRef : proxiesToQuery) { + BinderProxy bp = weakRef.get(); + String key; + if (bp == null) { + key = "<cleared weak-ref>"; + } else { + try { + key = bp.getInterfaceDescriptor(); + if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) { + key = "<proxy to dead node>"; } + } 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()]); @@ -354,9 +359,7 @@ public final class BinderProxy implements IBinder { * @hide */ public static InterfaceCount[] getSortedInterfaceCounts(int num) { - synchronized (sProxyMap) { - return sProxyMap.getSortedInterfaceCounts(num); - } + return sProxyMap.getSortedInterfaceCounts(num); } /** @@ -376,10 +379,8 @@ public final class BinderProxy implements IBinder { */ public static void dumpProxyDebugInfo() { if (Build.IS_DEBUGGABLE) { - synchronized (sProxyMap) { - sProxyMap.dumpProxyInterfaceCounts(); - sProxyMap.dumpPerUidProxyCounts(); - } + sProxyMap.dumpProxyInterfaceCounts(); + sProxyMap.dumpPerUidProxyCounts(); } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index f5426cd9203d..f21956bfe607 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -108,6 +108,7 @@ public class Build { * Whether this build was for an emulator device. * @hide */ + @UnsupportedAppUsage @TestApi public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1"); diff --git a/core/java/android/os/CancellationSignal.java b/core/java/android/os/CancellationSignal.java index e8053d5d275d..99fb9982e706 100644 --- a/core/java/android/os/CancellationSignal.java +++ b/core/java/android/os/CancellationSignal.java @@ -18,13 +18,19 @@ package android.os; import android.os.ICancellationSignal; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * Provides the ability to cancel an operation in progress. */ public final class CancellationSignal { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private boolean mIsCanceled; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private OnCancelListener mOnCancelListener; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private ICancellationSignal mRemote; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private boolean mCancelInProgress; /** @@ -152,6 +158,7 @@ public final class CancellationSignal { } } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private void waitForCancelFinishedLocked() { while (mCancelInProgress) { try { diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 154e8cd5a2d5..4ed7b17d1549 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -1690,6 +1690,8 @@ public final class Debug * such runtime statistic exists. * * <p>The following table lists the runtime statistics that the runtime supports. + * All statistics are approximate. Individual allocations may not be immediately reflected + * in the results. * Note runtime statistics may be added or removed in a future API level.</p> * * <table> diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 3462d1f56b67..c237222d9134 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -169,6 +169,7 @@ public class Environment { } /** {@hide} */ + @UnsupportedAppUsage @TestApi public static @NonNull File getStorageDirectory() { return DIR_ANDROID_STORAGE; diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index 9af9edae9a3f..a99bdabee137 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -28,15 +28,14 @@ import java.lang.reflect.Modifier; * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}. Each Handler * instance is associated with a single thread and that thread's message - * queue. When you create a new Handler, it is bound to the thread / - * message queue of the thread that is creating it -- from that point on, - * it will deliver messages and runnables to that message queue and execute - * them as they come out of the message queue. - * + * queue. When you create a new Handler it is bound to a {@link Looper}. + * It will deliver messages and runnables to that Looper's message + * queue and execute them on that Looper's thread. + * * <p>There are two main uses for a Handler: (1) to schedule messages and * runnables to be executed at some point in the future; and (2) to enqueue * an action to be performed on a different thread than your own. - * + * * <p>Scheduling messages is accomplished with the * {@link #post}, {@link #postAtTime(Runnable, long)}, * {@link #postDelayed}, {@link #sendEmptyMessage}, @@ -114,7 +113,18 @@ public class Handler { * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. + * + * @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs + * where operations are silently lost (if the Handler is not expecting new tasks and quits), + * crashes (if a handler is sometimes created on a thread without a Looper active), or race + * conditions, where the thread a handler is associated with is not what the author + * anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper + * explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or + * similar. If the implicit thread local behavior is required for compatibility, use + * {@code new Handler(Looper.myLooper())} to make it clear to readers. + * */ + @Deprecated public Handler() { this(null, false); } @@ -128,7 +138,17 @@ public class Handler { * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. - */ + * + * @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs + * where operations are silently lost (if the Handler is not expecting new tasks and quits), + * crashes (if a handler is sometimes created on a thread without a Looper active), or race + * conditions, where the thread a handler is associated with is not what the author + * anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper + * explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or + * similar. If the implicit thread local behavior is required for compatibility, use + * {@code new Handler(Looper.myLooper(), callback)} to make it clear to readers. + */ + @Deprecated public Handler(@Nullable Callback callback) { this(callback, false); } diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index aa255bf660d5..8a7a594f0b80 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -31,11 +31,13 @@ interface IDeviceIdleController { String[] getSystemPowerWhitelistExceptIdle(); String[] getSystemPowerWhitelist(); String[] getUserPowerWhitelist(); + @UnsupportedAppUsage String[] getFullPowerWhitelistExceptIdle(); String[] getFullPowerWhitelist(); int[] getAppIdWhitelistExceptIdle(); int[] getAppIdWhitelist(); int[] getAppIdUserWhitelist(); + @UnsupportedAppUsage int[] getAppIdTempWhitelist(); boolean isPowerSaveWhitelistExceptIdleApp(String name); boolean isPowerSaveWhitelistApp(String name); diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 9b8a40a6cab0..0cce19222d27 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -184,6 +184,7 @@ interface INetworkManagementService /** * Returns a list of currently tethered interfaces */ + @UnsupportedAppUsage String[] listTetheredInterfaces(); /** diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index e1d605e1c99d..185693e8e6e0 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -47,6 +47,7 @@ interface IPowerManager void wakeUp(long time, int reason, String details, String opPackageName); @UnsupportedAppUsage void goToSleep(long time, int reason, int flags); + @UnsupportedAppUsage(maxTargetSdk = 28) void nap(long time); @UnsupportedAppUsage boolean isInteractive(); diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java index c5f169802230..f98fdc393de3 100644 --- a/core/java/android/os/MessageQueue.java +++ b/core/java/android/os/MessageQueue.java @@ -468,6 +468,7 @@ public final class MessageQueue { * * @hide */ + @UnsupportedAppUsage @TestApi public int postSyncBarrier() { return postSyncBarrier(SystemClock.uptimeMillis()); @@ -512,6 +513,7 @@ public final class MessageQueue { * * @hide */ + @UnsupportedAppUsage @TestApi public void removeSyncBarrier(int token) { // Remove a sync barrier token from the queue. diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index dbe3c93738b8..041f31d67a3e 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -364,6 +364,11 @@ public final class Parcel { * @hide */ public static class ReadWriteHelper { + + @UnsupportedAppUsage + public ReadWriteHelper() { + } + public static final ReadWriteHelper DEFAULT = new ReadWriteHelper(); /** @@ -3148,6 +3153,7 @@ public final class Parcel { // Cache of previously looked up CREATOR.createFromParcel() methods for // particular classes. Keys are the names of the classes, values are // Method objects. + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator<?>>> mCreators = new HashMap<>(); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 2fff595d7150..ab4d424ac053 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -824,6 +824,7 @@ public final class PowerManager { final Context mContext; @UnsupportedAppUsage final IPowerManager mService; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) final Handler mHandler; IThermalService mThermalService; diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index f85297627d76..450bfaef50d4 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -229,6 +229,7 @@ public class Process { * First uid used for fully isolated sandboxed processes (with no permissions of their own) * @hide */ + @UnsupportedAppUsage @TestApi public static final int FIRST_ISOLATED_UID = 99000; @@ -236,6 +237,7 @@ public class Process { * Last uid used for fully isolated sandboxed processes (with no permissions of their own) * @hide */ + @UnsupportedAppUsage @TestApi public static final int LAST_ISOLATED_UID = 99999; @@ -1003,6 +1005,7 @@ public class Process { * your own log, or the Android Illuminati will find you some night and * beat you up. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static final native void sendSignalQuiet(int pid, int signal); /** @hide */ diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 48fc2a6bf449..e3f6e120d9c6 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -888,7 +888,7 @@ public class RecoverySystem { } List<SubscriptionInfo> invisibleSubs = new ArrayList<>(); for (SubscriptionInfo sub : availableSubs) { - if (sub.isEmbedded() && !subscriptionManager.isSubscriptionVisible(sub)) { + if (sub.isEmbedded() && sub.getGroupUuid() != null && sub.isOpportunistic()) { invisibleSubs.add(sub); } } diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java index 8fb123aa3da4..572b975fbafd 100644 --- a/core/java/android/os/Registrant.java +++ b/core/java/android/os/Registrant.java @@ -114,6 +114,7 @@ public class Registrant } } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public Handler getHandler() { diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java index 6e562ffc88ea..9c017dfff967 100644 --- a/core/java/android/os/RegistrantList.java +++ b/core/java/android/os/RegistrantList.java @@ -17,7 +17,6 @@ package android.os; import android.annotation.UnsupportedAppUsage; -import android.os.Handler; import java.util.ArrayList; @@ -27,6 +26,10 @@ public class RegistrantList ArrayList registrants = new ArrayList(); // of Registrant @UnsupportedAppUsage + public RegistrantList() { + } + + @UnsupportedAppUsage public synchronized void add(Handler h, int what, Object obj) { @@ -70,6 +73,7 @@ public class RegistrantList return registrants.size(); } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public synchronized Object get(int index) { diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java index 047ba1d20056..da58d0fac160 100644 --- a/core/java/android/os/RemoteCallback.java +++ b/core/java/android/os/RemoteCallback.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * @hide */ @@ -33,6 +35,7 @@ public final class RemoteCallback implements Parcelable { } private final OnResultListener mListener; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private final Handler mHandler; private final IRemoteCallback mCallback; diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index 9a9b0306063b..bf9225a2780a 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -102,6 +102,10 @@ public final class ServiceManager { }); @UnsupportedAppUsage + public ServiceManager() { + } + + @UnsupportedAppUsage private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index c707ba839336..0bf634e799cd 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1892,6 +1892,7 @@ public final class StrictMode { } /** @hide */ + @UnsupportedAppUsage @TestApi public static void conditionallyCheckInstanceCounts() { VmPolicy policy = getVmPolicy(); @@ -2751,6 +2752,7 @@ public final class StrictMode { } /** Create an instance of ViolationInfo initialized from a Parcel. */ + @UnsupportedAppUsage public ViolationInfo(Parcel in) { this(in, false); } diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index a6e5972faa55..8b0ffe155fc3 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -95,12 +95,17 @@ public class SystemProperties { @UnsupportedAppUsage private static native String native_get(String key); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native String native_get(String key, String def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native int native_get_int(String key, int def); @UnsupportedAppUsage private static native long native_get_long(String key, long def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native boolean native_get_boolean(String key, boolean def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_set(String key, String def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_add_change_callback(); private static native void native_report_sysprop_change(); diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index d70ba9921bfd..45ee4efa27f7 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -171,6 +171,7 @@ public final class UserHandle implements Parcelable { * "it's system", because of isolated UIDs. Use {@link #isCore} for that. * @hide */ + @UnsupportedAppUsage @TestApi public static boolean isApp(int uid) { if (uid > 0) { @@ -354,6 +355,7 @@ public final class UserHandle implements Parcelable { * components -- user, app, isolated, etc. * @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static void formatUid(PrintWriter pw, int uid) { if (uid < Process.FIRST_APPLICATION_UID) { pw.print(uid); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 9c9829fb08e2..c15618bdaa78 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1295,8 +1295,11 @@ public class UserManager { mContext.getContentResolver(), Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0; boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM); - boolean inCall = TelephonyManager.getDefault().getCallState() - != TelephonyManager.CALL_STATE_IDLE; + boolean inCall = false; + TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); + if (telephonyManager != null) { + inCall = telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE; + } boolean isUserSwitchDisallowed = hasUserRestriction(DISALLOW_USER_SWITCH); return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall && !isUserSwitchDisallowed; diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 702b41beb071..64d36a951023 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -27,6 +27,8 @@ import android.hardware.vibrator.V1_3.Effect; import android.net.Uri; import android.util.MathUtils; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; @@ -77,6 +79,7 @@ public abstract class VibrationEffect implements Parcelable { * @see #get(int) * @hide */ + @UnsupportedAppUsage @TestApi public static final int EFFECT_THUD = Effect.THUD; @@ -85,6 +88,7 @@ public abstract class VibrationEffect implements Parcelable { * @see #get(int) * @hide */ + @UnsupportedAppUsage @TestApi public static final int EFFECT_POP = Effect.POP; @@ -126,6 +130,7 @@ public abstract class VibrationEffect implements Parcelable { * @see #get(Uri, Context) * @hide */ + @UnsupportedAppUsage @TestApi public static final int[] RINGTONES = { Effect.RINGTONE_1, @@ -493,6 +498,7 @@ public abstract class VibrationEffect implements Parcelable { out.writeInt(mAmplitude); } + @UnsupportedAppUsage public static final @android.annotation.NonNull Parcelable.Creator<OneShot> CREATOR = new Parcelable.Creator<OneShot>() { @Override diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index 634b2baf098a..825fc64df5cc 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java @@ -40,14 +40,17 @@ public class WorkSource implements Parcelable { * The WorkSource object itself is not thread safe, but we need to * hold sTmpWorkSource lock while working with these statics. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) static final WorkSource sTmpWorkSource = new WorkSource(0); /** * For returning newbie work from a modification operation. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) static WorkSource sNewbWork; /** * For returning gone work form a modification operation. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) static WorkSource sGoneWork; /** @@ -89,6 +92,7 @@ public class WorkSource implements Parcelable { } /** @hide */ + @UnsupportedAppUsage @TestApi public WorkSource(int uid) { mNum = 1; @@ -135,12 +139,14 @@ public class WorkSource implements Parcelable { } /** @hide */ + @UnsupportedAppUsage @TestApi public int size() { return mNum; } /** @hide */ + @UnsupportedAppUsage @TestApi public int get(int index) { return mUids[index]; @@ -162,6 +168,7 @@ public class WorkSource implements Parcelable { } /** @hide */ + @UnsupportedAppUsage @TestApi public String getName(int index) { return mNames != null ? mNames[index] : null; @@ -416,6 +423,7 @@ public class WorkSource implements Parcelable { } /** @hide */ + @UnsupportedAppUsage @TestApi public boolean add(int uid) { if (mNum <= 0) { @@ -436,6 +444,7 @@ public class WorkSource implements Parcelable { } /** @hide */ + @UnsupportedAppUsage @TestApi public boolean add(int uid, String name) { if (mNum <= 0) { @@ -620,6 +629,7 @@ public class WorkSource implements Parcelable { return changed; } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private boolean updateLocked(WorkSource other, boolean set, boolean returnNewbs) { if (mNames == null && other.mNames == null) { return updateUidsLocked(other, set, returnNewbs); diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java index de983595efd4..384342c894d5 100644 --- a/core/java/android/os/health/HealthStatsParceler.java +++ b/core/java/android/os/health/HealthStatsParceler.java @@ -19,10 +19,8 @@ package android.os.health; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; -import android.util.ArrayMap; -import java.util.Arrays; -import java.util.Map; +import dalvik.annotation.compat.UnsupportedAppUsage; /** * Class to allow sending the HealthStats through aidl generated glue. @@ -41,6 +39,7 @@ public class HealthStatsParceler implements Parcelable { private HealthStatsWriter mWriter; private HealthStats mHealthStats; + @UnsupportedAppUsage public static final @android.annotation.NonNull Parcelable.Creator<HealthStatsParceler> CREATOR = new Parcelable.Creator<HealthStatsParceler>() { public HealthStatsParceler createFromParcel(Parcel in) { diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java index 0e00d5e9b7bf..4c92c28c1bfa 100644 --- a/core/java/android/os/image/DynamicSystemManager.java +++ b/core/java/android/os/image/DynamicSystemManager.java @@ -101,6 +101,19 @@ public class DynamicSystemManager { } } /** + * Start DynamicSystem installation. + * + * @return true if the call succeeds + */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) + public boolean startInstallation() { + try { + return mService.startInstallation(); + } catch (RemoteException e) { + throw new RuntimeException(e.toString()); + } + } + /** * Start DynamicSystem installation. This call may take an unbounded amount of time. The caller * may use another thread to call the getStartProgress() to get the progress. * @@ -112,9 +125,9 @@ public class DynamicSystemManager { * true. */ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) - public Session startInstallation(String name, long size, boolean readOnly) { + public Session createPartition(String name, long size, boolean readOnly) { try { - if (mService.startInstallation(name, size, readOnly)) { + if (mService.createPartition(name, size, readOnly)) { return new Session(); } else { return null; @@ -123,7 +136,18 @@ public class DynamicSystemManager { throw new RuntimeException(e.toString()); } } - + /** + * Finish a previously started installation. Installations without a cooresponding + * finishInstallation() will be cleaned up during device boot. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) + public boolean finishInstallation() { + try { + return mService.finishInstallation(); + } catch (RemoteException e) { + throw new RuntimeException(e.toString()); + } + } /** * Query the progress of the current installation operation. This can be called while the * installation is in progress. diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl index 75f67854743f..69cbab2c68ad 100644 --- a/core/java/android/os/image/IDynamicSystemService.aidl +++ b/core/java/android/os/image/IDynamicSystemService.aidl @@ -21,15 +21,26 @@ import android.gsi.GsiProgress; interface IDynamicSystemService { /** - * Start DynamicSystem installation. This call may take 60~90 seconds. The caller + * Start DynamicSystem installation. + * @return true if the call succeeds + */ + boolean startInstallation(); + + /** + * Create a DSU partition. This call may take 60~90 seconds. The caller * may use another thread to call the getStartProgress() to get the progress. - * * @param name The DSU partition name * @param size Size of the DSU image in bytes * @param readOnly True if this partition is readOnly * @return true if the call succeeds */ - boolean startInstallation(@utf8InCpp String name, long size, boolean readOnly); + boolean createPartition(@utf8InCpp String name, long size, boolean readOnly); + + /** + * Finish a previously started installation. Installations without + * a cooresponding finishInstallation() will be cleaned up during device boot. + */ + boolean finishInstallation(); /** * Query the progress of the current installation operation. This can be called while diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index 4aa0b08ae358..39d5b4529745 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -24,6 +24,11 @@ import android.annotation.UnsupportedAppUsage; * @hide */ public class StorageEventListener { + + @UnsupportedAppUsage + public StorageEventListener() { + } + /** * Called when the detection state of a USB Mass Storage host has changed. * @param connected true if the USB mass storage is connected. diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java index 6280600823d7..aefe8430f9de 100644 --- a/core/java/android/os/storage/StorageVolume.java +++ b/core/java/android/os/storage/StorageVolume.java @@ -173,6 +173,7 @@ public final class StorageVolume implements Parcelable { * @return the mount path * @hide */ + @UnsupportedAppUsage @TestApi public String getPath() { return mPath.toString(); diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 2f68eb475e7a..f1d90be9aafe 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -1862,6 +1862,7 @@ public final class CalendarContract { * * @hide */ + @UnsupportedAppUsage @TestApi public static final String[] SYNC_WRITABLE_COLUMNS = new String[] { _SYNC_ID, diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 0973a6412384..82a3c4015f70 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -35,6 +35,7 @@ import android.provider.ContactsContract.CommonDataKinds.Callable; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.DataUsageFeedback; +import android.telecom.CallerInfo; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; @@ -42,7 +43,6 @@ import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.Log; -import android.telephony.CallerInfo; import com.android.internal.telephony.PhoneConstants; import java.util.List; @@ -227,7 +227,7 @@ public class CallLog { /** * Indicates the call underwent Assisted Dialing. - * @hide + * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING */ public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index af3a16c987e6..f10e184ccf5a 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -126,6 +126,7 @@ public final class ContactsContract { * Prefix for column names that are not visible to client apps. * @hide */ + @UnsupportedAppUsage @TestApi public static final String HIDDEN_COLUMN_PREFIX = "x_"; @@ -6069,6 +6070,7 @@ public final class ContactsContract { * * @hide */ + @UnsupportedAppUsage @TestApi public static final Uri ENTERPRISE_CONTENT_URI = Uri.withAppendedPath(Data.ENTERPRISE_CONTENT_URI, "phones"); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2263f52dd361..ade0cafb2495 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2048,6 +2048,7 @@ public final class Settings { * This is the only type of reset available to non-system clients. * @hide */ + @UnsupportedAppUsage @TestApi public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; @@ -6454,6 +6455,7 @@ public final class Settings { * shortcut. Must be its flattened {@link ComponentName}. * @hide */ + @UnsupportedAppUsage @TestApi public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service"; @@ -6646,6 +6648,7 @@ public final class Settings { * * @hide */ + @UnsupportedAppUsage @TestApi public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled"; @@ -8493,6 +8496,7 @@ public final class Settings { * * @hide */ + @UnsupportedAppUsage @TestApi public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners"; @@ -8676,6 +8680,7 @@ public final class Settings { * The value is boolean (1 or 0). * @hide */ + @UnsupportedAppUsage @TestApi public static final String NOTIFICATION_BADGING = "notification_badging"; @@ -11130,25 +11135,26 @@ public final class Settings { */ public static final String MODE_RINGER = "mode_ringer"; - /** - * Overlay display devices setting. - * The associated value is a specially formatted string that describes the - * size and density of simulated secondary display devices. - * <p> - * Format: {width}x{height}/{dpi};... - * </p><p> - * Example: - * <ul> - * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li> - * <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first - * at 1080p and the second at 720p.</li> - * <li>If the value is empty, then no overlay display devices are created.</li> - * </ul></p> - * - * @hide - */ - @TestApi - public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices"; + /** + * Overlay display devices setting. + * The associated value is a specially formatted string that describes the + * size and density of simulated secondary display devices. + * <p> + * Format: {width}x{height}/{dpi};... + * </p><p> + * Example: + * <ul> + * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li> + * <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first + * at 1080p and the second at 720p.</li> + * <li>If the value is empty, then no overlay display devices are created.</li> + * </ul></p> + * + * @hide + */ + @UnsupportedAppUsage + @TestApi + public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices"; /** * Threshold values for the duration and level of a discharge cycle, @@ -11800,6 +11806,7 @@ public final class Settings { * @hide * @see com.android.server.power.batterysaver.BatterySaverPolicy */ + @UnsupportedAppUsage @TestApi public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants"; diff --git a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java new file mode 100644 index 000000000000..de90b94d7535 --- /dev/null +++ b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2019 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.carrier; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +import java.util.List; + +/** + * Provides basic structure for platform to connect to the carrier messaging service. + * <p> + * <code> + * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper = + * new CarrierMessagingServiceWrapperImpl(); + * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) { + * // wait for onServiceReady callback + * } else { + * // Unable to bind: handle error. + * } + * </code> + * <p> Upon completion {@link #disposeConnection} should be called to unbind the + * CarrierMessagingService. + * @hide + */ +@SystemApi +public abstract class CarrierMessagingServiceWrapper { + // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete + // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized. + private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection; + + private volatile ICarrierMessagingService mICarrierMessagingService; + + /** + * Binds to the carrier messaging service under package {@code carrierPackageName}. This method + * should be called exactly once. + * + * @param context the context + * @param carrierPackageName the carrier package name + * @return true upon successfully binding to a carrier messaging service, false otherwise + * @hide + */ + @SystemApi + public boolean bindToCarrierMessagingService(@NonNull Context context, + @NonNull String carrierPackageName) { + Preconditions.checkState(mCarrierMessagingServiceConnection == null); + + Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE); + intent.setPackage(carrierPackageName); + mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection(); + return context.bindService(intent, mCarrierMessagingServiceConnection, + Context.BIND_AUTO_CREATE); + } + + /** + * Unbinds the carrier messaging service. This method should be called exactly once. + * + * @param context the context + * @hide + */ + @SystemApi + public void disposeConnection(@NonNull Context context) { + Preconditions.checkNotNull(mCarrierMessagingServiceConnection); + context.unbindService(mCarrierMessagingServiceConnection); + mCarrierMessagingServiceConnection = null; + } + + /** + * Implemented by subclasses to use the carrier messaging service once it is ready. + * @hide + */ + @SystemApi + public abstract void onServiceReady(); + + /** + * Called when connection with service is established. + * + * @param carrierMessagingService the carrier messaing service interface + */ + private void onServiceReady(ICarrierMessagingService carrierMessagingService) { + mICarrierMessagingService = carrierMessagingService; + onServiceReady(); + } + + /** + * Request filtering an incoming SMS message. + * The service will call callback.onFilterComplete with the filtering result. + * + * @param pdu the PDUs of the message + * @param format the format of the PDUs, typically "3gpp" or "3gpp2" + * @param destPort the destination port of a data SMS. It will be -1 for text SMS + * @param subId SMS subscription ID of the SIM + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort, + int subId, @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.filterSms(pdu, format, destPort, subId, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new text SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send + * status. + * + * @param text the text to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress, + int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new data SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send + * status. + * + * @param data the data to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param destPort port number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress, + int destPort, int sendSmsFlag, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort, + sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new multi-part text SMS from the device. + * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete} + * with the send status. + * + * @param parts the parts of the multi-part text SMS to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendMultipartTextSms(@NonNull List<String> parts, int subId, + @NonNull String destAddress, int sendSmsFlag, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress, + sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request sending a new MMS PDU from the device. + * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send + * status. + * + * @param pduUri the content provider URI of the PDU to send + * @param subId SMS subscription ID of the SIM + * @param location the optional URI to send this MMS PDU. If this is {code null}, + * the PDU should be sent to the default MMSC URL. + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.sendMms(pduUri, subId, location, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Request downloading a new MMS. + * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the + * download status. + * + * @param pduUri the content provider URI of the PDU to be downloaded. + * @param subId SMS subscription ID of the SIM + * @param location the URI of the message to be downloaded. + * @param callback the callback to notify upon completion + * @hide + */ + @SystemApi + public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location, + @NonNull final CarrierMessagingCallbackWrapper callback) { + if (mICarrierMessagingService != null) { + try { + mICarrierMessagingService.downloadMms(pduUri, subId, location, + new CarrierMessagingCallbackWrapperInternal(callback)); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + + /** + * A basic {@link ServiceConnection}. + */ + private final class CarrierMessagingServiceConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + onServiceReady(ICarrierMessagingService.Stub.asInterface(service)); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + } + + /** + * Callback wrapper used for response to requests exposed by + * {@link CarrierMessagingServiceWrapper}. + * @hide + */ + @SystemApi + public abstract static class CarrierMessagingCallbackWrapper { + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}. + * @param result a bitmask integer to indicate how the incoming text SMS should be handled + * by the platform. Bits set can be + * {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and + * {@link CarrierMessagingService# + * RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}. + * {@see CarrierMessagingService#onReceiveTextSms}. + * @hide + */ + @SystemApi + public void onFilterComplete(int result) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and + * {@link CarrierMessagingServiceWrapper#sendDataSms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param messageRef message reference of the just-sent message. This field is applicable + * only if result is {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendSmsComplete(int result, int messageRef) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param messageRefs an array of message references, one for each part of the + * multipart SMS. This field is applicable only if result is + * {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}. + * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message + * was sent. sendConfPdu is ignored if the {@code result} is not + * {@link CarrierMessagingService#SEND_STATUS_OK}. + * @hide + */ + @SystemApi + public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) { + + } + + /** + * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}. + * @param result download status, one of {@link CarrierMessagingService#SEND_STATUS_OK}, + * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, + * and {@link CarrierMessagingService#SEND_STATUS_ERROR}. + * @hide + */ + @SystemApi + public void onDownloadMmsComplete(int result) { + + } + } + + private final class CarrierMessagingCallbackWrapperInternal + extends ICarrierMessagingCallback.Stub { + CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper; + + CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) { + mCarrierMessagingCallbackWrapper = callback; + } + + @Override + public void onFilterComplete(int result) throws RemoteException { + mCarrierMessagingCallbackWrapper.onFilterComplete(result); + } + + @Override + public void onSendSmsComplete(int result, int messageRef) throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef); + } + + @Override + public void onSendMultipartSmsComplete(int result, int[] messageRefs) + throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs); + } + + @Override + public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException { + mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu); + } + + @Override + public void onDownloadMmsComplete(int result) throws RemoteException { + mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result); + } + } +} diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java index aeb186b00686..eefc1b70bac9 100644 --- a/core/java/android/service/carrier/CarrierService.java +++ b/core/java/android/service/carrier/CarrierService.java @@ -16,17 +16,15 @@ package android.service.carrier; import android.annotation.CallSuper; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; -import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.ServiceManager; +import android.telephony.TelephonyRegistryManager; import android.util.Log; -import com.android.internal.telephony.ITelephonyRegistry; - /** * A service that exposes carrier-specific functionality to the system. * <p> @@ -55,16 +53,10 @@ public abstract class CarrierService extends Service { public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService"; - private static ITelephonyRegistry sRegistry; - private final ICarrierService.Stub mStubWrapper; public CarrierService() { mStubWrapper = new ICarrierServiceWrapper(); - if (sRegistry == null) { - sRegistry = ITelephonyRegistry.Stub.asInterface( - ServiceManager.getService("telephony.registry")); - } } /** @@ -122,9 +114,12 @@ public abstract class CarrierService extends Service { * @see android.telephony.TelephonyManager#hasCarrierPrivileges */ public final void notifyCarrierNetworkChange(boolean active) { - try { - if (sRegistry != null) sRegistry.notifyCarrierNetworkChange(active); - } catch (RemoteException | NullPointerException ex) {} + TelephonyRegistryManager telephonyRegistryMgr = + (TelephonyRegistryManager) this.getSystemService( + Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryMgr != null) { + telephonyRegistryMgr.notifyCarrierNetworkChange(active); + } } /** diff --git a/core/java/android/service/carrier/ICarrierMessagingService.aidl b/core/java/android/service/carrier/ICarrierMessagingService.aidl index 2d96c3da6487..c4dfb57bb6a0 100644 --- a/core/java/android/service/carrier/ICarrierMessagingService.aidl +++ b/core/java/android/service/carrier/ICarrierMessagingService.aidl @@ -36,6 +36,7 @@ oneway interface ICarrierMessagingService { * @param subId SMS subscription ID of the SIM * @param callback the callback to notify upon completion */ + @UnsupportedAppUsage(maxTargetSdk = 28) void filterSms( in MessagePdu pdu, String format, int destPort, int subId, in ICarrierMessagingCallback callback); diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index d3f2a70029f7..d254ffdb6986 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -29,6 +29,7 @@ interface IDreamManager { void awaken(); @UnsupportedAppUsage void setDreamComponents(in ComponentName[] componentNames); + @UnsupportedAppUsage ComponentName[] getDreamComponents(); ComponentName getDefaultDreamComponent(); void testDream(in ComponentName componentName); diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 12c25806d666..bc6a9e848e2a 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -21,6 +21,7 @@ import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -104,6 +105,26 @@ public abstract class EuiccService extends Service { "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE"; /** + * Intent action sent by the LPA to launch a carrier app Activity for eSIM activation, e.g. a + * carrier login screen. Carrier apps wishing to support this activation method must implement + * an Activity that responds to this intent action. Upon completion, the Activity must return + * one of the following results to the LPA: + * + * <p>{@code Activity.RESULT_CANCELED}: The LPA should treat this as an back button and abort + * the activation flow. + * <p>{@code Activity.RESULT_OK}: The LPA should try to get an activation code from the carrier + * app by binding to the carrier app service implementing + * {@link #ACTION_BIND_CARRIER_PROVISIONING_SERVICE}. + * <p>{@code Activity.RESULT_OK} with + * {@link android.telephony.euicc.EuiccManager#EXTRA_USE_QR_SCANNER} set to true: The LPA should + * start a QR scanner for the user to scan an eSIM profile QR code. + * <p>For other results: The LPA should treat this as an error. + **/ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_START_CARRIER_ACTIVATION = + "android.service.euicc.action.START_CARRIER_ACTIVATION"; + + /** * @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS * The difference is this one is used by system to bring up the LUI. */ @@ -138,6 +159,15 @@ public abstract class EuiccService extends Service { public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED"; + /** + * @see android.telephony.euicc.EuiccManager#ACTION_START_EUICC_ACTIVATION. This is + * a protected intent that can only be sent by the system, and requires the + * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission. + */ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_START_EUICC_ACTIVATION = + "android.service.euicc.action.START_EUICC_ACTIVATION"; + // LUI resolution actions. These are called by the platform to resolve errors in situations that // require user interaction. // TODO(b/33075886): Define extras for any input parameters to these dialogs once they are @@ -516,7 +546,7 @@ public abstract class EuiccService extends Service { * @see android.telephony.euicc.EuiccManager#eraseSubscriptions * * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase - * and use {@link #onEraseSubscriptionsWithOptions(int, int)} instead + * and use {@link #onEraseSubscriptions(int, int)} instead */ @Deprecated public abstract int onEraseSubscriptions(int slotId); @@ -533,7 +563,7 @@ public abstract class EuiccService extends Service { * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}. * @see android.telephony.euicc.EuiccManager#eraseSubscriptionsWithOptions */ - public int onEraseSubscriptionsWithOptions(int slotIndex, @ResetOption int options) { + public int onEraseSubscriptions(int slotIndex, @ResetOption int options) { throw new UnsupportedOperationException( "This method must be overridden to enable the ResetOption parameter"); } @@ -779,8 +809,7 @@ public abstract class EuiccService extends Service { mExecutor.execute(new Runnable() { @Override public void run() { - int result = EuiccService.this.onEraseSubscriptionsWithOptions( - slotIndex, options); + int result = EuiccService.this.onEraseSubscriptions(slotIndex, options); try { callback.onComplete(result); } catch (RemoteException e) { diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 0ce552ae330a..2af827e36696 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -28,11 +28,15 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Looper; +import android.telephony.Annotation.CallState; +import android.telephony.Annotation.RadioPowerState; +import android.telephony.Annotation.SimActivationState; +import android.telephony.Annotation.SrvccState; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.IPhoneStateListener; +import com.android.internal.annotations.VisibleForTesting; import dalvik.system.VMRuntime; @@ -567,7 +571,7 @@ public class PhoneStateListener { * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be * passed as an argument. */ - public void onCallStateChanged(@TelephonyManager.CallState int state, String phoneNumber) { + public void onCallStateChanged(@CallState int state, String phoneNumber) { // default implementation empty } @@ -773,7 +777,7 @@ public class PhoneStateListener { * @hide */ @SystemApi - public void onSrvccStateChanged(@TelephonyManager.SrvccState int srvccState) { + public void onSrvccStateChanged(@SrvccState int srvccState) { } @@ -791,7 +795,7 @@ public class PhoneStateListener { * @hide */ @SystemApi - public void onVoiceActivationStateChanged(@TelephonyManager.SimActivationState int state) { + public void onVoiceActivationStateChanged(@SimActivationState int state) { } /** @@ -807,7 +811,7 @@ public class PhoneStateListener { * @param state is the current SIM data activation state * @hide */ - public void onDataActivationStateChanged(@TelephonyManager.SimActivationState int state) { + public void onDataActivationStateChanged(@SimActivationState int state) { } /** @@ -966,7 +970,7 @@ public class PhoneStateListener { * @hide */ @SystemApi - public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) { + public void onRadioPowerStateChanged(@RadioPowerState int state) { // default implementation empty } @@ -1233,7 +1237,7 @@ public class PhoneStateListener { () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability))); } - public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) { + public void onRadioPowerStateChanged(@RadioPowerState int state) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java new file mode 100644 index 000000000000..456789fb77bc --- /dev/null +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -0,0 +1,717 @@ +/* + * Copyright (C) 2019 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.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.content.Context; +import android.net.LinkProperties; +import android.net.NetworkCapabilities; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.telephony.Annotation; +import android.telephony.Annotation.ApnType; +import android.telephony.Annotation.CallState; +import android.telephony.Annotation.DataActivityType; +import android.telephony.Annotation.DataFailureCause; +import android.telephony.Annotation.DataState; +import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.RadioPowerState; +import android.telephony.Annotation.SimActivationState; +import android.telephony.Annotation.SrvccState; +import android.telephony.CallQuality; +import android.telephony.CellInfo; +import android.telephony.DisconnectCause; +import android.telephony.PhoneCapability; +import android.telephony.PreciseCallState.State; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.TelephonyManager; +import android.telephony.data.ApnSetting; +import android.telephony.ims.ImsReasonInfo; +import android.util.Log; + +import com.android.internal.telephony.IOnSubscriptionsChangedListener; +import com.android.internal.telephony.ITelephonyRegistry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; + +/** + * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update + * or {@link PhoneCapability} changed. This might trigger callback from applications side through + * {@link android.telephony.PhoneStateListener} + * + * TODO: limit API access to only carrier apps with certain permissions or apps running on + * privileged UID. + * + * @hide + */ +@SystemApi +public class TelephonyRegistryManager { + + private static final String TAG = "TelephonyRegistryManager"; + private static ITelephonyRegistry sRegistry; + private final Context mContext; + + /** + * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>(); + /** + * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap + = new HashMap<>(); + + + /** @hide **/ + public TelephonyRegistryManager(@NonNull Context context) { + mContext = context; + if (sRegistry == null) { + sRegistry = ITelephonyRegistry.Stub.asInterface( + ServiceManager.getService("telephony.registry")); + } + } + + /** + * Register for changes to the list of active {@link SubscriptionInfo} records or to the + * individual records themselves. When a change occurs the onSubscriptionsChanged method of + * the listener will be invoked immediately if there has been a notification. The + * onSubscriptionChanged method will also be triggered once initially when calling this + * function. + * + * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener} + * with onSubscriptionsChanged overridden. + * @param executor the executor that will execute callbacks. + */ + public void addOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener, + @NonNull Executor executor) { + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged () { + Log.d(TAG, "onSubscriptionsChangedListener callback received."); + executor.execute(() -> listener.onSubscriptionsChanged()); + } + }; + mSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. This is not + * strictly necessary as the listener will automatically be unregistered if an attempt to + * invoke the listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) { + if (mSubscriptionChangedListenerMap.get(listener) == null) { + return; + } + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mSubscriptionChangedListenerMap.get(listener)); + mSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Register for changes to the list of opportunistic subscription records or to the + * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged + * method of the listener will be invoked immediately if there has been a notification. + * + * @param listener an instance of + * {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with + * onOpportunisticSubscriptionsChanged overridden. + * @param executor an Executor that will execute callbacks. + */ + public void addOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener, + @NonNull Executor executor) { + /** + * The callback methods need to be called on the executor thread where + * this object was created. If the binder did that for us it'd be nice. + */ + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged() { + final long identity = Binder.clearCallingIdentity(); + try { + Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received."); + executor.execute(() -> listener.onOpportunisticSubscriptionsChanged()); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }; + mOpportunisticSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(), + callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} + * that is currently listening opportunistic subscriptions change. This is not strictly + * necessary as the listener will automatically be unregistered if an attempt to invoke the + * listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) { + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mOpportunisticSubscriptionChangedListenerMap.get(listener)); + mOpportunisticSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Informs the system of an intentional upcoming carrier network change by a carrier app. + * This call only used to allow the system to provide alternative UI while telephony is + * performing an action that may result in intentional, temporary network lack of connectivity. + * <p> + * Based on the active parameter passed in, this method will either show or hide the alternative + * UI. There is no timeout associated with showing this UX, so a carrier app must be sure to + * call with active set to false sometime after calling with it set to {@code true}. + * <p> + * Requires Permission: calling app has carrier privileges. + * + * @param active Whether the carrier network change is or shortly will be + * active. Set this value to true to begin showing alternative UI and false to stop. + * @see TelephonyManager#hasCarrierPrivileges + */ + public void notifyCarrierNetworkChange(boolean active) { + try { + sRegistry.notifyCarrierNetworkChange(active); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify call state changed on certain subscription. + * + * @param subId for which call state changed. + * @param slotIndex for which call state changed. Can be derived from subId except when subId is + * invalid. + * @param state latest call state. e.g, offhook, ringing + * @param incomingNumber incoming phone number. + * + * @hide + */ + public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state, + String incomingNumber) { + try { + sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify call state changed on all subscriptions. + * + * @param state latest call state. e.g, offhook, ringing + * @param incomingNumber incoming phone number. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void notifyCallStateChangedForAllSubscriptions(@CallState int state, + @Nullable String incomingNumber) { + try { + sRegistry.notifyCallStateForAllSubs(state, incomingNumber); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify {@link ServiceState} update on certain subscription. + * + * @param subId for which the service state changed. + * @param slotIndex for which the service state changed. Can be derived from subId except + * subId is invalid. + * @param state service state e.g, in service, out of service or roaming status. + * + * @hide + */ + public void notifyServiceStateChanged(int subId, int slotIndex, ServiceState state) { + try { + sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify {@link SignalStrength} update on certain subscription. + * + * @param subId for which the signalstrength changed. + * @param slotIndex for which the signalstrength changed. Can be derived from subId except when + * subId is invalid. + * @param signalStrength e.g, signalstrength level {@see SignalStrength#getLevel()} + * + * @hide + */ + public void notifySignalStrengthChanged(int subId, int slotIndex, + SignalStrength signalStrength) { + try { + sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify changes to the message-waiting indicator on certain subscription. e.g, The status bar + * uses message waiting indicator to determine when to display the voicemail icon. + * + * @param subId for which message waiting indicator changed. + * @param slotIndex for which message waiting indicator changed. Can be derived from subId + * except when subId is invalid. + * @param msgWaitingInd {@code true} indicates there is message-waiting indicator, {@code false} + * otherwise. + * + * @hide + */ + public void notifyMessageWaitingChanged(int subId, int slotIndex, boolean msgWaitingInd) { + try { + sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify changes to the call-forwarding status on certain subscription. + * + * @param subId for which call forwarding status changed. + * @param callForwardInd {@code true} indicates there is call forwarding, {@code false} + * otherwise. + * + * @hide + */ + public void notifyCallForwardingChanged(int subId, boolean callForwardInd) { + try { + sRegistry.notifyCallForwardingChangedForSubscriber(subId, callForwardInd); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify changes to activity state changes on certain subscription. + * + * @param subId for which data activity state changed. + * @param dataActivityType indicates the latest data activity type e.g, {@link + * TelephonyManager#DATA_ACTIVITY_IN} + * + * @hide + */ + public void notifyDataActivityChanged(int subId, @DataActivityType int dataActivityType) { + try { + sRegistry.notifyDataActivityForSubscriber(subId, dataActivityType); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify changes to default (Internet) data connection state on certain subscription. + * + * @param subId for which data connection state changed. + * @param slotIndex for which data connections state changed. Can be derived from subId except + * when subId is invalid. + * @param state latest data connection state, e.g, + * @param isDataConnectivityPossible indicates if data is allowed + * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. + * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. + * @param linkProperties {@link LinkProperties} associated with this data connection. + * @param networkCapabilities {@link NetworkCapabilities} associated with this data connection. + * @param networkType associated with this data connection. + * @param roaming {@code true} indicates in roaming, {@false} otherwise. + * @see TelephonyManager#DATA_DISCONNECTED + * @see TelephonyManager#isDataConnectivityPossible() + * + * @hide + */ + public void notifyDataConnectionForSubscriber(int slotIndex, int subId, @DataState int state, + boolean isDataConnectivityPossible, + @ApnType String apn, String apnType, LinkProperties linkProperties, + NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { + try { + sRegistry.notifyDataConnectionForSubscriber(slotIndex, subId, state, + isDataConnectivityPossible, + apn, apnType, linkProperties, networkCapabilities, networkType, roaming); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify {@link CallQuality} change on certain subscription. + * + * @param subId for which call quality state changed. + * @param slotIndex for which call quality state changed. Can be derived from subId except when + * subId is invalid. + * @param callQuality Information about call quality e.g, call quality level + * @param networkType associated with this data connection. e.g, LTE + * + * @hide + */ + public void notifyCallQualityChanged(int subId, int slotIndex, CallQuality callQuality, + @NetworkType int networkType) { + try { + sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify emergency number list changed on certain subscription. + * + * @param subId for which emergency number list changed. + * @param slotIndex for which emergency number list changed. Can be derived from subId except + * when subId is invalid. + * + * @hide + */ + public void notifyEmergencyNumberList(int subId, int slotIndex) { + try { + sRegistry.notifyEmergencyNumberList(slotIndex, subId); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify radio power state changed on certain subscription. + * + * @param subId for which radio power state changed. + * @param slotIndex for which radio power state changed. Can be derived from subId except when + * subId is invalid. + * @param radioPowerState the current modem radio state. + * + * @hide + */ + public void notifyRadioPowerStateChanged(int subId, int slotIndex, + @RadioPowerState int radioPowerState) { + try { + sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify {@link PhoneCapability} changed. + * + * @param phoneCapability the capability of the modem group. + * + * @hide + */ + public void notifyPhoneCapabilityChanged(PhoneCapability phoneCapability) { + try { + sRegistry.notifyPhoneCapabilityChanged(phoneCapability); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify data activation state changed on certain subscription. + * @see TelephonyManager#getDataActivationState() + * + * @param subId for which data activation state changed. + * @param slotIndex for which data activation state changed. Can be derived from subId except + * when subId is invalid. + * @param activationState sim activation state e.g, activated. + * + * @hide + */ + public void notifyDataActivationStateChanged(int subId, int slotIndex, + @SimActivationState int activationState) { + try { + sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId, + TelephonyManager.SIM_ACTIVATION_TYPE_DATA, activationState); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify voice activation state changed on certain subscription. + * @see TelephonyManager#getVoiceActivationState() + * + * @param subId for which voice activation state changed. + * @param slotIndex for which voice activation state changed. Can be derived from subId except + * subId is invalid. + * @param activationState sim activation state e.g, activated. + * + * @hide + */ + public void notifyVoiceActivationStateChanged(int subId, int slotIndex, + @SimActivationState int activationState) { + try { + sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId, + TelephonyManager.SIM_ACTIVATION_TYPE_VOICE, activationState); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify User mobile data state changed on certain subscription. e.g, mobile data is enabled + * or disabled. + * + * @param subId for which mobile data state has changed. + * @param slotIndex for which mobile data state has changed. Can be derived from subId except + * when subId is invalid. + * @param state {@code true} indicates mobile data is enabled/on. {@code false} otherwise. + * + * @hide + */ + public void notifyUserMobileDataStateChanged(int slotIndex, int subId, boolean state) { + try { + sRegistry.notifyUserMobileDataStateChangedForPhoneId(slotIndex, subId, state); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * TODO: this is marked as deprecated, can we move this one safely? + * + * @param subId + * @param slotIndex + * @param rawData + * + * @hide + */ + public void notifyOemHookRawEventForSubscriber(int subId, int slotIndex, byte[] rawData) { + try { + sRegistry.notifyOemHookRawEventForSubscriber(slotIndex, subId, rawData); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify IMS call disconnect causes which contains {@link android.telephony.ims.ImsReasonInfo}. + * + * @param subId for which ims call disconnect. + * @param imsReasonInfo the reason for ims call disconnect. + * + * @hide + */ + public void notifyImsDisconnectCause(int subId, ImsReasonInfo imsReasonInfo) { + try { + sRegistry.notifyImsDisconnectCause(subId, imsReasonInfo); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify precise data connection failed cause on certain subscription. + * + * @param subId for which data connection failed. + * @param slotIndex for which data conenction failed. Can be derived from subId except when + * subId is invalid. + * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. + * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. + * @param failCause data fail cause. + * + * @hide + */ + public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, String apnType, + String apn, @DataFailureCause int failCause) { + try { + sRegistry.notifyPreciseDataConnectionFailed(slotIndex, subId, apnType, apn, failCause); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify single Radio Voice Call Continuity (SRVCC) state change for the currently active call + * on certain subscription. + * + * @param subId for which srvcc state changed. + * @param state srvcc state + * + * @hide + */ + public void notifySrvccStateChanged(int subId, @SrvccState int state) { + try { + sRegistry.notifySrvccStateChanged(subId, state); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify over the air sim provisioning(OTASP) mode changed on certain subscription. + * + * @param subId for which otasp mode changed. + * @param otaspMode latest mode for OTASP e.g, OTASP needed. + * + * @hide + */ + public void notifyOtaspChanged(int subId, int otaspMode) { + try { + sRegistry.notifyOtaspChanged(subId, otaspMode); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify precise call state changed on certain subscription, including foreground, background + * and ringcall states. + * + * @param subId for which precise call state changed. + * @param slotIndex for which precise call state changed. Can be derived from subId except when + * subId is invalid. + * @param ringCallPreciseState ringCall state. + * @param foregroundCallPreciseState foreground call state. + * @param backgroundCallPreciseState background call state. + * + * @hide + */ + public void notifyPreciseCallState(int subId, int slotIndex, @State int ringCallPreciseState, + @State int foregroundCallPreciseState, @State int backgroundCallPreciseState) { + try { + sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState, + foregroundCallPreciseState, backgroundCallPreciseState); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify call disconnect causes which contains {@link DisconnectCause} and {@link + * android.telephony.PreciseDisconnectCause}. + * + * @param subId for which call disconnected. + * @param slotIndex for which call disconnected. Can be derived from subId except when subId is + * invalid. + * @param cause {@link DisconnectCause} for the disconnected call. + * @param preciseCause {@link android.telephony.PreciseDisconnectCause} for the disconnected + * call. + * + * @hide + */ + public void notifyDisconnectCause(int slotIndex, int subId, int cause, int preciseCause) { + try { + sRegistry.notifyDisconnectCause(slotIndex, subId, cause, preciseCause); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify data connection failed on certain subscription. + * + * @param subId for which data connection failed. + * @param slotIndex for which data conenction faled. Can be derived from subId except when subId + * is invalid. + * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. Note each data + * connection can support multiple anyTypes. + * + * @hide + */ + public void notifyDataConnectionFailed(int subId, int slotIndex, String apnType) { + try { + sRegistry.notifyDataConnectionFailedForSubscriber(slotIndex, subId, apnType); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * TODO change from bundle to CellLocation? + * @hide + */ + public void notifyCellLocation(int subId, Bundle cellLocation) { + try { + sRegistry.notifyCellLocationForSubscriber(subId, cellLocation); + } catch (RemoteException ex) { + // system process is dead + } + } + + /** + * Notify {@link CellInfo} changed on certain subscription. e.g, when an observed cell info has + * changed or new cells have been added or removed on the given subscription. + * + * @param subId for which cellinfo changed. + * @param cellInfo A list of cellInfo associated with the given subscription. + * + * @hide + */ + public void notifyCellInfoChanged(int subId, List<CellInfo> cellInfo) { + try { + sRegistry.notifyCellInfoForSubscriber(subId, cellInfo); + } catch (RemoteException ex) { + + } + } + + /** + * @param activeDataSubId + * @hide + */ + public void notifyActiveDataSubIdChanged(int activeDataSubId) { + try { + sRegistry.notifyActiveDataSubIdChanged(activeDataSubId); + } catch (RemoteException ex) { + + } + } +} diff --git a/core/java/android/util/Singleton.java b/core/java/android/util/Singleton.java index 33135e6fd62c..15c6b5b5d7f8 100644 --- a/core/java/android/util/Singleton.java +++ b/core/java/android/util/Singleton.java @@ -26,6 +26,11 @@ import android.annotation.UnsupportedAppUsage; * @hide */ public abstract class Singleton<T> { + + @UnsupportedAppUsage + public Singleton() { + } + @UnsupportedAppUsage private T mInstance; diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java index 54cfc00cb5b3..5f9bf39fb3dd 100644 --- a/core/java/android/view/AccessibilityIterators.java +++ b/core/java/android/view/AccessibilityIterators.java @@ -47,6 +47,10 @@ public final class AccessibilityIterators { public static abstract class AbstractTextSegmentIterator implements TextSegmentIterator { @UnsupportedAppUsage + public AbstractTextSegmentIterator() { + } + + @UnsupportedAppUsage protected String mText; private final int[] mSegment = new int[2]; diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java index 05d9167589d4..6b200e1af39a 100644 --- a/core/java/android/view/ActionMode.java +++ b/core/java/android/view/ActionMode.java @@ -21,6 +21,8 @@ import android.annotation.StringRes; import android.annotation.TestApi; import android.graphics.Rect; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * Represents a contextual mode of the user interface. Action modes can be used to provide * alternative interaction modes and replace parts of the normal UI until finished. @@ -279,6 +281,7 @@ public abstract class ActionMode { * @return true if the UI used to show this action mode can take focus * @hide Internal use only */ + @UnsupportedAppUsage @TestApi public boolean isUiFocusable() { return true; diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index e95b5caa4fa0..28eb79ae1f2a 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -331,6 +331,7 @@ public final class Choreographer { * @return the requested time between frames, in milliseconds * @hide */ + @UnsupportedAppUsage @TestApi public static long getFrameDelay() { return sFrameDelay; @@ -413,6 +414,7 @@ public final class Choreographer { * @see #removeCallbacks * @hide */ + @UnsupportedAppUsage @TestApi public void postCallback(int callbackType, Runnable action, Object token) { postCallbackDelayed(callbackType, action, token, 0); @@ -432,6 +434,7 @@ public final class Choreographer { * @see #removeCallback * @hide */ + @UnsupportedAppUsage @TestApi public void postCallbackDelayed(int callbackType, Runnable action, Object token, long delayMillis) { @@ -482,6 +485,7 @@ public final class Choreographer { * @see #postCallbackDelayed * @hide */ + @UnsupportedAppUsage @TestApi public void removeCallbacks(int callbackType, Runnable action, Object token) { if (callbackType < 0 || callbackType > CALLBACK_LAST) { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 39792ce58367..1c3294858db8 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -151,6 +151,7 @@ interface IWindowManager float getCurrentAnimatorScale(); // For testing + @UnsupportedAppUsage(maxTargetSdk = 28) void setInTouchMode(boolean showFocus); // For StrictMode flashing a red border on violations from the UI @@ -158,6 +159,7 @@ interface IWindowManager // Manager uses that to determine whether or not the red border should // actually be shown. (it will be ignored that pid doesn't have windows // on screen) + @UnsupportedAppUsage(maxTargetSdk = 28) void showStrictModeViolation(boolean on); // Proxy to set the system property for whether the flashing diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 86e94f4da170..833e78ff5c71 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -2613,6 +2613,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #getActionButton() * @hide */ + @UnsupportedAppUsage @TestApi public final void setActionButton(int button) { nativeSetActionButton(mNativePtr, button); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 4e86e60fdd62..a35eb1e2b309 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4555,6 +4555,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } static class ListenerInfo { + + @UnsupportedAppUsage + ListenerInfo() { + } + /** * Listener used to dispatch focus change events. * This field should be made private, so it is hidden from the SDK. @@ -24695,6 +24700,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param isRoot true if the view belongs to the root namespace, false * otherwise */ + @UnsupportedAppUsage @TestApi public void setIsRootNamespace(boolean isRoot) { if (isRoot) { @@ -27831,6 +27837,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private int mClassification; + @UnsupportedAppUsage + private CheckForLongPress() { + } + @Override public void run() { if ((mOriginalPressedState == isPressed()) && (mParent != null) @@ -28316,6 +28326,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * whenever possible. */ static class InvalidateInfo { + + @UnsupportedAppUsage + InvalidateInfo() { + } + private static final int POOL_LIMIT = 10; private static final SynchronizedPool<InvalidateInfo> sPool = diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index c50a3aa8ac7c..d002d7e66d6a 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -218,6 +218,11 @@ public final class ViewTreeObserver { * @hide */ public final static class InternalInsetsInfo { + + @UnsupportedAppUsage + public InternalInsetsInfo() { + } + /** * Offsets from the frame of the window at which the content of * windows behind it should be placed. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 2e5a7501f898..450de6d8c233 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1686,6 +1686,7 @@ public interface WindowManager extends ViewManager { * * {@hide} */ + @UnsupportedAppUsage @TestApi public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 0x00000040; @@ -1930,6 +1931,7 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, name = "COLOR_SPACE_AGNOSTIC") }) + @UnsupportedAppUsage @TestApi public int privateFlags; diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java index 563e00e3ca6a..7e067197ced8 100644 --- a/core/java/android/webkit/CacheManager.java +++ b/core/java/android/webkit/CacheManager.java @@ -50,6 +50,11 @@ public final class CacheManager { */ @Deprecated public static class CacheResult { + + @UnsupportedAppUsage + public CacheResult() { + } + // these fields are saved to the database @UnsupportedAppUsage int httpStatusCode; diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 6b324a541c42..b9da3071d895 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -36,7 +36,6 @@ import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.accessibility.AccessibilityEvent; import android.view.inspector.InspectableProperty; -import android.view.inspector.InspectionCompanion; import android.view.inspector.PropertyMapper; import android.view.inspector.PropertyReader; import android.widget.RemoteViews.RemoteView; @@ -2026,6 +2025,11 @@ public class RelativeLayout extends ViewGroup { * A node with no dependent is considered a root of the graph. */ static class Node { + + @UnsupportedAppUsage + Node() { + } + /** * The view representing this node in the layout. */ diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java index 1bed32ecf347..a5d3e45323a4 100644 --- a/core/java/android/widget/ScrollBarDrawable.java +++ b/core/java/android/widget/ScrollBarDrawable.java @@ -60,6 +60,10 @@ public class ScrollBarDrawable extends Drawable implements Drawable.Callback { private ColorFilter mColorFilter; private boolean mHasSetColorFilter; + @UnsupportedAppUsage + public ScrollBarDrawable() { + } + /** * Indicate whether the horizontal scrollbar track should always be drawn * regardless of the extent. Defaults to false. diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java index 0b08099b51ed..7307de5146f8 100644 --- a/core/java/com/android/internal/app/AlertActivity.java +++ b/core/java/com/android/internal/app/AlertActivity.java @@ -34,6 +34,10 @@ import android.view.accessibility.AccessibilityEvent; */ public abstract class AlertActivity extends Activity implements DialogInterface { + @UnsupportedAppUsage + public AlertActivity() { + } + /** * The model for the alert. * diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 00206fc38d1d..80c821b03393 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -25,6 +25,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.app.Activity; import android.app.ActivityManager; import android.app.prediction.AppPredictionContext; @@ -139,6 +140,9 @@ import java.util.Set; public class ChooserActivity extends ResolverActivity { private static final String TAG = "ChooserActivity"; + @UnsupportedAppUsage + public ChooserActivity() { + } /** * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java index c11089ba19bd..49f77e11cf80 100644 --- a/core/java/com/android/internal/app/LocaleStore.java +++ b/core/java/com/android/internal/app/LocaleStore.java @@ -194,7 +194,7 @@ public class LocaleStore { private static Set<String> getSimCountries(Context context) { Set<String> result = new HashSet<>(); - TelephonyManager tm = TelephonyManager.from(context); + TelephonyManager tm = context.getSystemService(TelephonyManager.class); if (tm != null) { String iso = tm.getSimCountryIso().toUpperCase(Locale.US); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 58ce03baa136..f22e62ccff45 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -101,6 +101,10 @@ import java.util.Set; @UiThread public class ResolverActivity extends Activity { + @UnsupportedAppUsage + public ResolverActivity() { + } + // Temporary flag for new chooser delegate behavior. boolean mEnableChooserDelegate = true; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java index fd2ada08edc1..36bc22906695 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java @@ -49,6 +49,18 @@ public final class CompatibilityChangeConfig implements Parcelable { return mChangeConfig.forceDisabledSet(); } + /** + * Returns if a change is enabled or disabled in this config. + */ + public boolean isChangeEnabled(long changeId) { + if (mChangeConfig.isForceEnabled(changeId)) { + return true; + } else if (mChangeConfig.isForceDisabled(changeId)) { + return false; + } + throw new IllegalStateException("Change " + changeId + " is not defined."); + } + private CompatibilityChangeConfig(Parcel in) { long[] enabledArray = in.createLongArray(); long[] disabledArray = in.createLongArray(); diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl new file mode 100644 index 000000000000..3bc72771f99c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 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.compat; + +parcelable CompatibilityChangeInfo; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java new file mode 100644 index 000000000000..e48e2df4043c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 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.compat; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class is a parcelable version of {@link com.android.server.compat.Change}. + * + * @hide + */ +public class CompatibilityChangeInfo implements Parcelable { + private final long mChangeId; + private final @Nullable String mName; + private final int mEnableAfterTargetSdk; + private final boolean mDisabled; + + public long getId() { + return mChangeId; + } + + @Nullable + public String getName() { + return mName; + } + + public int getEnableAfterTargetSdk() { + return mEnableAfterTargetSdk; + } + + public boolean getDisabled() { + return mDisabled; + } + + public CompatibilityChangeInfo( + Long changeId, String name, int enableAfterTargetSdk, boolean disabled) { + this.mChangeId = changeId; + this.mName = name; + this.mEnableAfterTargetSdk = enableAfterTargetSdk; + this.mDisabled = disabled; + } + + private CompatibilityChangeInfo(Parcel in) { + mChangeId = in.readLong(); + mName = in.readString(); + mEnableAfterTargetSdk = in.readInt(); + mDisabled = in.readBoolean(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mChangeId); + dest.writeString(mName); + dest.writeInt(mEnableAfterTargetSdk); + dest.writeBoolean(mDisabled); + } + + public static final Parcelable.Creator<CompatibilityChangeInfo> CREATOR = + new Parcelable.Creator<CompatibilityChangeInfo>() { + + @Override + public CompatibilityChangeInfo createFromParcel(Parcel in) { + return new CompatibilityChangeInfo(in); + } + + @Override + public CompatibilityChangeInfo[] newArray(int size) { + return new CompatibilityChangeInfo[size]; + } + }; +} diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 8391ad2f12c2..7dcb12c9e72b 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -17,8 +17,10 @@ package com.android.internal.compat; import android.content.pm.ApplicationInfo; +import java.util.Map; parcelable CompatibilityChangeConfig; +parcelable CompatibilityChangeInfo; /** * Platform private API for talking with the PlatformCompat service. @@ -131,7 +133,7 @@ interface IPlatformCompat boolean isChangeEnabledByUid(long changeId, int uid); /** - * Add overrides to compatibility changes. + * Add overrides to compatibility changes. Kills the app to allow the changes to take effect. * * @param overrides Parcelable containing the compat change overrides to be applied. * @param packageName The package name of the app whose changes will be overridden. @@ -140,10 +142,57 @@ interface IPlatformCompat void setOverrides(in CompatibilityChangeConfig overrides, in String packageName); /** - * Revert overrides to compatibility changes. + * Add overrides to compatibility changes. Doesn't kill the app, to be only used in tests. + * + * @param overrides Parcelable containing the compat change overrides to be applied. + * @param packageName The package name of the app whose changes will be overridden. + * + */ + void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName); + + /** + * Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig, + * String)}. This restores the default behaviour for the given change and app, once any app + * processes have been restarted. + * Kills the app to allow the changes to take effect. + * + * @param changeId The ID of the change that was overridden. + * @param packageName The app package name that was overridden. + * @return {@code true} if an override existed; + */ + boolean clearOverride(long changeId, String packageName); + + /** + * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect. * * @param packageName The package name of the app whose overrides will be cleared. * */ void clearOverrides(in String packageName); + + /** + * Revert overrides to compatibility changes. Doesn't kill the app, to be only used in tests. + * + * @param packageName The package name of the app whose overrides will be cleared. + * + */ + void clearOverridesForTest(in String packageName); + + + /** + * Get configs for an application. + * + * @param appInfo The application whose config will be returned. + * + * @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for + * the given app or not. + */ + CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo); + + /** + * List all compatibility changes. + * + * @return An array of {@link CompatChangeInfo} known to the service. + */ + CompatibilityChangeInfo[] listAllChanges(); } diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java index c928f3f39f03..5d7d3af8750a 100644 --- a/core/java/com/android/internal/content/PackageMonitor.java +++ b/core/java/com/android/internal/content/PackageMonitor.java @@ -27,6 +27,7 @@ import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.util.Slog; + import com.android.internal.os.BackgroundThread; import com.android.internal.util.Preconditions; @@ -72,6 +73,10 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { String[] mTempArray = new String[1]; @UnsupportedAppUsage + public PackageMonitor() { + } + + @UnsupportedAppUsage public void register(Context context, Looper thread, boolean externalStorage) { register(context, thread, null, externalStorage); } diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index a691a2403f37..f916cf64564d 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -41,6 +41,10 @@ public class MetricsLogger { private static MetricsLogger sMetricsLogger; + @UnsupportedAppUsage + public MetricsLogger() { + } + private static MetricsLogger getLogger() { if (sMetricsLogger == null) { sMetricsLogger = new MetricsLogger(); diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java index 9ee97108ce49..2ad9759b1f68 100644 --- a/core/java/com/android/internal/net/LegacyVpnInfo.java +++ b/core/java/com/android/internal/net/LegacyVpnInfo.java @@ -45,6 +45,10 @@ public class LegacyVpnInfo implements Parcelable { public int state = -1; public PendingIntent intent; + @UnsupportedAppUsage + public LegacyVpnInfo() { + } + @Override public int describeContents() { return 0; diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index 65b974ba8b42..e6be54964705 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -108,6 +108,10 @@ public class VpnConfig implements Parcelable { public Network[] underlyingNetworks; public ProxyInfo proxyInfo; + @UnsupportedAppUsage + public VpnConfig() { + } + public void updateAllowedFamilies(InetAddress address) { if (address instanceof Inet4Address) { allowIPv4 = true; diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java index 278f40660ee9..5ba662913529 100644 --- a/core/java/com/android/internal/os/BaseCommand.java +++ b/core/java/com/android/internal/os/BaseCommand.java @@ -40,6 +40,10 @@ public abstract class BaseCommand { private String[] mRawArgs; + @UnsupportedAppUsage + public BaseCommand() { + } + /** * Call to run the command. */ diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java index 02c9542fa40d..b1fc369835c6 100644 --- a/core/java/com/android/internal/os/BatterySipper.java +++ b/core/java/com/android/internal/os/BatterySipper.java @@ -134,6 +134,8 @@ public class BatterySipper implements Comparable<BatterySipper> { // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto) // so the ordinal values (and therefore the order) must never change. // **************** + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/os/BatterySipper$DrainType;") public enum DrainType { AMBIENT_DISPLAY, @UnsupportedAppUsage diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 46e041b3f33e..3d91c37272ad 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -114,6 +114,13 @@ public final class Zygote { */ public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17; + /** + * Disable runtime access to {@link android.annotation.TestApi} annotated members. + * + * <p>This only takes effect if Hidden API access restrictions are enabled as well. + */ + public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18; + /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; /** Default external storage should be mounted. */ diff --git a/core/java/com/android/internal/package-info.java b/core/java/com/android/internal/package-info.java new file mode 100644 index 000000000000..8a226dbdc9fe --- /dev/null +++ b/core/java/com/android/internal/package-info.java @@ -0,0 +1,4 @@ +/** + * @hide + */ +package com.android.internal; diff --git a/core/java/com/android/internal/preference/YesNoPreference.java b/core/java/com/android/internal/preference/YesNoPreference.java index 7abf416bf0af..94ef619f286a 100644 --- a/core/java/com/android/internal/preference/YesNoPreference.java +++ b/core/java/com/android/internal/preference/YesNoPreference.java @@ -23,6 +23,8 @@ import android.os.Parcelable; import android.preference.DialogPreference; import android.util.AttributeSet; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * The {@link YesNoPreference} is a preference to show a dialog with Yes and No * buttons. @@ -40,6 +42,7 @@ public class YesNoPreference extends DialogPreference { this(context, attrs, defStyleAttr, 0); } + @UnsupportedAppUsage public YesNoPreference(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.yesNoPreferenceStyle); } diff --git a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl index 493b1ff6aba7..493b1ff6aba7 100644 --- a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl +++ b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index 90019eef62fd..084a3cc64a35 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -29,6 +29,9 @@ import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; +/** + * {@hide} + */ oneway interface IPhoneStateListener { void onServiceStateChanged(in ServiceState serviceState); void onSignalStrengthChanged(int asu); diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index a20c49455888..d7a7af1d530f 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -43,14 +43,16 @@ interface ITelephonyRegistry { void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events, boolean notifyNow); @UnsupportedAppUsage - void notifyCallState(int state, String incomingNumber); - void notifyCallStateForPhoneId(in int phoneId, in int subId, int state, String incomingNumber); + void notifyCallStateForAllSubs(int state, String incomingNumber); + void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber); void notifyServiceStateForPhoneId(in int phoneId, in int subId, in ServiceState state); void notifySignalStrengthForPhoneId(in int phoneId, in int subId, in SignalStrength signalStrength); void notifyMessageWaitingChangedForPhoneId(in int phoneId, in int subId, in boolean mwi); + @UnsupportedAppUsage(maxTargetSdk = 28) void notifyCallForwardingChanged(boolean cfi); void notifyCallForwardingChangedForSubscriber(in int subId, boolean cfi); + @UnsupportedAppUsage(maxTargetSdk = 28) void notifyDataActivity(int state); void notifyDataActivityForSubscriber(in int subId, int state); void notifyDataConnection(int state, boolean isDataConnectivityPossible, @@ -63,8 +65,10 @@ interface ITelephonyRegistry { @UnsupportedAppUsage void notifyDataConnectionFailed(String apnType); void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType); + @UnsupportedAppUsage(maxTargetSdk = 28) void notifyCellLocation(in Bundle cellLocation); void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation); + @UnsupportedAppUsage(maxTargetSdk = 28) void notifyOtaspChanged(in int subId, in int otaspMode); @UnsupportedAppUsage void notifyCellInfo(in List<CellInfo> cellInfo); diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java index 630916ebeecb..c1d129b66e7a 100644 --- a/core/java/com/android/internal/util/MemInfoReader.java +++ b/core/java/com/android/internal/util/MemInfoReader.java @@ -24,6 +24,10 @@ public final class MemInfoReader { final long[] mInfos = new long[Debug.MEMINFO_COUNT]; @UnsupportedAppUsage + public MemInfoReader() { + } + + @UnsupportedAppUsage public void readMemInfo() { // Permit disk reads here, as /proc/meminfo isn't really "on // disk" and should be fast. TODO: make BlockGuard ignore diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index f9cdf3d0be61..f5a9fde97159 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -16,9 +16,11 @@ package com.android.internal.view; +import android.annotation.UnsupportedAppUsage; import android.graphics.Point; import android.graphics.Rect; import android.hardware.input.InputManager; +import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -37,6 +39,10 @@ public class BaseIWindow extends IWindow.Stub { private IWindowSession mSession; public int mSeq; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public BaseIWindow() { + } + public void setSession(IWindowSession session) { mSession = session; } diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java index d48034b66266..1f5b0701d2a7 100644 --- a/core/java/com/android/internal/widget/PointerLocationView.java +++ b/core/java/com/android/internal/widget/PointerLocationView.java @@ -91,6 +91,10 @@ public class PointerLocationView extends View implements InputDeviceListener, private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator(); private VelocityTracker.Estimator mAltEstimator = new VelocityTracker.Estimator(); + @UnsupportedAppUsage + public PointerState() { + } + public void clearTrace() { mTraceCount = 0; } diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java index a0740eee5df6..e1a10a5805f5 100644 --- a/core/java/com/android/server/net/BaseNetworkObserver.java +++ b/core/java/com/android/server/net/BaseNetworkObserver.java @@ -28,6 +28,11 @@ import android.net.RouteInfo; * @hide */ public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub { + + @UnsupportedAppUsage + public BaseNetworkObserver() { + } + @Override public void interfaceStatusChanged(String iface, boolean up) { // default no-op diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java index 9d12f82aeb75..00fcb16f6d3a 100644 --- a/core/java/com/google/android/util/AbstractMessageParser.java +++ b/core/java/com/google/android/util/AbstractMessageParser.java @@ -17,13 +17,14 @@ package com.google.android.util; import android.annotation.UnsupportedAppUsage; + import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.Set; -import java.util.List; /** * @@ -653,8 +654,9 @@ public abstract class AbstractMessageParser { /** Represents a unit of parsed output. */ public static abstract class Token { + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;") public enum Type { - @UnsupportedAppUsage HTML ("html"), @UnsupportedAppUsage diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9a90555041d7..9e4c2220576c 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -667,6 +667,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; + char dex2oatCpuSetBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX]; + char dex2oatCpuSetImageBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; @@ -956,6 +958,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option"); parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j", "-Ximage-compiler-option"); + parseCompilerOption("dalvik.vm.dex2oat-cpu-set", dex2oatCpuSetBuf, "--cpu-set=", + "-Xcompiler-option"); + parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=", + "-Ximage-compiler-option"); // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to // pass the instruction-set-features/variant as an image-compiler-option. diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h index 16ef753c0cd0..f03f42737134 100644 --- a/core/jni/core_jni_helpers.h +++ b/core/jni/core_jni_helpers.h @@ -22,6 +22,18 @@ #include <nativehelper/scoped_utf_chars.h> #include <android_runtime/AndroidRuntime.h> +// Host targets (layoutlib) do not differentiate between regular and critical native methods, +// and they need all the JNI methods to have JNIEnv* and jclass/jobject as their first two arguments. +// The following macro allows to have those arguments when compiling for host while omitting them when +// compiling for Android. +#ifdef __ANDROID__ +#define CRITICAL_JNI_PARAMS +#define CRITICAL_JNI_PARAMS_COMMA +#else +#define CRITICAL_JNI_PARAMS JNIEnv*, jclass +#define CRITICAL_JNI_PARAMS_COMMA JNIEnv*, jclass, +#endif + namespace android { // Defines some helpful functions. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9aacbe65e480..74b4f34ebbf4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -142,7 +142,7 @@ <protected-broadcast android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.device.action.UUID" /> <protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" /> - <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.action.ALIAS_CHANGED" /> <protected-broadcast android:name="android.bluetooth.device.action.FOUND" /> <protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" /> <protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" /> @@ -497,6 +497,7 @@ <protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" /> <protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" /> <protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" /> + <protected-broadcast android:name="android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED" /> <protected-broadcast android:name="android.telephony.action.SECRET_CODE" /> <protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" /> <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" /> @@ -1625,7 +1626,7 @@ @hide This should only be used by Settings and SystemUI. --> <permission android:name="android.permission.NETWORK_SETTINGS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows SetupWizard to call methods in Networking services <p>Not for use by any other third-party or privileged applications. @@ -2145,12 +2146,12 @@ <!-- Must be required by a telephony data service to ensure that only the system can bind to it. - <p>Protection level: signature + <p>Protection level: signature|telephony @SystemApi @hide --> <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Must be required by a NetworkService to ensure that only the system can bind to it. @@ -2171,11 +2172,11 @@ <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to it. - <p>Protection level: signature + <p>Protection level: signature|telephony @hide --> <permission android:name="android.permission.BIND_EUICC_SERVICE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- ================================== --> <!-- Permissions for sdcard interaction --> @@ -2955,7 +2956,7 @@ @hide --> <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- @SystemApi Allows an application to use {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} @@ -3735,7 +3736,7 @@ @hide --> <permission android:name="android.permission.DEVICE_POWER" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows toggling battery saver on the system. Superseded by DEVICE_POWER permission. @hide @SystemApi @@ -3770,13 +3771,13 @@ <p>Not for use by third-party applications. --> <permission android:name="android.permission.BROADCAST_SMS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows an application to broadcast a WAP PUSH receipt notification. <p>Not for use by third-party applications. --> <permission android:name="android.permission.BROADCAST_WAP_PUSH" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- @SystemApi Allows an application to broadcast privileged networking requests. <p>Not for use by third-party applications. @@ -4391,13 +4392,13 @@ {@link android.provider.BlockedNumberContract}. @hide --> <permission android:name="android.permission.READ_BLOCKED_NUMBERS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows the holder to write blocked numbers. See {@link android.provider.BlockedNumberContract}. @hide --> <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only the system can bind to it. diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 77fca8fe4d8e..17045d812f4b 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -295,6 +295,9 @@ <!-- Additional flag from base permission type: this permission can be automatically granted to the system app predictor --> <flag name="appPredictor" value="0x200000" /> + <!-- Additional flag from base permission type: this permission can be automatically + granted to the system telephony apps --> + <flag name="telephony" value="0x400000" /> </attr> <!-- Flags indicating more context for a permission group. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 05f78d458699..84d4857b032d 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -448,7 +448,7 @@ </string-array> <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] --> - <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastreceiver + <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastservice </string> <!-- If the mobile hotspot feature requires provisioning, a package name and class name @@ -529,7 +529,7 @@ - TYPE_ETHERNET (9) is prepended to this list, and - - the return value of TelephonyManager.getTetherApnRequired() + - the return value of TelephonyManager.isTetherApnRequired() determines how the array is further modified: * TRUE (DUN REQUIRED). @@ -3677,6 +3677,15 @@ --> <string name="config_defaultWellbeingPackage" translatable="false"></string> + + <!-- The package name for the system telephony apps. + This package must be trusted, as it will be granted with permissions with special telephony + protection level. Note, framework by default support multiple telephony apps, each package + name is separated by comma. + Example: "com.android.phone,com.android.stk,com.android.providers.telephony" + --> + <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string> + <!-- The component name for the default system attention service. This service must be trusted, as it can be activated without explicit consent of the user. See android.attention.AttentionManagerService. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6efa2d653b4c..e729b03c1b82 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3056,9 +3056,9 @@ <string name="ok">OK</string> <!-- Preference framework strings. --> <string name="cancel">Cancel</string> - <!-- Preference framework strings. --> + <!-- Preference framework strings. {@deprecated Do not use. Incorrectly matches android.R.string.ok rather than "yes".} --> <string name="yes">OK</string> - <!-- Preference framework strings. --> + <!-- Preference framework strings. {@deprecated Do not use. Incorrectly matches android.R.string.cancel rather than "no".} --> <string name="no">Cancel</string> <!-- This is the generic "attention" string to be used in attention dialogs. Typically combined with setIconAttribute(android.R.attr.alertDialogIcon) diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0804703a585b..e8cd271118dc 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3464,6 +3464,7 @@ <java-symbol type="string" name="config_defaultAutofillService" /> <java-symbol type="string" name="config_defaultTextClassifierPackage" /> <java-symbol type="string" name="config_defaultWellbeingPackage" /> + <java-symbol type="string" name="config_telephonyPackages" /> <java-symbol type="string" name="config_defaultContentCaptureService" /> <java-symbol type="string" name="config_defaultAugmentedAutofillService" /> <java-symbol type="string" name="config_defaultAppPredictionService" /> diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java index 58c43ac2cf91..5e41355601e4 100644 --- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java +++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java @@ -508,7 +508,12 @@ public class PackageParserTest { apexInfo.modulePath = apexFile.getPath(); apexInfo.versionCode = 191000070; int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; - PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexInfo, flags); + + PackageParser pp = new PackageParser(); + Package p = pp.parsePackage(apexFile, flags, false); + PackageParser.collectCertificates(p, false); + PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags); + assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName); assertTrue(pi.applicationInfo.enabled); assertEquals(28, pi.applicationInfo.targetSdkVersion); diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 14011373d2ed..80f3cc68221f 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -49,6 +49,12 @@ applications that come with the platform <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> </privapp-permissions> + <privapp-permissions package="com.android.cellbroadcastservice"> + <permission name="android.permission.MODIFY_PHONE_STATE"/> + <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> + <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/> + </privapp-permissions> + <privapp-permissions package="com.android.externalstorage"> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk index 99dfd0a6d455..2392b333c587 100644 --- a/data/sounds/AudioPackage11.mk +++ b/data/sounds/AudioPackage11.mk @@ -32,7 +32,7 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Lock.ogg \ $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Unlock.ogg \ $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Trusted.ogg \ - $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/ChargingStarted.ogg \. + $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/ChargingStarted.ogg \ $(LOCAL_PATH)/effects/ogg/InCallNotification.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/InCallNotification.ogg \ $(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/notifications/Adara.ogg \ diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 646aa13664c4..b6f525042713 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -922,15 +922,26 @@ public class KeyStore { } } - public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature, - byte[] entropy) { + /** + * Android KeyStore finish operation. + * + * @param token Authentication token. + * @param arguments Keymaster arguments + * @param input Optional additional input data. + * @param signature Optional signature to be verified. + * @param entropy Optional additional entropy + * @return OperationResult that will indicate success or error of the operation. + */ + public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] input, + byte[] signature, byte[] entropy) { OperationPromise promise = new OperationPromise(); try { mBinder.asBinder().linkToDeath(promise, 0); arguments = arguments != null ? arguments : new KeymasterArguments(); entropy = entropy != null ? entropy : new byte[0]; + input = input != null ? input : new byte[0]; signature = signature != null ? signature : new byte[0]; - int errorCode = mBinder.finish(promise, token, arguments, signature, entropy); + int errorCode = mBinder.finish(promise, token, arguments, input, signature, entropy); if (errorCode == NO_ERROR) { return promise.getFuture().get(); } else { @@ -948,7 +959,7 @@ public class KeyStore { } public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { - return finish(token, arguments, signature, null); + return finish(token, arguments, null, signature, null); } private class KeystoreResultPromise diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java index 441ee660b53a..c6515efd2c61 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java @@ -432,7 +432,7 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC } @Override - public OperationResult finish(byte[] signature, byte[] additionalEntropy) { + public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) { if ((additionalEntropy != null) && (additionalEntropy.length > 0)) { throw new ProviderException("AAD stream does not support additional entropy"); } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index 3dc884eb38ad..17aacb9756aa 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -210,13 +210,9 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { } } if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { - if (mKeySizeBits < 64) { + if (mKeySizeBits < 64 || mKeySizeBits > 512) { throw new InvalidAlgorithmParameterException( - "HMAC key size must be at least 64 bits."); - } - if (mKeySizeBits > 512 && spec.isStrongBoxBacked()) { - throw new InvalidAlgorithmParameterException( - "StrongBox HMAC key size must be smaller than 512 bits."); + "HMAC key sizes must be within 64-512 bits, inclusive."); } // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index bd6ce7ec6a3b..e3f43efff72b 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -1256,6 +1256,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * * Sets whether to include a temporary unique ID field in the attestation certificate. */ + @UnsupportedAppUsage @TestApi @NonNull public Builder setUniqueIdIncluded(boolean uniqueIdIncluded) { diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java index e0304787142d..75bea26aecef 100644 --- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java @@ -62,7 +62,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS * Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't * be reached. */ - OperationResult finish(byte[] siganture, byte[] additionalEntropy); + OperationResult finish(byte[] input, byte[] siganture, byte[] additionalEntropy); } // Binder buffer is about 1MB, but it's shared between all active transactions of the process. @@ -217,7 +217,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS byte[] output = update(input, inputOffset, inputLength); output = ArrayUtils.concat(output, flush()); - OperationResult opResult = mKeyStoreStream.finish(signature, additionalEntropy); + OperationResult opResult = mKeyStoreStream.finish(EmptyArray.BYTE, signature, + additionalEntropy); if (opResult == null) { throw new KeyStoreConnectException(); } else if (opResult.resultCode != KeyStore.NO_ERROR) { @@ -334,8 +335,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS } @Override - public OperationResult finish(byte[] signature, byte[] additionalEntropy) { - return mKeyStore.finish(mOperationToken, null, signature, additionalEntropy); + public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) { + return mKeyStore.finish(mOperationToken, null, input, signature, additionalEntropy); } } } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index f51848e5691a..4c08a3829934 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -234,9 +234,6 @@ cc_defaults { "protos/graphicsstats.proto", ], - // Allow implicit fallthroughs in HardwareBitmapUploader.cpp until they are fixed. - cflags: ["-Wno-implicit-fallthrough"], - proto: { export_proto_headers: true, }, diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 9bb6031b76ac..b64588e0dcd2 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -302,6 +302,7 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) { switch (skBitmap.info().colorType()) { case kRGBA_8888_SkColorType: formatInfo.isSupported = true; + [[fallthrough]]; // ARGB_4444 is upconverted to RGBA_8888 case kARGB_4444_SkColorType: formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888; diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index e8905143eb37..f9b2fe057995 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -37,6 +37,8 @@ import com.android.internal.R; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.telephony.GsmAlphabet; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.io.UnsupportedEncodingException; import java.util.concurrent.TimeUnit; @@ -115,6 +117,7 @@ public class GpsNetInitiatedHandler { private final INetInitiatedListener mNetInitiatedListener; // Set to true if string from HAL is encoded as Hex, e.g., "3F0039" + @UnsupportedAppUsage static private boolean mIsHexInput = true; // End time of emergency call, and extension, if set @@ -123,6 +126,9 @@ public class GpsNetInitiatedHandler { public static class GpsNiNotification { + @android.annotation.UnsupportedAppUsage + public GpsNiNotification() { + } public int notificationId; public int niType; public boolean needNotify; @@ -130,9 +136,13 @@ public class GpsNetInitiatedHandler { public boolean privacyOverride; public int timeout; public int defaultResponse; + @UnsupportedAppUsage public String requestorId; + @UnsupportedAppUsage public String text; + @UnsupportedAppUsage public int requestorIdEncoding; + @UnsupportedAppUsage public int textEncoding; }; @@ -258,6 +268,7 @@ public class GpsNetInitiatedHandler { } // Handles NI events from HAL + @UnsupportedAppUsage public void handleNiNotification(GpsNiNotification notif) { if (DEBUG) Log.d(TAG, "in handleNiNotification () :" + " notificationId: " + notif.notificationId @@ -539,6 +550,7 @@ public class GpsNetInitiatedHandler { * set to -1, and <code> isHex </code> can be false. * @return the decoded string */ + @UnsupportedAppUsage static private String decodeString(String original, boolean isHex, int coding) { if (coding == GPS_ENC_NONE || coding == GPS_ENC_UNKNOWN) { diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl index a5716304f0d8..8ae972bde4f9 100644 --- a/location/java/com/android/internal/location/ILocationProvider.aidl +++ b/location/java/com/android/internal/location/ILocationProvider.aidl @@ -29,10 +29,13 @@ import com.android.internal.location.ProviderRequest; */ interface ILocationProvider { + @UnsupportedAppUsage oneway void setLocationProviderManager(in ILocationProviderManager manager); + @UnsupportedAppUsage oneway void setRequest(in ProviderRequest request, in WorkSource ws); + @UnsupportedAppUsage oneway void sendExtraCommand(String command, in Bundle extras); // --- deprecated and will be removed the future --- diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl index c038f36206f6..02fa94c845a6 100644 --- a/media/java/android/media/IRingtonePlayer.aidl +++ b/media/java/android/media/IRingtonePlayer.aidl @@ -27,6 +27,7 @@ import android.os.UserHandle; */ interface IRingtonePlayer { /** Used for Ringtone.java playback */ + @UnsupportedAppUsage oneway void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping); oneway void playWithVolumeShaping(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping, in @nullable VolumeShaper.Configuration volumeShaperConfig); diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 510ee442f852..c9d79784004c 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1702,20 +1702,22 @@ final public class MediaCodec { break; } case EVENT_FRAME_RENDERED: - synchronized (mListenerLock) { - Map<String, Object> map = (Map<String, Object>)msg.obj; - for (int i = 0; ; ++i) { - Object mediaTimeUs = map.get(i + "-media-time-us"); - Object systemNano = map.get(i + "-system-nano"); - if (mediaTimeUs == null || systemNano == null - || mOnFrameRenderedListener == null) { - break; - } - mOnFrameRenderedListener.onFrameRendered( - mCodec, (long)mediaTimeUs, (long)systemNano); + Map<String, Object> map = (Map<String, Object>)msg.obj; + for (int i = 0; ; ++i) { + Object mediaTimeUs = map.get(i + "-media-time-us"); + Object systemNano = map.get(i + "-system-nano"); + OnFrameRenderedListener onFrameRenderedListener; + synchronized (mListenerLock) { + onFrameRenderedListener = mOnFrameRenderedListener; } - break; + if (mediaTimeUs == null || systemNano == null + || onFrameRenderedListener == null) { + break; + } + onFrameRenderedListener.onFrameRendered( + mCodec, (long)mediaTimeUs, (long)systemNano); } + break; default: { break; diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 09221a37cb13..c4eb0310f292 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -79,6 +79,10 @@ public class MediaFile { @UnsupportedAppUsage private static final HashMap<Integer, String> sFormatToMimeTypeMap = new HashMap<>(); + @UnsupportedAppUsage + public MediaFile() { + } + /** @deprecated file types no longer exist */ @Deprecated @UnsupportedAppUsage diff --git a/media/java/android/media/tv/OWNER b/media/java/android/media/tv/OWNERS index 64c0bb53e894..64c0bb53e894 100644 --- a/media/java/android/media/tv/OWNER +++ b/media/java/android/media/tv/OWNERS diff --git a/media/jni/Android.bp b/media/jni/Android.bp index e6c1c67b98e5..f873eeb9aa00 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -100,13 +100,14 @@ cc_library_shared { "android_media_Utils.cpp", ], + header_libs: [ + "libgui_headers", + ], + shared_libs: [ "liblog", - "libgui", - "libnativewindow", "libui", "libutils", - "android.hidl.token@1.0-utils", ], include_dirs: [ diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp index 8c38d887f82b..84a0e0d032d9 100644 --- a/media/jni/android_media_MediaDataSource.cpp +++ b/media/jni/android_media_MediaDataSource.cpp @@ -26,7 +26,6 @@ #include <nativehelper/JNIHelp.h> #include <binder/MemoryDealer.h> -#include <drm/drm_framework_common.h> #include <media/stagefright/foundation/ADebug.h> #include <nativehelper/ScopedLocalRef.h> @@ -160,8 +159,4 @@ String8 JMediaDataSource::toString() { return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid()); } -sp<DecryptHandle> JMediaDataSource::DrmInitialization(const char * /* mime */) { - return NULL; -} - } // namespace android diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h index 39405d2db579..378baf433fed 100644 --- a/media/jni/android_media_MediaDataSource.h +++ b/media/jni/android_media_MediaDataSource.h @@ -47,7 +47,6 @@ public: virtual void close(); virtual uint32_t getFlags(); virtual String8 toString(); - virtual sp<DecryptHandle> DrmInitialization(const char *mime); private: // Protect all member variables with mLock because this object will be diff --git a/media/lib/tvremote/OWNERS b/media/lib/tvremote/OWNERS new file mode 100644 index 000000000000..81d52e1d72db --- /dev/null +++ b/media/lib/tvremote/OWNERS @@ -0,0 +1,2 @@ +nutka@google.com +skill@google.com diff --git a/mms/OWNERS b/mms/OWNERS new file mode 100644 index 000000000000..ba00d5d75010 --- /dev/null +++ b/mms/OWNERS @@ -0,0 +1,14 @@ +set noparent + +tgunn@google.com +breadley@google.com +hallliu@google.com +rgreenwalt@google.com +amitmahajan@google.com +fionaxu@google.com +jackyu@google.com +jminjie@google.com +satk@google.com +shuoq@google.com +refuhoo@google.com +nazaninb@google.com diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java new file mode 100644 index 000000000000..4bcf04691652 --- /dev/null +++ b/mms/java/android/telephony/MmsManager.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 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.app.ActivityThread; +import android.app.PendingIntent; +import android.net.Uri; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.telephony.IMms; + +/** + * Manages MMS operations such as sending multimedia messages. + * Get this object by calling the static method {@link #getInstance()}. + * @hide + */ +public class MmsManager { + private static final String TAG = "MmsManager"; + + /** Singleton object constructed during class initialization. */ + private static final MmsManager sInstance = new MmsManager(); + + /** + * Get the MmsManager singleton instance. + * + * @return the {@link MmsManager} singleton instance. + */ + public static MmsManager getInstance() { + return sInstance; + } + + /** + * Send an MMS message + * + * @param subId the subscription id + * @param contentUri the content Uri from which the message pdu will be read + * @param locationUrl the optional location url where message should be sent to + * @param configOverrides the carrier-specific messaging configuration values to override for + * sending the message. + * @param sentIntent if not NULL this <code>PendingIntent</code> is broadcast when the message + * is successfully sent, or failed + */ + public void sendMultimediaMessage(int subId, Uri contentUri, String locationUrl, + Bundle configOverrides, PendingIntent sentIntent) { + try { + final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); + if (iMms == null) { + return; + } + + iMms.sendMessage(subId, ActivityThread.currentPackageName(), contentUri, + locationUrl, configOverrides, sentIntent); + } catch (RemoteException e) { + // Ignore it + } + } + + /** + * Download an MMS message from carrier by a given location URL + * + * @param subId the subscription id + * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained + * from the MMS WAP push notification + * @param contentUri the content uri to which the downloaded pdu will be written + * @param configOverrides the carrier-specific messaging configuration values to override for + * downloading the message. + * @param downloadedIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is downloaded, or the download is failed + * @throws IllegalArgumentException if locationUrl or contentUri is empty + */ + public void downloadMultimediaMessage(int subId, String locationUrl, Uri contentUri, + Bundle configOverrides, PendingIntent downloadedIntent) { + try { + final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); + if (iMms == null) { + return; + } + iMms.downloadMessage(subId, ActivityThread.currentPackageName(), + locationUrl, contentUri, configOverrides, downloadedIntent); + } catch (RemoteException e) { + // Ignore it + } + } + + /** + * Get carrier-dependent configuration values. + * + * @param subId the subscription id + * @return bundle key/values pairs of configuration values + */ + public Bundle getCarrierConfigValues(int subId) { + try { + IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); + if (iMms != null) { + return iMms.getCarrierConfigValues(subId); + } + } catch (RemoteException ex) { + // ignore it + } + return null; + } +} diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl index fa5073ef1c7e..fa5073ef1c7e 100644 --- a/telephony/java/com/android/internal/telephony/IMms.aidl +++ b/mms/java/com/android/internal/telephony/IMms.aidl diff --git a/native/android/libandroid_net.map.txt b/native/android/libandroid_net.map.txt index be3531da462d..8d4e9009cc56 100644 --- a/native/android/libandroid_net.map.txt +++ b/native/android/libandroid_net.map.txt @@ -1,15 +1,19 @@ -# They are also all available to vendor code. +# The following symbols marked with # llndk are available to vendor code. +# Unlike other VNDK libraries where keeping backwards compatibility is required +# only within a platform release, these symbols need much longer suppport +# because the same LLNDK library serves for both system and vendor partition +# which might be a few years old. LIBANDROID_NET { global: # These functions have been part of the NDK since API 24. - android_getaddrinfofornetwork; # vndk - android_setsocknetwork; # vndk - android_setprocnetwork; # vndk + android_getaddrinfofornetwork; # llndk + android_setsocknetwork; # llndk + android_setprocnetwork; # llndk # These functions have been part of the NDK since API 29. - android_res_cancel; # vndk - android_res_nquery; # vndk - android_res_nresult; # vndk - android_res_nsend; # vndk + android_res_cancel; # llndk + android_res_nquery; # llndk + android_res_nresult; # llndk + android_res_nsend; # llndk local: *; }; diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java index 41fb07228791..f94f69f0fd3f 100644 --- a/opengl/java/com/google/android/gles_jni/EGLImpl.java +++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java @@ -16,12 +16,18 @@ package com.google.android.gles_jni; -import javax.microedition.khronos.egl.*; - import android.graphics.SurfaceTexture; import android.view.Surface; -import android.view.SurfaceView; import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; public class EGLImpl implements EGL10 { private EGLContextImpl mContext = new EGLContextImpl(-1); @@ -50,6 +56,10 @@ public class EGLImpl implements EGL10 { /** @hide **/ public static native int getInitCount(EGLDisplay display); + @UnsupportedAppUsage + public EGLImpl() { + } + public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list) { long eglContextId = _eglCreateContext(display, config, share_context, attrib_list); if (eglContextId == 0) { diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java index d4c0c8049dad..2a8d07f03148 100644 --- a/opengl/java/com/google/android/gles_jni/GLImpl.java +++ b/opengl/java/com/google/android/gles_jni/GLImpl.java @@ -26,7 +26,10 @@ import android.os.Build; import android.os.UserHandle; import android.util.Log; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.nio.Buffer; + import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10Ext; import javax.microedition.khronos.opengles.GL11; @@ -56,6 +59,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack { private boolean have_OES_framebuffer_object; private boolean have_OES_texture_cube_map; + @UnsupportedAppUsage public GLImpl() { } diff --git a/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp new file mode 100644 index 000000000000..7728464f8652 --- /dev/null +++ b/packages/CtsShim/Android.bp @@ -0,0 +1,74 @@ +// +// Copyright (C) 2016 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. +// + +//########################################################## +// Variant: Privileged app + +android_app_import { + name: "CtsShimPrivPrebuilt", + + // this needs to be a privileged application + privileged: true, + + // Make sure the build system doesn't try to resign the APK + dex_preopt: { + enabled: false, + }, + + arch: { + arm: { + apk: "apk/arm/CtsShimPriv.apk", + }, + arm64: { + apk: "apk/arm/CtsShimPriv.apk", + }, + x86: { + apk: "apk/x86/CtsShimPriv.apk", + }, + x86_64: { + apk: "apk/x86/CtsShimPriv.apk", + }, + }, + presigned: true, +} + +//########################################################## +// Variant: System app + +android_app_import { + name: "CtsShimPrebuilt", + + // Make sure the build system doesn't try to resign the APK + dex_preopt: { + enabled: false, + }, + + arch: { + arm: { + apk: "apk/arm/CtsShim.apk", + }, + arm64: { + apk: "apk/arm/CtsShim.apk", + }, + x86: { + apk: "apk/x86/CtsShim.apk", + }, + x86_64: { + apk: "apk/x86/CtsShim.apk", + }, + }, + presigned: true, +} diff --git a/packages/CtsShim/Android.mk b/packages/CtsShim/Android.mk deleted file mode 100644 index 12972f14514b..000000000000 --- a/packages/CtsShim/Android.mk +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -LOCAL_PATH := $(call my-dir) - -########################################################### -# Variant: Privileged app - -include $(CLEAR_VARS) - -LOCAL_MODULE := CtsShimPrivPrebuilt -LOCAL_MODULE_TAGS := optional -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MODULE_CLASS := APPS -LOCAL_BUILT_MODULE_STEM := package.apk -# Make sure the build system doesn't try to resign the APK -LOCAL_CERTIFICATE := PRESIGNED -LOCAL_DEX_PREOPT := false -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 - -LOCAL_SRC_FILES_arm := apk/arm/CtsShimPriv.apk -LOCAL_SRC_FILES_arm64 := apk/arm/CtsShimPriv.apk -LOCAL_SRC_FILES_x86 := apk/x86/CtsShimPriv.apk -LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShimPriv.apk - -include $(BUILD_PREBUILT) - - -########################################################### -# Variant: System app - -include $(CLEAR_VARS) - -LOCAL_MODULE := CtsShimPrebuilt -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := APPS -LOCAL_BUILT_MODULE_STEM := package.apk -# Make sure the build system doesn't try to resign the APK -LOCAL_CERTIFICATE := PRESIGNED -LOCAL_DEX_PREOPT := false -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 - -LOCAL_SRC_FILES_arm := apk/arm/CtsShim.apk -LOCAL_SRC_FILES_arm64 := apk/arm/CtsShim.apk -LOCAL_SRC_FILES_x86 := apk/x86/CtsShim.apk -LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShim.apk - -include $(BUILD_PREBUILT) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp new file mode 100644 index 000000000000..ede1fab64973 --- /dev/null +++ b/packages/CtsShim/build/Android.bp @@ -0,0 +1,117 @@ +// Copyright (C) 2019 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. + +// Build rules to build shim apks. + +//########################################################## +// Variant: Privileged app upgrade + +android_app { + name: "CtsShimPrivUpgrade", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: "shim_priv_upgrade/AndroidManifest.xml", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], +} + +genrule { + name: "generate_priv_manifest", + srcs: [ + "shim_priv/AndroidManifest.xml", + ":CtsShimPrivUpgrade" + ], + out: ["AndroidManifest.xml"], + cmd: "sed -e s/__HASH__/`sha512sum -b $(location :CtsShimPrivUpgrade) | cut -d' ' -f1`/ $(location shim_priv/AndroidManifest.xml) > $(out)", +} + +//########################################################## +// Variant: Privileged app + +android_app { + name: "CtsShimPriv", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: ":generate_priv_manifest", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], + // Explicitly uncompress native libs rather than letting the build system doing it and destroy the + // v2/v3 signature. + use_embedded_native_libs: true, +} + +//########################################################## +// Variant: Privileged app upgrade w/ the wrong SHA + +android_app { + name: "CtsShimPrivUpgradeWrongSHA", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + // anything to make this package's SHA different from CtsShimPrivUpgrade + aaptflags: [ + "--version-name", + "WrongSHA", + ], + + manifest: "shim_priv_upgrade/AndroidManifest.xml", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], + +} + +//########################################################## +// Variant: System app + +android_app { + name: "CtsShim", + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: "shim/AndroidManifest.xml", +} diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk deleted file mode 100644 index 03eb0d9aad5a..000000000000 --- a/packages/CtsShim/build/Android.mk +++ /dev/null @@ -1,116 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -LOCAL_PATH := $(my-dir) - -########################################################### -# Variant: Privileged app upgrade - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShimPrivUpgrade - -LOCAL_MANIFEST_FILE := shim_priv_upgrade/AndroidManifest.xml - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -include $(BUILD_PACKAGE) -my_shim_priv_upgrade_apk := $(LOCAL_BUILT_MODULE) - -########################################################### -# Variant: Privileged app - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShimPriv - -# Generate the upgrade key by taking the hash of the built CtsShimPrivUpgrade apk -gen := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,true)/AndroidManifest.xml -$(gen): PRIVATE_CUSTOM_TOOL = sed -e "s/__HASH__/`sha512sum $(PRIVATE_INPUT_APK) | cut -d' ' -f1`/" $< >$@ -$(gen): PRIVATE_INPUT_APK := $(my_shim_priv_upgrade_apk) -$(gen): $(LOCAL_PATH)/shim_priv/AndroidManifest.xml $(my_shim_priv_upgrade_apk) - $(transform-generated-source) - -my_shim_priv_upgrade_apk := - -LOCAL_FULL_MANIFEST_FILE := $(gen) - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -LOCAL_USE_AAPT2 := true - -include $(BUILD_PACKAGE) - -########################################################### -# Variant: Privileged app upgrade w/ the wrong SHA - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false -# anything to make this package's SHA different from CtsShimPrivUpgrade -LOCAL_AAPT_FLAGS := --version-name WrongSHA - -LOCAL_PACKAGE_NAME := CtsShimPrivUpgradeWrongSHA - -LOCAL_MANIFEST_FILE := shim_priv_upgrade/AndroidManifest.xml - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -include $(BUILD_PACKAGE) - - -########################################################### -# Variant: System app - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShim - -LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml - -LOCAL_USE_AAPT2 := true - -include $(BUILD_PACKAGE) - -########################################################### -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 738c4257d2c5..19ae97070188 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -102,9 +102,10 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { Thread thread = new Thread( () -> { - mDynSystem.startInstallation("userdata", mUserdataSize, false); + mDynSystem.startInstallation(); + mDynSystem.createPartition("userdata", mUserdataSize, false); mInstallationSession = - mDynSystem.startInstallation("system", mSystemSize, true); + mDynSystem.createPartition("system", mSystemSize, true); }); thread.start(); @@ -157,6 +158,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { reportedInstalledSize = installedSize; } } + mDynSystem.finishInstallation(); return null; } catch (Exception e) { diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java index bc5a2c05e379..69bd0ed0c59c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java @@ -29,6 +29,8 @@ import android.system.StructUtsname; import android.telephony.PhoneNumberUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; +import android.text.BidiFormatter; +import android.text.TextDirectionHeuristics; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; @@ -206,4 +208,15 @@ public class DeviceInfoUtils { return sb.toString(); } + /** + * To get the formatting text for display in a potentially opposite-directionality context + * without garbling. + * @param subscriptionInfo {@link SubscriptionInfo} subscription information. + * @return Returns phone number with Bidi format. + */ + public static String getBidiFormattedPhoneNumber(Context context, + SubscriptionInfo subscriptionInfo) { + final String phoneNumber = getFormattedPhoneNumber(context, subscriptionInfo); + return BidiFormatter.getInstance().unicodeWrap(phoneNumber, TextDirectionHeuristics.LTR); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 9a95288a69ae..ec5bc96f574c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -363,12 +363,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> /** * Get name from remote device - * @return {@link BluetoothDevice#getAliasName()} if - * {@link BluetoothDevice#getAliasName()} is not null otherwise return + * @return {@link BluetoothDevice#getAlias()} if + * {@link BluetoothDevice#getAlias()} is not null otherwise return * {@link BluetoothDevice#getAddress()} */ public String getName() { - final String aliasName = mDevice.getAliasName(); + final String aliasName = mDevice.getAlias(); return TextUtils.isEmpty(aliasName) ? getAddress() : aliasName; } @@ -426,7 +426,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> * @return true if device's alias name is not null nor empty, false otherwise */ public boolean hasHumanReadableName() { - return !TextUtils.isEmpty(mDevice.getAliasName()); + return !TextUtils.isEmpty(mDevice.getAlias()); } /** @@ -573,7 +573,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } if (BluetoothUtils.D) { - Log.e(TAG, "updating profiles for " + mDevice.getAliasName() + ", " + mDevice); + Log.e(TAG, "updating profiles for " + mDevice.getAlias() + ", " + mDevice); BluetoothClass bluetoothClass = mDevice.getBluetoothClass(); if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString()); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index 33e754044873..7050db14bfb1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -166,7 +166,7 @@ public class CachedBluetoothDeviceManager { return cachedDevice.getName(); } - String name = device.getAliasName(); + String name = device.getAlias(); if (name != null) { return name; } diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index ea3c1d95925c..092cbf3c7c12 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -222,7 +222,8 @@ public class DataUsageController { } } - return TelephonyManager.from(mContext).createForSubscriptionId(subscriptionId); + return mContext.getSystemService( + TelephonyManager.class).createForSubscriptionId(subscriptionId); } public void setMobileDataEnabled(boolean enabled) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS index d5d2e9e8c146..f506b7c12d81 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS @@ -1,7 +1,7 @@ # Default reviewers for this and subdirectories. +qal@google.com +arcwang@google.com +govenliu@google.com asapperstein@google.com -asargent@google.com -dling@google.com -zhfan@google.com # Emergency approvers in case the above are not available
\ No newline at end of file diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java index dc47de8546db..c37509b55f7f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java @@ -95,9 +95,9 @@ public class CachedBluetoothDeviceManagerTest { when(mDevice1.getName()).thenReturn(DEVICE_NAME_1); when(mDevice2.getName()).thenReturn(DEVICE_NAME_2); when(mDevice3.getName()).thenReturn(DEVICE_NAME_3); - when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1); - when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2); - when(mDevice3.getAliasName()).thenReturn(DEVICE_ALIAS_3); + when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1); + when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2); + when(mDevice3.getAlias()).thenReturn(DEVICE_ALIAS_3); when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1); when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2); when(mDevice3.getBluetoothClass()).thenReturn(DEVICE_CLASS_2); @@ -224,7 +224,7 @@ public class CachedBluetoothDeviceManagerTest { assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1); final String newAliasName = "NewAliasName"; - when(mDevice1.getAliasName()).thenReturn(newAliasName); + when(mDevice1.getAlias()).thenReturn(newAliasName); mCachedDeviceManager.onDeviceNameUpdated(mDevice1); assertThat(cachedDevice1.getName()).isEqualTo(newAliasName); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 93dcbfeab172..999916d39cd0 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -699,7 +699,7 @@ public class CachedBluetoothDeviceTest { @Test public void deviceName_testAliasNameAvailable() { - when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS); + when(mDevice.getAlias()).thenReturn(DEVICE_ALIAS); when(mDevice.getName()).thenReturn(DEVICE_NAME); CachedBluetoothDevice cachedBluetoothDevice = new CachedBluetoothDevice(mContext, mProfileManager, mDevice); @@ -722,7 +722,7 @@ public class CachedBluetoothDeviceTest { @Test public void deviceName_testRenameDevice() { final String[] alias = {DEVICE_ALIAS}; - doAnswer(invocation -> alias[0]).when(mDevice).getAliasName(); + doAnswer(invocation -> alias[0]).when(mDevice).getAlias(); doAnswer(invocation -> { alias[0] = (String) invocation.getArguments()[0]; return true; @@ -839,14 +839,14 @@ public class CachedBluetoothDeviceTest { @Test public void getName_aliasNameNotNull_returnAliasName() { - when(mDevice.getAliasName()).thenReturn(DEVICE_NAME); + when(mDevice.getAlias()).thenReturn(DEVICE_NAME); assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME); } @Test public void getName_aliasNameIsNull_returnAddress() { - when(mDevice.getAliasName()).thenReturn(null); + when(mDevice.getAlias()).thenReturn(null); assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS); } @@ -854,7 +854,7 @@ public class CachedBluetoothDeviceTest { @Test public void setName_setDeviceNameIsNotNull() { final String name = "test name"; - when(mDevice.getAliasName()).thenReturn(DEVICE_NAME); + when(mDevice.getAlias()).thenReturn(DEVICE_NAME); mCachedDevice.setName(name); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java index 2b5466c4161f..7be176a37bb4 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java @@ -75,8 +75,8 @@ public class HearingAidDeviceManagerTest { when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2); when(mDevice1.getName()).thenReturn(DEVICE_NAME_1); when(mDevice2.getName()).thenReturn(DEVICE_NAME_2); - when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1); - when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2); + when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1); + when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2); when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS); when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS); when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java index 3da5e766c389..f7bee30a087f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java @@ -75,7 +75,7 @@ public class DataUsageControllerTest { public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) .thenReturn(mSubscriptionManager); when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); diff --git a/packages/SystemUI/legacy/recents/res/values/config.xml b/packages/SystemUI/legacy/recents/res/values/config.xml index 2ff9abf4003d..0fbb623d2ba0 100644 --- a/packages/SystemUI/legacy/recents/res/values/config.xml +++ b/packages/SystemUI/legacy/recents/res/values/config.xml @@ -26,6 +26,14 @@ (package/class) --> <string name="config_recentsComponent" translatable="false">com.android.systemui.recents.LegacyRecentsImpl</string> + <!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents --> + <string-array name="config_systemUIServiceComponentsPerUser" translatable="false"> + <item>com.android.systemui.Dependency$DependencyCreator</item> + <item>com.android.systemui.util.NotificationChannels</item> + <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item> + <item>com.android.systemui.recents.Recents</item> + </string-array> + <!-- Whether recents should use hardware layers for its taskviews. This flag can be enabled for devices where the java drawing of round rects may be slow --> <bool name="config_recents_use_hardware_layers">false</bool> diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java index a150de95fcf0..a572110c6b9d 100644 --- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java +++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java @@ -195,6 +195,7 @@ public class LegacyRecentsImpl implements RecentsImplementation { mContext.getColor(R.color.recents_task_bar_default_background_color); final int defaultTaskViewBackgroundColor = mContext.getColor(R.color.recents_task_view_default_background_color); + getComponent(Recents.class).putComponent(LegacyRecentsImpl.class, this); sDebugFlags = new RecentsDebugFlags(); sSystemServicesProxy = SystemServicesProxy.getInstance(mContext); sConfiguration = new RecentsConfiguration(mContext); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index 689d161c2ee8..239addd4ee1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -208,11 +208,9 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, @Override public void onDarkChanged(Rect area, float darkIntensity, int tint) { - if (!isInArea(area, this)) { - return; - } + float intensity = isInArea(area, this) ? darkIntensity : 0; mMobileDrawable.setTintList( - ColorStateList.valueOf(mDualToneHandler.getSingleColor(darkIntensity))); + ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity))); ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint)); mIn.setImageTintList(color); mOut.setImageTintList(color); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java index 23e2d277034d..6dbcc44e385b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java @@ -236,15 +236,13 @@ public class StatusBarWifiView extends FrameLayout implements DarkReceiver, @Override public void onDarkChanged(Rect area, float darkIntensity, int tint) { - if (!isInArea(area, this)) { - return; - } - - mWifiIcon.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint))); - mIn.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint))); - mOut.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint))); - mDotView.setDecorColor(tint); - mDotView.setIconColor(tint, false); + int areaTint = getTint(area, this, tint); + ColorStateList color = ColorStateList.valueOf(areaTint); + mWifiIcon.setImageTintList(color); + mIn.setImageTintList(color); + mOut.setImageTintList(color); + mDotView.setDecorColor(areaTint); + mDotView.setIconColor(areaTint, false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index db2be0e78e9a..f73ca1c36005 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -21,20 +21,24 @@ import static com.android.systemui.Dependency.MAIN_HANDLER_NAME; import android.app.ActivityManager; import android.content.Context; import android.net.ConnectivityManager; +import android.net.wifi.WifiClient; import android.net.wifi.WifiManager; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.UserManager; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; /** + * Controller used to retrieve information related to a hotspot. */ @Singleton public class HotspotControllerImpl implements HotspotController, WifiManager.SoftApCallback { @@ -49,10 +53,11 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof private final Context mContext; private int mHotspotState; - private int mNumConnectedDevices; + private volatile int mNumConnectedDevices; private boolean mWaitingForTerminalState; /** + * Controller used to retrieve information related to a hotspot. */ @Inject public HotspotControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler) { @@ -96,7 +101,6 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof /** * Adds {@code callback} to the controller. The controller will update the callback on state * changes. It will immediately trigger the callback added to notify current state. - * @param callback */ @Override public void addCallback(Callback callback) { @@ -106,13 +110,16 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof mCallbacks.add(callback); if (mWifiManager != null) { if (mCallbacks.size() == 1) { - mWifiManager.registerSoftApCallback(this, mMainHandler); + mWifiManager.registerSoftApCallback(this, + new HandlerExecutor(mMainHandler)); } else { - // mWifiManager#registerSoftApCallback triggers a call to onNumClientsChanged - // on the Main Handler. In order to always update the callback on added, we - // make this call when adding callbacks after the first. + // mWifiManager#registerSoftApCallback triggers a call to + // onConnectedClientsChanged on the Main Handler. In order to always update + // the callback on added, we make this call when adding callbacks after the + // first. mMainHandler.post(() -> - callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices)); + callback.onHotspotChanged(isHotspotEnabled(), + mNumConnectedDevices)); } } } @@ -217,8 +224,8 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof } @Override - public void onNumClientsChanged(int numConnectedDevices) { - mNumConnectedDevices = numConnectedDevices; + public void onConnectedClientsChanged(List<WifiClient> clients) { + mNumConnectedDevices = clients.size(); fireHotspotChangedCallback(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index e75365e66f81..c519f5694e5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -22,6 +22,8 @@ import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; +import android.telephony.CellSignalStrength; +import android.telephony.CellSignalStrengthCdma; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -48,6 +50,7 @@ import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionD import java.io.PrintWriter; import java.util.BitSet; import java.util.Objects; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -457,6 +460,18 @@ public class MobileSignalController extends SignalController< } /** + * Extracts the CellSignalStrengthCdma from SignalStrength then returns the level + */ + private final int getCdmaLevel() { + List<CellSignalStrengthCdma> signalStrengthCdma = + mSignalStrength.getCellSignalStrengths(CellSignalStrengthCdma.class); + if (!signalStrengthCdma.isEmpty()) { + return signalStrengthCdma.get(0).getLevel(); + } + return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + } + + /** * Updates the current state based on mServiceState, mSignalStrength, mDataNetType, * mDataState, and mSimState. It should be called any time one of these is updated. * This will call listeners if necessary. @@ -470,7 +485,7 @@ public class MobileSignalController extends SignalController< && mSignalStrength != null; if (mCurrentState.connected) { if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { - mCurrentState.level = mSignalStrength.getCdmaLevel(); + mCurrentState.level = getCdmaLevel(); } else { mCurrentState.level = mSignalStrength.getLevel(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java index 3e4c4d6a7a8a..7496e3ade351 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java @@ -42,6 +42,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; +import java.util.ArrayList; +import java.util.concurrent.Executor; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -67,10 +70,11 @@ public class HotspotControllerImplTest extends SysuiTestCase { mContext.addMockSystemService(WifiManager.class, mWifiManager); doAnswer((InvocationOnMock invocation) -> { - ((WifiManager.SoftApCallback) invocation.getArgument(0)).onNumClientsChanged(1); + ((WifiManager.SoftApCallback) invocation.getArgument(0)) + .onConnectedClientsChanged(new ArrayList<>()); return null; }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class), - any(Handler.class)); + any(Executor.class)); mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper())); } diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 2bfe287c82b3..61bfb92363bd 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -27,6 +27,7 @@ java_defaults { "androidx.annotation_annotation", "netd_aidl_interface-java", "networkstack-aidl-interfaces-java", + "android.hardware.tetheroffload.control-V1.0-java", "tethering-client", ], manifest: "AndroidManifestBase.xml", @@ -38,11 +39,39 @@ android_library { defaults: ["TetheringAndroidLibraryDefaults"], } +cc_library_shared { + name: "libtetheroffloadjni", + srcs: [ + "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp", + ], + shared_libs: [ + "libnativehelper", + "libcutils", + "android.hardware.tetheroffload.config@1.0", + ], + static_libs: [ + "liblog", + "libbase", + "libhidlbase", + "libutils", + ], + + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], +} + // Common defaults for compiling the actual APK. java_defaults { name: "TetheringAppDefaults", platform_apis: true, privileged: true, + jni_libs: [ + "libtetheroffloadjni", + ], resource_dirs: [ "res", ], @@ -71,7 +100,10 @@ filegroup { name: "tethering-servicescore-srcs", srcs: [ "src/com/android/server/connectivity/tethering/EntitlementManager.java", + "src/com/android/server/connectivity/tethering/OffloadController.java", + "src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java", "src/com/android/server/connectivity/tethering/TetheringConfiguration.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java", ], } @@ -84,5 +116,14 @@ filegroup { "src/android/net/ip/IpServer.java", "src/android/net/ip/RouterAdvertisementDaemon.java", "src/android/net/util/InterfaceSet.java", + "src/android/net/util/PrefixUtils.java", + ], +} + +// This group would be removed when tethering migration is done. +filegroup { + name: "tethering-jni-srcs", + srcs: [ + "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp", ], } diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml index b9cac1994359..dc013da33869 100644 --- a/packages/Tethering/AndroidManifestBase.xml +++ b/packages/Tethering/AndroidManifestBase.xml @@ -23,7 +23,6 @@ <application android:label="Tethering" android:defaultToDeviceProtectedStorage="true" - android:directBootAware="true" - android:usesCleartextTraffic="true"> + android:directBootAware="true"> </application> </manifest> diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp index 3eaf48845a2f..3eaf48845a2f 100644 --- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp +++ b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp diff --git a/services/net/java/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java index f60694aaedc9..f203e9995f3d 100644 --- a/services/net/java/android/net/util/PrefixUtils.java +++ b/packages/Tethering/src/android/net/util/PrefixUtils.java @@ -42,16 +42,19 @@ public class PrefixUtils { public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24"); + /** Get non forwardable prefixes. */ public static Set<IpPrefix> getNonForwardablePrefixes() { final HashSet<IpPrefix> prefixes = new HashSet<>(); addNonForwardablePrefixes(prefixes); return prefixes; } + /** Add non forwardable prefixes. */ public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) { Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES); } + /** Get local prefixes from |lp|. */ public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) { final HashSet<IpPrefix> localPrefixes = new HashSet<>(); if (lp == null) return localPrefixes; @@ -66,10 +69,12 @@ public class PrefixUtils { return localPrefixes; } + /** Convert LinkAddress |addr| to IpPrefix. */ public static IpPrefix asIpPrefix(LinkAddress addr) { return new IpPrefix(addr.getAddress(), addr.getPrefixLength()); } + /** Convert InetAddress |ip| to IpPrefix. */ public static IpPrefix ipAddressAsPrefix(InetAddress ip) { final int bitLength = (ip instanceof Inet4Address) ? NetworkConstants.IPV4_ADDR_BITS diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java index a3c299814a7a..16734d83e3aa 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java @@ -36,8 +36,8 @@ import android.net.netlink.NetlinkSocket; import android.net.util.IpUtils; import android.net.util.SharedLog; import android.os.Handler; -import android.os.Looper; import android.os.INetworkManagementService; +import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; @@ -60,7 +60,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; /** * A class to encapsulate the business logic of programming the tethering @@ -74,7 +73,7 @@ public class OffloadController { private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); - private static enum UpdateType { IF_NEEDED, FORCE }; + private enum UpdateType { IF_NEEDED, FORCE }; private final Handler mHandler; private final OffloadHardwareInterface mHwInterface; @@ -128,6 +127,7 @@ public class OffloadController { } } + /** Start hardware offload. */ public boolean start() { if (started()) return true; @@ -235,6 +235,7 @@ public class OffloadController { return isStarted; } + /** Stop hardware offload. */ public void stop() { // Completely stops tethering offload. After this method is called, it is no longer safe to // call any HAL method, no callbacks from the hardware will be delivered, and any in-flight @@ -258,7 +259,9 @@ public class OffloadController { // getTetherStats() is the only function in OffloadController that can be called from // a different thread. Do not attempt to update stats by querying the offload HAL // synchronously from a different thread than our Handler thread. http://b/64771555. - Runnable updateStats = () -> { updateStatsForCurrentUpstream(); }; + Runnable updateStats = () -> { + updateStatsForCurrentUpstream(); + }; if (Looper.myLooper() == mHandler.getLooper()) { updateStats.run(); } else { @@ -358,6 +361,7 @@ public class OffloadController { } } + /** Set current tethering upstream LinkProperties. */ public void setUpstreamLinkProperties(LinkProperties lp) { if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return; @@ -376,6 +380,7 @@ public class OffloadController { pushUpstreamParameters(prevUpstream); } + /** Set local prefixes. */ public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { mExemptPrefixes = localPrefixes; @@ -383,6 +388,7 @@ public class OffloadController { computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); } + /** Update current downstream LinkProperties. */ public void notifyDownstreamLinkProperties(LinkProperties lp) { final String ifname = lp.getInterfaceName(); final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp)); @@ -421,6 +427,7 @@ public class OffloadController { } } + /** Remove downstream interface from offload hardware. */ public void removeDownstreamInterface(String ifname) { final LinkProperties lp = mDownstreams.remove(ifname); if (lp == null) return; @@ -481,7 +488,7 @@ public class OffloadController { iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways)); if (!success) { - return success; + return success; } // Update stats after we've told the hardware to change routing so we don't miss packets. @@ -545,6 +552,7 @@ public class OffloadController { return false; } + /** Dump information. */ public void dump(IndentingPrintWriter pw) { if (isOffloadDisabled()) { pw.println("Offload disabled"); @@ -630,7 +638,7 @@ public class OffloadController { if (ip instanceof Inet4Address) { return (Inet4Address) ip; } - } catch (IllegalArgumentException iae) {} + } catch (IllegalArgumentException iae) { } return null; } diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java index 207f86762b95..01339a4a2c33 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java @@ -23,9 +23,9 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; +import android.net.util.SharedLog; import android.os.Handler; import android.os.RemoteException; -import android.net.util.SharedLog; import android.system.OsConstants; import java.util.ArrayList; @@ -55,18 +55,34 @@ public class OffloadHardwareInterface { private TetheringOffloadCallback mTetheringOffloadCallback; private ControlCallback mControlCallback; + /** The callback to notify status of offload management process. */ public static class ControlCallback { + /** Offload started. */ public void onStarted() {} + /** + * Offload stopped because an error has occurred in lower layer. + */ public void onStoppedError() {} + /** + * Offload stopped because the device has moved to a bearer on which hardware offload is + * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will + * likely fail and cannot be presumed to be saved inside of the hardware management process. + * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin + * offload again. + */ public void onStoppedUnsupported() {} + /** Indicate that offload is able to proivde support for this time. */ public void onSupportAvailable() {} + /** Offload stopped because of usage limit reached. */ public void onStoppedLimitReached() {} + /** Indicate to update NAT timeout. */ public void onNatTimeoutUpdate(int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) {} } + /** The object which records Tx/Rx forwarded bytes. */ public static class ForwardedStats { public long rxBytes; public long txBytes; @@ -76,11 +92,13 @@ public class OffloadHardwareInterface { txBytes = 0; } + /** Add Tx/Rx bytes. */ public void add(ForwardedStats other) { rxBytes += other.rxBytes; txBytes += other.txBytes; } + /** Returns the string representation of this object. */ public String toString() { return String.format("rx:%s tx:%s", rxBytes, txBytes); } @@ -91,14 +109,17 @@ public class OffloadHardwareInterface { mLog = log.forSubComponent(TAG); } + /** Get default value indicating whether offload is supported. */ public int getDefaultTetherOffloadDisabled() { return DEFAULT_TETHER_OFFLOAD_DISABLED; } + /** Configure offload management process. */ public boolean initOffloadConfig() { return configOffload(); } + /** Initialize the tethering offload HAL. */ public boolean initOffloadControl(ControlCallback controlCb) { mControlCallback = controlCb; @@ -125,8 +146,8 @@ public class OffloadHardwareInterface { mOffloadControl.initOffload( mTetheringOffloadCallback, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -134,9 +155,10 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } + /** Stop IOffloadControl. */ public void stopOffloadControl() { if (mOffloadControl != null) { try { @@ -154,6 +176,7 @@ public class OffloadHardwareInterface { mLog.log("stopOffloadControl()"); } + /** Get Tx/Rx usage from last query. */ public ForwardedStats getForwardedStats(String upstream) { final String logmsg = String.format("getForwardedStats(%s)", upstream); @@ -174,6 +197,7 @@ public class OffloadHardwareInterface { return stats; } + /** Set local prefixes to offload management process. */ public boolean setLocalPrefixes(ArrayList<String> localPrefixes) { final String logmsg = String.format("setLocalPrefixes([%s])", String.join(",", localPrefixes)); @@ -182,8 +206,8 @@ public class OffloadHardwareInterface { try { mOffloadControl.setLocalPrefixes(localPrefixes, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -191,9 +215,10 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } + /** Set data limit value to offload management process. */ public boolean setDataLimit(String iface, long limit) { final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit); @@ -203,8 +228,8 @@ public class OffloadHardwareInterface { mOffloadControl.setDataLimit( iface, limit, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -212,9 +237,10 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } + /** Set upstream parameters to offload management process. */ public boolean setUpstreamParameters( String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) { iface = (iface != null) ? iface : NO_INTERFACE_NAME; @@ -230,8 +256,8 @@ public class OffloadHardwareInterface { mOffloadControl.setUpstreamParameters( iface, v4addr, v4gateway, v6gws, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -239,9 +265,10 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } + /** Add downstream prefix to offload management process. */ public boolean addDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix); @@ -249,8 +276,8 @@ public class OffloadHardwareInterface { try { mOffloadControl.addDownstream(ifname, prefix, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -258,9 +285,10 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } + /** Remove downstream prefix from offload management process. */ public boolean removeDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix); @@ -268,8 +296,8 @@ public class OffloadHardwareInterface { try { mOffloadControl.removeDownstream(ifname, prefix, (boolean success, String errMsg) -> { - results.success = success; - results.errMsg = errMsg; + results.mSuccess = success; + results.mErrMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); @@ -277,7 +305,7 @@ public class OffloadHardwareInterface { } record(logmsg, results); - return results.success; + return results.mSuccess; } private void record(String msg, Throwable t) { @@ -286,7 +314,7 @@ public class OffloadHardwareInterface { private void record(String msg, CbResults results) { final String logmsg = msg + YIELDS + results; - if (!results.success) { + if (!results.mSuccess) { mLog.e(logmsg); } else { mLog.log(logmsg); @@ -298,7 +326,7 @@ public class OffloadHardwareInterface { public final ControlCallback controlCb; public final SharedLog log; - public TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) { + TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) { handler = h; controlCb = cb; log = sharedLog; @@ -332,7 +360,7 @@ public class OffloadHardwareInterface { @Override public void updateTimeout(NatTimeoutUpdate params) { handler.post(() -> { - controlCb.onNatTimeoutUpdate( + controlCb.onNatTimeoutUpdate( networkProtocolToOsConstant(params.proto), params.src.addr, uint16(params.src.port), params.dst.addr, uint16(params.dst.port)); @@ -352,15 +380,15 @@ public class OffloadHardwareInterface { } private static class CbResults { - boolean success; - String errMsg; + boolean mSuccess; + String mErrMsg; @Override public String toString() { - if (success) { + if (mSuccess) { return "ok"; } else { - return "fail: " + errMsg; + return "fail: " + mErrMsg; } } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java index 77097271c454..cf0e3b2ddda7 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -251,7 +251,7 @@ public class TetheringConfiguration { /** Check whether dun is required. */ public static boolean checkDunRequired(Context ctx, int id) { final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); - return (tm != null) ? tm.getTetherApnRequired(id) : false; + return (tm != null) ? tm.isTetherApnRequired(id) : false; } private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 3a9e21f943d8..9769596ab1d0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -146,6 +146,7 @@ public class UpstreamNetworkMonitor { } } + /** Listen all networks. */ public void startObserveAllNetworks() { stop(); @@ -155,6 +156,13 @@ public class UpstreamNetworkMonitor { cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); } + /** + * Stop tracking candidate tethering upstreams and release mobile network request. + * Note: this function is used when tethering is stopped because tethering do not need to + * choose upstream anymore. But it would not stop default network tracking because + * EntitlementManager may need to know default network to decide whether to request entitlement + * check even tethering is not active yet. + */ public void stop() { releaseMobileNetworkRequest(); @@ -165,6 +173,7 @@ public class UpstreamNetworkMonitor { mNetworkMap.clear(); } + /** Setup or teardown DUN connection according to |dunRequired|. */ public void updateMobileRequiresDun(boolean dunRequired) { final boolean valueChanged = (mDunRequired != dunRequired); mDunRequired = dunRequired; @@ -174,10 +183,12 @@ public class UpstreamNetworkMonitor { } } + /** Whether mobile network is requested. */ public boolean mobileNetworkRequested() { return (mMobileNetworkCallback != null); } + /** Request mobile network if mobile upstream is permitted. */ public void registerMobileNetworkRequest() { if (!isCellularUpstreamPermitted()) { mLog.i("registerMobileNetworkRequest() is not permitted"); @@ -209,6 +220,7 @@ public class UpstreamNetworkMonitor { cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler); } + /** Release mobile network request. */ public void releaseMobileNetworkRequest() { if (mMobileNetworkCallback == null) return; @@ -221,6 +233,9 @@ public class UpstreamNetworkMonitor { // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). + /** + * Select the first available network from |perferredTypes|. + */ public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); @@ -254,7 +269,11 @@ public class UpstreamNetworkMonitor { return typeStatePair.ns; } - // Returns null if no current upstream available. + /** + * Get current preferred upstream network. If default network is cellular and DUN is required, + * preferred upstream would be DUN otherwise preferred upstream is the same as default network. + * Returns null if no current upstream is available. + */ public NetworkState getCurrentPreferredUpstream() { final NetworkState dfltState = (mDefaultInternetNetwork != null) ? mNetworkMap.get(mDefaultInternetNetwork) @@ -270,10 +289,12 @@ public class UpstreamNetworkMonitor { return findFirstDunNetwork(mNetworkMap.values()); } + /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */ public void setCurrentUpstream(Network upstream) { mTetheringUpstreamNetwork = upstream; } + /** Return local prefixes. */ public Set<IpPrefix> getLocalPrefixes() { return (Set<IpPrefix>) mLocalPrefixes.clone(); } @@ -501,8 +522,8 @@ public class UpstreamNetworkMonitor { try { nc = ConnectivityManager.networkCapabilitiesForType(type); } catch (IllegalArgumentException iae) { - Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + - ConnectivityManager.getNetworkTypeName(type)); + Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + + ConnectivityManager.getNetworkTypeName(type)); continue; } if (!isCellularUpstreamPermitted && isCellular(nc)) { @@ -547,18 +568,18 @@ public class UpstreamNetworkMonitor { } private static boolean isCellular(NetworkCapabilities nc) { - return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) && - nc.hasCapability(NET_CAPABILITY_NOT_VPN); + return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) + && nc.hasCapability(NET_CAPABILITY_NOT_VPN); } private static boolean hasCapability(NetworkState ns, int netCap) { - return (ns != null) && (ns.networkCapabilities != null) && - ns.networkCapabilities.hasCapability(netCap); + return (ns != null) && (ns.networkCapabilities != null) + && ns.networkCapabilities.hasCapability(netCap); } private static boolean isNetworkUsableAndNotCellular(NetworkState ns) { - return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) && - !isCellular(ns.networkCapabilities); + return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) + && !isCellular(ns.networkCapabilities); } private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) { diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index 5564bd6ecbca..363be18a73bc 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -25,6 +25,7 @@ android_test { static_libs: [ "androidx.test.rules", "frameworks-base-testutils", + "net-tests-utils", "mockito-target-extended-minus-junit4", "TetheringApiCurrentLib", "testables", @@ -46,7 +47,9 @@ filegroup { name: "tethering-tests-src", srcs: [ "src/com/android/server/connectivity/tethering/EntitlementManagerTest.java", + "src/com/android/server/connectivity/tethering/OffloadControllerTest.java", "src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java", "src/android/net/dhcp/DhcpServingParamsParcelExtTest.java", "src/android/net/ip/IpServerTest.java", "src/android/net/util/InterfaceSetTest.java", diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java index 9931aec01487..8574f5401496 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java @@ -26,10 +26,10 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; import static com.android.testutils.MiscAssertsKt.assertContainsAll; +import static com.android.testutils.MiscAssertsKt.assertThrows; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; @@ -148,10 +148,8 @@ public class OffloadControllerTest { public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception { setupFunctioningHardwareInterface(); when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1); - try { - Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED); - fail(); - } catch (SettingNotFoundException expected) {} + assertThrows(SettingNotFoundException.class, () -> + Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); final OffloadController offload = makeOffloadController(); offload.start(); @@ -168,10 +166,8 @@ public class OffloadControllerTest { public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception { setupFunctioningHardwareInterface(); when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0); - try { - Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED); - fail(); - } catch (SettingNotFoundException expected) {} + assertThrows(SettingNotFoundException.class, () -> + Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); final OffloadController offload = makeOffloadController(); offload.start(); diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java index 9f9221f3010d..9c65c0deed07 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java @@ -145,7 +145,7 @@ public class TetheringConfigurationTest { @Test public void testDunFromTelephonyManagerMeansDun() { - when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(true); + when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(true); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -169,7 +169,7 @@ public class TetheringConfigurationTest { @Test public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { - when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -212,7 +212,7 @@ public class TetheringConfigurationTest { @Test public void testNoDefinedUpstreamTypesAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{}); - when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -235,7 +235,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn( new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -253,7 +253,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { when(mResources.getIntArray(config_tether_upstream_types)) .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java index 0d276cbd1b85..c028d6d9cadc 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java @@ -87,7 +87,7 @@ public class UpstreamNetworkMonitorTest { // Actual contents of the request don't matter for this test. The lack of // any specific TRANSPORT_* is sufficient to identify this request. - private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build(); + private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build(); @Mock private Context mContext; @Mock private EntitlementManager mEntitleMgr; @@ -140,7 +140,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testDefaultNetworkIsTracked() throws Exception { assertTrue(mCM.hasNoCallbacks()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertEquals(1, mCM.trackingDefault.size()); @@ -153,7 +153,7 @@ public class UpstreamNetworkMonitorTest { public void testListensForAllNetworks() throws Exception { assertTrue(mCM.listening.isEmpty()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertFalse(mCM.listening.isEmpty()); assertTrue(mCM.isListeningForAll()); @@ -164,9 +164,9 @@ public class UpstreamNetworkMonitorTest { @Test public void testCallbacksRegistered() { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); verify(mCM, times(1)).requestNetwork( - eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class)); + eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class)); mUNM.startObserveAllNetworks(); verify(mCM, times(1)).registerNetworkCallback( any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class)); @@ -191,7 +191,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -217,7 +217,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Try a few things that must not result in any state change. mUNM.registerMobileNetworkRequest(); @@ -226,7 +226,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class)); @@ -250,7 +250,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -266,17 +266,17 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.updateMobileRequiresDun(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Test going from DUN to no-DUN correctly re-registers callbacks. mUNM.updateMobileRequiresDun(false); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -287,7 +287,7 @@ public class UpstreamNetworkMonitorTest { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // There are no networks, so there is nothing to select. assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); @@ -369,7 +369,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testGetCurrentPreferredUpstream() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); mUNM.updateMobileRequiresDun(false); @@ -418,7 +418,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testLocalPrefixes() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // [0] Test minimum set of local prefixes. @@ -431,13 +431,13 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); final LinkProperties wifiLp = wifiAgent.linkProperties; wifiLp.setInterfaceName("wlan0"); - final String[] WIFI_ADDRS = { + final String[] wifi_addrs = { "fe80::827a:bfff:fe6f:374d", "100.112.103.18", "2001:db8:4:fd00:827a:bfff:fe6f:374d", "2001:db8:4:fd00:6dea:325a:fdae:4ef4", "fd6a:a640:60bf:e985::123", // ULA address for good measure. }; - for (String addrStr : WIFI_ADDRS) { + for (String addrStr : wifi_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/20"; wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -458,10 +458,10 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); final LinkProperties cellLp = cellAgent.linkProperties; cellLp.setInterfaceName("rmnet_data0"); - final String[] CELL_ADDRS = { + final String[] cell_addrs = { "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d", }; - for (String addrStr : CELL_ADDRS) { + for (String addrStr : cell_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; cellLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -481,10 +481,10 @@ public class UpstreamNetworkMonitorTest { dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); final LinkProperties dunLp = dunAgent.linkProperties; dunLp.setInterfaceName("rmnet_data1"); - final String[] DUN_ADDRS = { + final String[] dun_addrs = { "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d", }; - for (String addrStr : DUN_ADDRS) { + for (String addrStr : dun_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; dunLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -525,7 +525,7 @@ public class UpstreamNetworkMonitorTest { // Mobile has higher pirority than wifi. preferredTypes.add(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // Setup wifi and make wifi as default network. final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); @@ -556,6 +556,15 @@ public class UpstreamNetworkMonitorTest { mCM.legacyTypeMap.values().iterator().next()); } + private boolean isDunRequested() { + for (NetworkRequest req : mCM.requested.values()) { + if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { + return true; + } + } + return false; + } + public static class TestConnectivityManager extends ConnectivityManager { public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>(); public Set<NetworkCallback> trackingDefault = new HashSet<>(); @@ -598,17 +607,10 @@ public class UpstreamNetworkMonitorTest { return false; } - boolean isDunRequested() { - for (NetworkRequest req : requested.values()) { - if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { - return true; - } - } - return false; + int getNetworkId() { + return ++mNetworkId; } - int getNetworkId() { return ++mNetworkId; } - void makeDefaultNetwork(TestNetworkAgent agent) { if (Objects.equals(defaultNetwork, agent)) return; @@ -630,7 +632,7 @@ public class UpstreamNetworkMonitorTest { public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { assertFalse(allCallbacks.containsKey(cb)); allCallbacks.put(cb, h); - if (mDefaultRequest.equals(req)) { + if (sDefaultRequest.equals(req)) { assertFalse(trackingDefault.contains(cb)); trackingDefault.add(cb); } else { @@ -749,9 +751,13 @@ public class UpstreamNetworkMonitorTest { private final State mLoggingState = new LoggingState(); class LoggingState extends State { - @Override public void enter() { messages.clear(); } + @Override public void enter() { + messages.clear(); + } - @Override public void exit() { messages.clear(); } + @Override public void exit() { + messages.clear(); + } @Override public boolean processMessage(Message msg) { messages.add(msg); diff --git a/services/core/Android.bp b/services/core/Android.bp index fcf012cd3a6b..a05c2cc31e40 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -31,6 +31,7 @@ java_library_static { "android.hardware.light-V2.0-java", "android.hardware.power-V1.0-java", "android.hardware.tv.cec-V1.0-java", + "app-compat-annotations", ], required: [ @@ -49,12 +50,11 @@ java_library_static { "android.hardware.biometrics.fingerprint-V2.1-java", "android.hardware.oemlock-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", - "android.hardware.vibrator-V1.0-java", + "android.hardware.vibrator-V1.4-java", "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-V2-java", - "netd_aidl_interface-java", "netd_event_listener_interface-java", ], } diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java index 3a7b5d683507..207e007cc62f 100644 --- a/services/core/java/com/android/server/AppStateTracker.java +++ b/services/core/java/com/android/server/AppStateTracker.java @@ -700,14 +700,16 @@ public class AppStateTracker { Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId + (idle ? " idle" : " active") + " " + bucket); } - final boolean changed; - if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) { - changed = mExemptedPackages.add(userId, packageName); - } else { - changed = mExemptedPackages.remove(userId, packageName); - } - if (changed) { - mHandler.notifyExemptChanged(); + synchronized (mLock) { + final boolean changed; + if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) { + changed = mExemptedPackages.add(userId, packageName); + } else { + changed = mExemptedPackages.remove(userId, packageName); + } + if (changed) { + mHandler.notifyExemptChanged(); + } } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ce0e9e7e56cf..81eb4b355a21 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -97,6 +97,7 @@ import android.net.NetworkMonitorManager; import android.net.NetworkPolicyManager; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; @@ -2643,7 +2644,8 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: { - updateNetworkScore(nai, msg.arg1); + final NetworkScore ns = (NetworkScore) msg.obj; + updateNetworkScore(nai, ns); break; } case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { @@ -5594,9 +5596,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); + final NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, + ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver, mNMS, factorySerialNumber); // Make sure the network capabilities reflect what the agent info says. nai.setNetworkCapabilities(mixInCapabilities(nai, nc)); @@ -6729,7 +6733,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void updateNetworkScore(NetworkAgentInfo nai, int score) { + private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) { + int score = ns.getIntExtension(NetworkScore.LEGACY_SCORE); if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score); if (score < 0) { loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score + @@ -6738,7 +6743,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } final int oldScore = nai.getCurrentScore(); - nai.setCurrentScore(score); + nai.setNetworkScore(ns); rematchAllNetworksAndRequests(nai, oldScore); diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index 190e6cf2d35c..7b02b6e0ac11 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -18,7 +18,6 @@ package com.android.server; import android.content.Context; import android.content.pm.PackageManager; -import android.gsi.GsiInstallParams; import android.gsi.GsiProgress; import android.gsi.IGsiService; import android.gsi.IGsid; @@ -47,6 +46,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements private static final int GSID_ROUGH_TIMEOUT_MS = 8192; private static final String PATH_DEFAULT = "/data/gsi"; private Context mContext; + private String mInstallPath; private volatile IGsiService mGsiService; DynamicSystemService(Context context) { @@ -115,8 +115,8 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements } @Override - public boolean startInstallation(String name, long size, boolean readOnly) - throws RemoteException { + public boolean startInstallation() throws RemoteException { + IGsiService service = getGsiService(); // priority from high to low: sysprop -> sdcard -> /data String path = SystemProperties.get("os.aot.path"); if (path.isEmpty()) { @@ -138,14 +138,19 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements } Slog.i(TAG, "startInstallation -> " + path); } + mInstallPath = path; + if (service.openInstall(path) != 0) { + Slog.i(TAG, "Failed to open " + path); + return false; + } + return true; + } + + @Override + public boolean createPartition(String name, long size, boolean readOnly) + throws RemoteException { IGsiService service = getGsiService(); - GsiInstallParams installParams = new GsiInstallParams(); - installParams.installDir = path; - installParams.name = name; - installParams.size = size; - installParams.wipe = readOnly; - installParams.readOnly = readOnly; - if (service.beginGsiInstall(installParams) != 0) { + if (service.createPartition(name, size, readOnly) != 0) { Slog.i(TAG, "Failed to install " + name); return false; } @@ -153,6 +158,16 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements } @Override + public boolean finishInstallation() throws RemoteException { + IGsiService service = getGsiService(); + if (service.closeInstall() != 0) { + Slog.i(TAG, "Failed to finish installation"); + return false; + } + return true; + } + + @Override public GsiProgress getInstallationProgress() throws RemoteException { return getGsiService().getInstallProgress(); } @@ -190,6 +205,8 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements @Override public boolean remove() throws RemoteException { + IGsiService gsiService = getGsiService(); + String install_dir = gsiService.getInstalledGsiImageDir(); return getGsiService().removeGsi(); } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 14678884e8e2..447ed59a775e 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -33,6 +33,9 @@ import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; +import android.telephony.Annotation.DataFailureCause; +import android.telephony.Annotation.RadioPowerState; +import android.telephony.Annotation.SrvccState; import android.telephony.CallAttributes; import android.telephony.CallQuality; import android.telephony.CellInfo; @@ -245,7 +248,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - @TelephonyManager.RadioPowerState + @RadioPowerState private int mRadioPowerState = TelephonyManager.RADIO_POWER_UNAVAILABLE; private final LocalLog mLocalLog = new LocalLog(100); @@ -961,13 +964,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - public void notifyCallState(int state, String phoneNumber) { + public void notifyCallStateForAllSubs(int state, String phoneNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } if (VDBG) { - log("notifyCallState: state=" + state + " phoneNumber=" + phoneNumber); + log("notifyCallStateForAllSubs: state=" + state + " phoneNumber=" + phoneNumber); } synchronized (mRecords) { @@ -994,13 +997,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { SubscriptionManager.INVALID_SUBSCRIPTION_ID); } - public void notifyCallStateForPhoneId(int phoneId, int subId, int state, - String incomingNumber) { + public void notifyCallState(int phoneId, int subId, int state, String incomingNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } if (VDBG) { - log("notifyCallStateForPhoneId: subId=" + subId + log("notifyCallState: subId=" + subId + " state=" + state + " incomingNumber=" + incomingNumber); } synchronized (mRecords) { @@ -1094,10 +1096,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { if (validatePhoneId(phoneId)) { switch (activationType) { - case PhoneConstants.SIM_ACTIVATION_TYPE_VOICE: + case TelephonyManager.SIM_ACTIVATION_TYPE_VOICE: mVoiceActivationState[phoneId] = activationState; break; - case PhoneConstants.SIM_ACTIVATION_TYPE_DATA: + case TelephonyManager.SIM_ACTIVATION_TYPE_DATA: mDataActivationState[phoneId] = activationState; break; default: @@ -1110,7 +1112,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + " state=" + activationState); } try { - if ((activationType == PhoneConstants.SIM_ACTIVATION_TYPE_VOICE) && + if ((activationType == TelephonyManager.SIM_ACTIVATION_TYPE_VOICE) && r.matchPhoneStateListenerEvent( PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) && idMatch(r.subId, subId, phoneId)) { @@ -1121,7 +1123,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } r.callback.onVoiceActivationStateChanged(activationState); } - if ((activationType == PhoneConstants.SIM_ACTIVATION_TYPE_DATA) && + if ((activationType == TelephonyManager.SIM_ACTIVATION_TYPE_DATA) && r.matchPhoneStateListenerEvent( PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) && idMatch(r.subId, subId, phoneId)) { @@ -1241,7 +1243,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) { - if (!checkNotifyPermission("notifyCellInfo()")) { + if (!checkNotifyPermission("notifyCellInfoForSubscriber()")) { return; } if (VDBG) { @@ -1258,7 +1260,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { try { if (DBG_LOC) { - log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r); + log("notifyCellInfoForSubscriber: mCellInfo=" + cellInfo + + " r=" + r); } r.callback.onCellInfoChanged(cellInfo); } catch (RemoteException ex) { @@ -1718,7 +1721,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyPreciseDataConnectionFailed(int phoneId, int subId, String apnType, - String apn, @DataFailCause.FailCause int failCause) { + String apn, @DataFailureCause int failCause) { if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { return; } @@ -1748,7 +1751,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void notifySrvccStateChanged(int subId, @TelephonyManager.SrvccState int state) { + public void notifySrvccStateChanged(int subId, @SrvccState int state) { if (!checkNotifyPermission("notifySrvccStateChanged()")) { return; } @@ -1855,8 +1858,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - public void notifyRadioPowerStateChanged(int phoneId, int subId, - @TelephonyManager.RadioPowerState int state) { + public void notifyRadioPowerStateChanged(int phoneId, int subId, @RadioPowerState int state) { if (!checkNotifyPermission("notifyRadioPowerStateChanged()")) { return; } @@ -2227,7 +2229,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private void broadcastPreciseDataConnectionStateChanged(int state, int networkType, String apnType, String apn, LinkProperties linkProperties, - @DataFailCause.FailCause int failCause) { + @DataFailureCause int failCause) { Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED); intent.putExtra(PhoneConstants.STATE_KEY, state); intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType); diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 9936d73fb800..d622fb433ed8 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -29,6 +29,7 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.input.InputManager; import android.hardware.vibrator.V1_0.EffectStrength; +import android.hardware.vibrator.V1_4.Capabilities; import android.icu.text.DateFormat; import android.media.AudioAttributes; import android.media.AudioManager; @@ -108,6 +109,9 @@ public class VibratorService extends IVibratorService.Stub // If a vibration is playing for longer than 5s, it's probably not haptic feedback. private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000; + // If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration. + private static final long ASYNC_TIMEOUT_MULTIPLIER = 2; + // A mapping from the intensity adjustment to the scaling to apply, where the intensity // adjustment is defined as the delta between the default intensity level and the user selected @@ -123,6 +127,7 @@ public class VibratorService extends IVibratorService.Stub private final boolean mAllowPriorityVibrationsInLowPowerMode; private final boolean mSupportsAmplitudeControl; private final boolean mSupportsExternalControl; + private final long mCapabilities; private final int mDefaultVibrationAmplitude; private final SparseArray<VibrationEffect> mFallbackEffects; private final SparseArray<Integer> mProcStatesCache = new SparseArray(); @@ -163,9 +168,10 @@ public class VibratorService extends IVibratorService.Stub static native void vibratorOff(); static native boolean vibratorSupportsAmplitudeControl(); static native void vibratorSetAmplitude(int amplitude); - static native long vibratorPerformEffect(long effect, long strength); + static native long vibratorPerformEffect(long effect, long strength, Vibration vibration); static native boolean vibratorSupportsExternalControl(); static native void vibratorSetExternalControl(boolean enabled); + static native long vibratorGetCapabilities(); private final IUidObserver mUidObserver = new IUidObserver.Stub() { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { @@ -226,6 +232,14 @@ public class VibratorService extends IVibratorService.Stub } } + private void onComplete() { + synchronized (mLock) { + if (this == mCurrentVibration) { + doCancelVibrateLocked(); + } + } + } + public boolean hasTimeoutLongerThan(long millis) { final long duration = effect.getDuration(); return duration >= 0 && duration > millis; @@ -347,6 +361,7 @@ public class VibratorService extends IVibratorService.Stub mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl(); mSupportsExternalControl = vibratorSupportsExternalControl(); + mCapabilities = vibratorGetCapabilities(); mContext = context; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); @@ -1135,10 +1150,14 @@ public class VibratorService extends IVibratorService.Stub } // Input devices don't support prebaked effect, so skip trying it with them. if (!usingInputDeviceVibrators) { - long timeout = vibratorPerformEffect(prebaked.getId(), - prebaked.getEffectStrength()); + long duration = vibratorPerformEffect(prebaked.getId(), + prebaked.getEffectStrength(), vib); + long timeout = duration; + if ((mCapabilities & Capabilities.PERFORM_COMPLETION_CALLBACK) != 0) { + timeout *= ASYNC_TIMEOUT_MULTIPLIER; + } if (timeout > 0) { - noteVibratorOnLocked(vib.uid, timeout); + noteVibratorOnLocked(vib.uid, duration); return timeout; } } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 19ad32e202fe..454941ccdb03 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -89,6 +89,7 @@ public class Watchdog extends Thread { "/system/bin/drmserver", "/system/bin/mediadrmserver", "/system/bin/mediaserver", + "/system/bin/netd", "/system/bin/sdcard", "/system/bin/surfaceflinger", "/system/bin/vold", @@ -103,6 +104,8 @@ public class Watchdog extends Thread { public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList( "android.hardware.audio@2.0::IDevicesFactory", "android.hardware.audio@4.0::IDevicesFactory", + "android.hardware.audio@5.0::IDevicesFactory", + "android.hardware.audio@6.0::IDevicesFactory", "android.hardware.biometrics.face@1.0::IBiometricsFace", "android.hardware.bluetooth@1.0::IBluetoothHci", "android.hardware.camera.provider@2.4::ICameraProvider", diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 7bc2e6d647be..6cbbcddc2b3f 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -192,34 +192,38 @@ public final class ActiveServices { @Override public void stopForegroundServicesForUidPackage(final int uid, final String packageName) { synchronized (mAm) { - final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid)); - final int N = smap.mServicesByInstanceName.size(); - final ArrayList<ServiceRecord> toStop = new ArrayList<>(N); - for (int i = 0; i < N; i++) { - final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i); - if (uid == r.serviceInfo.applicationInfo.uid - || packageName.equals(r.serviceInfo.packageName)) { - if (r.isForeground) { - toStop.add(r); - } - } - } + stopAllForegroundServicesLocked(uid, packageName); + } + } + } - // Now stop them all - final int numToStop = toStop.size(); - if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) { - Slog.i(TAG, "Package " + packageName + "/" + uid - + " entering FAS with foreground services"); - } - for (int i = 0; i < numToStop; i++) { - final ServiceRecord r = toStop.get(i); - if (DEBUG_FOREGROUND_SERVICE) { - Slog.i(TAG, " Stopping fg for service " + r); - } - setServiceForegroundInnerLocked(r, 0, null, 0, 0); + void stopAllForegroundServicesLocked(final int uid, final String packageName) { + final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid)); + final int N = smap.mServicesByInstanceName.size(); + final ArrayList<ServiceRecord> toStop = new ArrayList<>(N); + for (int i = 0; i < N; i++) { + final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i); + if (uid == r.serviceInfo.applicationInfo.uid + || packageName.equals(r.serviceInfo.packageName)) { + if (r.isForeground) { + toStop.add(r); } } } + + // Now stop them all + final int numToStop = toStop.size(); + if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) { + Slog.i(TAG, "Package " + packageName + "/" + uid + + " in FAS with foreground services"); + } + for (int i = 0; i < numToStop; i++) { + final ServiceRecord r = toStop.get(i); + if (DEBUG_FOREGROUND_SERVICE) { + Slog.i(TAG, " Stopping fg for service " + r); + } + setServiceForegroundInnerLocked(r, 0, null, 0, 0); + } } /** @@ -1010,12 +1014,23 @@ public final class ActiveServices { } } if (!aa.mAppOnTop) { - if (active == null) { - active = new ArrayList<>(); + // Transitioning a fg-service host app out of top: if it's bg restricted, + // it loses the fg service state now. + if (!appRestrictedAnyInBackground(aa.mUid, aa.mPackageName)) { + if (active == null) { + active = new ArrayList<>(); + } + if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" + + aa.mPackageName + ", uid=" + aa.mUid); + active.add(aa); + } else { + if (DEBUG_FOREGROUND_SERVICE) { + Slog.d(TAG, "bg-restricted app " + + aa.mPackageName + "/" + aa.mUid + + " exiting top; demoting fg services "); + } + stopAllForegroundServicesLocked(aa.mUid, aa.mPackageName); } - if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" - + aa.mPackageName + ", uid=" + aa.mUid); - active.add(aa); } } smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 76bfc97ac1c1..5af1480af94b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -24,6 +24,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.REMOVE_TASKS; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; +import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; @@ -348,7 +349,6 @@ import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; import com.android.server.appop.AppOpsService; -import com.android.server.compat.CompatConfig; import com.android.server.compat.PlatformCompat; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.firewall.IntentFirewall; @@ -5048,8 +5048,9 @@ public class ActivityManagerService extends IActivityManager.Stub bindApplicationTimeMillis = SystemClock.elapsedRealtime(); mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); - long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info); + long[] disabledCompatChanges = {}; if (mPlatformCompat != null) { + disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info); mPlatformCompat.resetReporting(app.info); } if (app.isolatedEntryPoint != null) { @@ -7786,10 +7787,18 @@ public class ActivityManagerService extends IActivityManager.Stub false /* mountExtStorageFull */, abiOverride); } - // TODO: Move to ProcessList? @GuardedBy("this") final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) { + return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks, + false /* disableTestApiChecks */, mountExtStorageFull, abiOverride); + } + + // TODO: Move to ProcessList? + @GuardedBy("this") + final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, + boolean disableHiddenApiChecks, boolean disableTestApiChecks, + boolean mountExtStorageFull, String abiOverride) { ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName, @@ -7824,7 +7833,7 @@ public class ActivityManagerService extends IActivityManager.Stub mPersistentStartingProcesses.add(app); mProcessList.startProcessLocked(app, new HostingRecord("added application", customProcess != null ? customProcess : app.processName), - disableHiddenApiChecks, mountExtStorageFull, abiOverride); + disableHiddenApiChecks, disableTestApiChecks, mountExtStorageFull, abiOverride); } return app; @@ -15761,10 +15770,13 @@ public class ActivityManagerService extends IActivityManager.Stub boolean disableHiddenApiChecks = ai.usesNonSdkApi() || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0; - if (disableHiddenApiChecks) { + boolean disableTestApiChecks = disableHiddenApiChecks + || (flags & INSTR_FLAG_DISABLE_TEST_API_CHECKS) != 0; + if (disableHiddenApiChecks || disableTestApiChecks) { enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS, "disable hidden API checks"); } + final boolean mountExtStorageFull = isCallerShell() && (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0; @@ -15779,7 +15791,7 @@ public class ActivityManagerService extends IActivityManager.Stub } ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, - mountExtStorageFull, abiOverride); + disableTestApiChecks, mountExtStorageFull, abiOverride); app.setActiveInstrumentation(activeInstr); activeInstr.mFinished = false; activeInstr.mRunningProcesses.add(app); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 0c1388cc82d8..d9e4844209d0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -41,6 +41,7 @@ import android.app.usage.AppStandbyInfo; import android.app.usage.ConfigurationStats; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageStatsManager; +import android.compat.Compatibility; import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.Context; @@ -80,15 +81,17 @@ import android.os.UserManager; import android.text.TextUtils; import android.text.format.Time; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.DebugUtils; import android.util.DisplayMetrics; import android.util.proto.ProtoOutputStream; import android.view.Display; +import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.util.HexDump; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; -import com.android.server.compat.CompatConfig; +import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; import java.io.File; @@ -2868,56 +2871,49 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - private void killPackage(String packageName, PrintWriter pw) throws RemoteException { - int uid = mPm.getPackageUid(packageName, 0, mUserId); - if (uid < 0) { - // uid is negative if the package wasn't found. - pw.println("Didn't find package " + packageName + " on device."); - } else { - pw.println("Killing package " + packageName + " (UID " + uid + ")."); - final long origId = Binder.clearCallingIdentity(); - mInterface.killUid(UserHandle.getAppId(uid), - UserHandle.USER_ALL, "killPackage"); - Binder.restoreCallingIdentity(origId); - } - } - private int runCompat(PrintWriter pw) throws RemoteException { - final CompatConfig config = CompatConfig.get(); + final PlatformCompat platformCompat = (PlatformCompat) + ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); String toggleValue = getNextArgRequired(); long changeId; String changeIdString = getNextArgRequired(); try { changeId = Long.parseLong(changeIdString); } catch (NumberFormatException e) { - changeId = config.lookupChangeId(changeIdString); + changeId = platformCompat.lookupChangeId(changeIdString); } if (changeId == -1) { pw.println("Unknown or invalid change: '" + changeIdString + "'."); + return -1; } String packageName = getNextArgRequired(); + if (!platformCompat.isKnownChangeId(changeId)) { + pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it" + + " could have no effect."); + } + ArraySet<Long> enabled = new ArraySet<>(); + ArraySet<Long> disabled = new ArraySet<>(); switch (toggleValue) { case "enable": - if (!config.addOverride(changeId, packageName, true)) { - pw.println("Warning! Change " + changeId + " is not known yet. Enabling it" - + " could have no effect."); - } + enabled.add(changeId); pw.println("Enabled change " + changeId + " for " + packageName + "."); - killPackage(packageName, pw); + CompatibilityChangeConfig overrides = + new CompatibilityChangeConfig( + new Compatibility.ChangeConfig(enabled, disabled)); + platformCompat.setOverrides(overrides, packageName); return 0; case "disable": - if (!config.addOverride(changeId, packageName, false)) { - pw.println("Warning! Change " + changeId + " is not known yet. Disabling it" - + " could have no effect."); - } + disabled.add(changeId); pw.println("Disabled change " + changeId + " for " + packageName + "."); - killPackage(packageName, pw); + overrides = + new CompatibilityChangeConfig( + new Compatibility.ChangeConfig(enabled, disabled)); + platformCompat.setOverrides(overrides, packageName); return 0; case "reset": - if (config.removeOverride(changeId, packageName)) { + if (platformCompat.clearOverride(changeId, packageName)) { pw.println("Reset change " + changeId + " for " + packageName + " to default value."); - killPackage(packageName, pw); } else { pw.println("No override exists for changeId " + changeId + "."); } @@ -3032,7 +3028,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" specified then send to all users."); pw.println(" --receiver-permission <PERMISSION>: Require receiver to hold permission."); pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]"); - pw.println(" [--user <USER_ID> | current] [--no-hidden-api-checks]"); + pw.println(" [--user <USER_ID> | current]"); + pw.println(" [--no-hidden-api-checks [--no-test-api-checks]]"); pw.println(" [--no-isolated-storage]"); pw.println(" [--no-window-animation] [--abi <ABI>] <COMPONENT>"); pw.println(" Start an Instrumentation. Typically this target <COMPONENT> is in the"); @@ -3052,6 +3049,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --user <USER_ID> | current: Specify user instrumentation runs in;"); pw.println(" current user if not specified."); pw.println(" --no-hidden-api-checks: disable restrictions on use of hidden API."); + pw.println(" --no-test-api-checks: disable restrictions to test APIs, if hidden"); + pw.println(" API checks are enabled."); pw.println(" --no-isolated-storage: don't use isolated storage sandbox and "); pw.println(" mount full external storage"); pw.println(" --no-window-animation: turn off window animations while running."); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 525531635df6..0524f91a01fb 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -445,7 +445,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) { // We were asked to fetch Telephony data. if (mTelephony == null) { - mTelephony = TelephonyManager.from(mContext); + mTelephony = mContext.getSystemService(TelephonyManager.class); } if (mTelephony != null) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c2f452932775..567404697395 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -731,7 +731,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void notePhoneState(int state) { enforceCallingPermission(); - int simState = TelephonyManager.getDefault().getSimState(); + int simState = mContext.getSystemService(TelephonyManager.class).getSimState(); synchronized (mStats) { mStats.notePhoneStateLocked(state, simState); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 3d598ddbd030..4692fd4eeb2e 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -1419,15 +1419,11 @@ public final class ProcessList { /** * @return {@code true} if process start is successful, false otherwise. - * @param app - * @param hostingRecord - * @param disableHiddenApiChecks - * @param abiOverride */ @GuardedBy("mService") boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, - boolean disableHiddenApiChecks, boolean mountExtStorageFull, - String abiOverride) { + boolean disableHiddenApiChecks, boolean disableTestApiChecks, + boolean mountExtStorageFull, String abiOverride) { if (app.pendingStart) { return true; } @@ -1572,6 +1568,10 @@ public final class ProcessList { throw new IllegalStateException("Invalid API policy: " + policy); } runtimeFlags |= policyBits; + + if (disableTestApiChecks) { + runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY; + } } String useAppImageCache = SystemProperties.get( @@ -1845,7 +1845,8 @@ public final class ProcessList { final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, String abiOverride) { return startProcessLocked(app, hostingRecord, - false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride); + false /* disableHiddenApiChecks */, false /* disableTestApiChecks */, + false /* mountExtStorageFull */, abiOverride); } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 055a4bde8a78..48f08e3226e3 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1461,10 +1461,13 @@ public class AudioService extends IAudioService.Stub } if (!TextUtils.isEmpty(packageName)) { PackageManager pm = mContext.getPackageManager(); + ActivityManager am = + (ActivityManager) mContext.getSystemService(mContext.ACTIVITY_SERVICE); + if (pm.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName) == PackageManager.PERMISSION_GRANTED) { try { - assistantUid = pm.getPackageUid(packageName, 0); + assistantUid = pm.getPackageUidAsUser(packageName, am.getCurrentUser()); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "updateAssistantUId() could not find UID for package: " + packageName); @@ -1582,12 +1585,13 @@ public class AudioService extends IAudioService.Stub setMicrophoneMuteNoCallerCheck(currentUser); } - private int rescaleIndex(int index, int srcStream, int dstStream) { - int srcRange = - mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex(); - int dstRange = - mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex(); + private int getIndexRange(int streamType) { + return (mStreamStates[streamType].getMaxIndex() - mStreamStates[streamType].getMinIndex()); + } + private int rescaleIndex(int index, int srcStream, int dstStream) { + int srcRange = getIndexRange(srcStream); + int dstRange = getIndexRange(dstStream); if (srcRange == 0) { Log.e(TAG, "rescaleIndex : index range should not be zero"); return mStreamStates[dstStream].getMinIndex(); @@ -1598,6 +1602,17 @@ public class AudioService extends IAudioService.Stub / srcRange; } + private int rescaleStep(int step, int srcStream, int dstStream) { + int srcRange = getIndexRange(srcStream); + int dstRange = getIndexRange(dstStream); + if (srcRange == 0) { + Log.e(TAG, "rescaleStep : index range should not be zero"); + return 0; + } + + return ((step * dstRange + srcRange / 2) / srcRange); + } + /////////////////////////////////////////////////////////////////////////// // IPC methods /////////////////////////////////////////////////////////////////////////// @@ -1774,7 +1789,7 @@ public class AudioService extends IAudioService.Stub } } else { // convert one UI step (+/-1) into a number of internal units on the stream alias - step = rescaleIndex(10, streamType, streamTypeAlias); + step = rescaleStep(10, streamType, streamTypeAlias); } // If either the client forces allowing ringer modes for this adjustment, @@ -3896,8 +3911,7 @@ public class AudioService extends IAudioService.Stub final boolean muteSystem = (zenPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0; final boolean muteNotificationAndRing = ZenModeConfig - .areAllPriorityOnlyNotificationZenSoundsMuted( - mNm.getConsolidatedNotificationPolicy()); + .areAllPriorityOnlyNotificationZenSoundsMuted(zenPolicy); return muteAlarms && isAlarm(streamType) || muteMedia && isMedia(streamType) || muteSystem && isSystem(streamType) @@ -3909,11 +3923,13 @@ public class AudioService extends IAudioService.Stub } /** - * DND total silence: media and alarms streams are tied to the muted ringer - * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)} - * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode) - * DND priority only: alarms, media, system streams can be muted separate from ringer based on - * zenPolicy (this method determines which streams) + * Notifications, ringer and system sounds are controlled by the ringer: + * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)} but can + * also be muted by DND based on the DND mode: + * DND total silence: media and alarms streams can be muted by DND + * DND alarms only: no streams additionally controlled by DND + * DND priority only: alarms, media, system, ringer and notification streams can be muted by + * DND. The current applied zenPolicy determines which streams will be muted by DND. * @return true if changed, else false */ private boolean updateZenModeAffectedStreams() { @@ -3934,6 +3950,11 @@ public class AudioService extends IAudioService.Stub & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) { zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM; } + + if (ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(zenPolicy)) { + zenModeAffectedStreams |= 1 << AudioManager.STREAM_NOTIFICATION; + zenModeAffectedStreams |= 1 << AudioManager.STREAM_RING; + } } if (mZenModeAffectedStreams != zenModeAffectedStreams) { diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java index bd129f70ee29..41008c277e4b 100644 --- a/services/core/java/com/android/server/audio/FocusRequester.java +++ b/services/core/java/com/android/server/audio/FocusRequester.java @@ -437,7 +437,8 @@ public class FocusRequester { } int dispatchFocusChange(int focusChange) { - if (mFocusDispatcher == null) { + final IAudioFocusDispatcher fd = mFocusDispatcher; + if (fd == null) { if (MediaFocusControl.DEBUG) { Log.e(TAG, "dispatchFocusChange: no focus dispatcher"); } return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } @@ -457,7 +458,7 @@ public class FocusRequester { mFocusLossReceived = focusChange; } try { - mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId); + fd.dispatchAudioFocusChange(focusChange, mClientId); } catch (android.os.RemoteException e) { Log.e(TAG, "dispatchFocusChange: error talking to focus listener " + mClientId, e); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; @@ -466,16 +467,18 @@ public class FocusRequester { } void dispatchFocusResultFromExtPolicy(int requestResult) { - if (mFocusDispatcher == null) { + final IAudioFocusDispatcher fd = mFocusDispatcher; + if (fd == null) { if (MediaFocusControl.DEBUG) { Log.e(TAG, "dispatchFocusResultFromExtPolicy: no focus dispatcher"); } + return; } if (DEBUG) { Log.v(TAG, "dispatching result" + requestResult + " to " + mClientId); } try { - mFocusDispatcher.dispatchFocusResultFromExtPolicy(requestResult, mClientId); + fd.dispatchFocusResultFromExtPolicy(requestResult, mClientId); } catch (android.os.RemoteException e) { Log.e(TAG, "dispatchFocusResultFromExtPolicy: error talking to focus listener" + mClientId, e); diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index bc5973d1b270..87624359ef85 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import java.util.HashMap; @@ -35,12 +36,8 @@ import java.util.Map; * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ -public final class CompatChange { +public final class CompatChange extends CompatibilityChangeInfo { - private final long mChangeId; - @Nullable private final String mName; - private final int mEnableAfterTargetSdk; - private final boolean mDisabled; private Map<String, Boolean> mPackageOverrides; public CompatChange(long changeId) { @@ -56,29 +53,15 @@ public final class CompatChange { */ public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk, boolean disabled) { - mChangeId = changeId; - mName = name; - mEnableAfterTargetSdk = enableAfterTargetSdk; - mDisabled = disabled; + super(changeId, name, enableAfterTargetSdk, disabled); } /** * @param change an object generated by services/core/xsd/platform-compat-config.xsd */ public CompatChange(Change change) { - mChangeId = change.getId(); - mName = change.getName(); - mEnableAfterTargetSdk = change.getEnableAfterTargetSdk(); - mDisabled = change.getDisabled(); - } - - long getId() { - return mChangeId; - } - - @Nullable - String getName() { - return mName; + super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(), + change.getDisabled()); } /** @@ -121,11 +104,11 @@ public final class CompatChange { if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) { return mPackageOverrides.get(app.packageName); } - if (mDisabled) { + if (getDisabled()) { return false; } - if (mEnableAfterTargetSdk != -1) { - return app.targetSdkVersion > mEnableAfterTargetSdk; + if (getEnableAfterTargetSdk() != -1) { + return app.targetSdkVersion > getEnableAfterTargetSdk(); } return true; } @@ -133,14 +116,14 @@ public final class CompatChange { @Override public String toString() { StringBuilder sb = new StringBuilder("ChangeId(") - .append(mChangeId); - if (mName != null) { - sb.append("; name=").append(mName); + .append(getId()); + if (getName() != null) { + sb.append("; name=").append(getName()); } - if (mEnableAfterTargetSdk != -1) { - sb.append("; enableAfterTargetSdk=").append(mEnableAfterTargetSdk); + if (getEnableAfterTargetSdk() != -1) { + sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk()); } - if (mDisabled) { + if (getDisabled()) { sb.append("; disabled"); } if (mPackageOverrides != null && mPackageOverrides.size() > 0) { diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 0fabd9aef373..490cce347188 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -16,6 +16,7 @@ package com.android.server.compat; +import android.compat.Compatibility.ChangeConfig; import android.content.pm.ApplicationInfo; import android.os.Environment; import android.text.TextUtils; @@ -26,6 +27,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import com.android.server.compat.config.XmlParser; @@ -37,15 +39,18 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; import javax.xml.datatype.DatatypeConfigurationException; + /** * This class maintains state relating to platform compatibility changes. * * <p>It stores the default configuration for each change, and any per-package overrides that have * been configured. */ -public final class CompatConfig { +final class CompatConfig { private static final String TAG = "CompatConfig"; @@ -57,13 +62,13 @@ public final class CompatConfig { private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); @VisibleForTesting - public CompatConfig() { + CompatConfig() { } /** * @return The static instance of this class to be used within the system server. */ - public static CompatConfig get() { + static CompatConfig get() { return sInstance; } @@ -73,7 +78,7 @@ public final class CompatConfig { * * @param change The change to add. Any change with the same ID will be overwritten. */ - public void addChange(CompatChange change) { + void addChange(CompatChange change) { synchronized (mChanges) { mChanges.put(change.getId(), change); } @@ -85,10 +90,10 @@ public final class CompatConfig { * * @param app The app in question * @return A sorted long array of change IDs. We use a primitive array to minimize memory - * footprint: Every app process will store this array statically so we aim to reduce - * overhead as much as possible. + * footprint: Every app process will store this array statically so we aim to reduce + * overhead as much as possible. */ - public long[] getDisabledChanges(ApplicationInfo app) { + long[] getDisabledChanges(ApplicationInfo app) { LongArray disabled = new LongArray(); synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { @@ -109,7 +114,7 @@ public final class CompatConfig { * @param name Name of the change to look up * @return The change ID, or {@code -1} if no change with that name exists. */ - public long lookupChangeId(String name) { + long lookupChangeId(String name) { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { if (TextUtils.equals(mChanges.valueAt(i).getName(), name)) { @@ -124,11 +129,11 @@ public final class CompatConfig { * Find if a given change is enabled for a given application. * * @param changeId The ID of the change in question - * @param app App to check for + * @param app App to check for * @return {@code true} if the change is enabled for this app. Also returns {@code true} if the - * change ID is not known, as unknown changes are enabled by default. + * change ID is not known, as unknown changes are enabled by default. */ - public boolean isChangeEnabled(long changeId, ApplicationInfo app) { + boolean isChangeEnabled(long changeId, ApplicationInfo app) { synchronized (mChanges) { CompatChange c = mChanges.get(changeId); if (c == null) { @@ -146,14 +151,15 @@ public final class CompatConfig { * * <p>Note, package overrides are not persistent and will be lost on system or runtime restart. * - * @param changeId The ID of the change to be overridden. Note, this call will succeed even if - * this change is not known; it will only have any effect if any code in the - * platform is gated on the ID given. + * @param changeId The ID of the change to be overridden. Note, this call will succeed even + * if + * this change is not known; it will only have any effect if any code in the + * platform is gated on the ID given. * @param packageName The app package name to override the change for. - * @param enabled If the change should be enabled or disabled. + * @param enabled If the change should be enabled or disabled. * @return {@code true} if the change existed before adding the override. */ - public boolean addOverride(long changeId, String packageName, boolean enabled) { + boolean addOverride(long changeId, String packageName, boolean enabled) { boolean alreadyKnown = true; synchronized (mChanges) { CompatChange c = mChanges.get(changeId); @@ -168,15 +174,27 @@ public final class CompatConfig { } /** + * Check whether the change is known to the compat config. + * + * @return {@code true} if the change is known. + */ + boolean isKnownChangeId(long changeId) { + synchronized (mChanges) { + CompatChange c = mChanges.get(changeId); + return c != null; + } + } + + /** * Removes an override previously added via {@link #addOverride(long, String, boolean)}. This * restores the default behaviour for the given change and app, once any app processes have been * restarted. * - * @param changeId The ID of the change that was overridden. + * @param changeId The ID of the change that was overridden. * @param packageName The app package name that was overridden. * @return {@code true} if an override existed; */ - public boolean removeOverride(long changeId, String packageName) { + boolean removeOverride(long changeId, String packageName) { boolean overrideExists = false; synchronized (mChanges) { CompatChange c = mChanges.get(changeId); @@ -187,22 +205,22 @@ public final class CompatConfig { } return overrideExists; } + /** * Overrides the enabled state for a given change and app. This method is intended to be used * *only* for debugging purposes. * * <p>Note, package overrides are not persistent and will be lost on system or runtime restart. * - * @param overrides list of overrides to default changes config. + * @param overrides list of overrides to default changes config. * @param packageName app for which the overrides will be applied. */ - public void addOverrides( - CompatibilityChangeConfig overrides, String packageName) { + void addOverrides(CompatibilityChangeConfig overrides, String packageName) { synchronized (mChanges) { - for (Long changeId: overrides.enabledChanges()) { + for (Long changeId : overrides.enabledChanges()) { addOverride(changeId, packageName, true); } - for (Long changeId: overrides.disabledChanges()) { + for (Long changeId : overrides.disabledChanges()) { addOverride(changeId, packageName, false); } } @@ -217,7 +235,7 @@ public final class CompatConfig { * * @param packageName The package for which the overrides should be purged. */ - public void removePackageOverrides(String packageName) { + void removePackageOverrides(String packageName) { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { mChanges.valueAt(i).removePackageOverride(packageName); @@ -226,11 +244,11 @@ public final class CompatConfig { } /** - * Dumps the current list of compatibility config information. - * - * @param pw The {@link PrintWriter} instance to which the information will be dumped. - */ - public void dumpConfig(PrintWriter pw) { + * Dumps the current list of compatibility config information. + * + * @param pw The {@link PrintWriter} instance to which the information will be dumped. + */ + void dumpConfig(PrintWriter pw) { synchronized (mChanges) { if (mChanges.size() == 0) { pw.println("No compat overrides."); @@ -243,6 +261,49 @@ public final class CompatConfig { } } + /** + * Get the config for a given app. + * + * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped. + * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the + * given app. + */ + + CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) { + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + synchronized (mChanges) { + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange c = mChanges.valueAt(i); + if (c.isEnabled(applicationInfo)) { + enabled.add(c.getId()); + } else { + disabled.add(c.getId()); + } + } + } + return new CompatibilityChangeConfig(new ChangeConfig(enabled, disabled)); + } + + /** + * Dumps all the compatibility change information. + * + * @return An array of {@link CompatibilityChangeInfo} with the current changes. + */ + CompatibilityChangeInfo[] dumpChanges() { + synchronized (mChanges) { + CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()]; + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange change = mChanges.valueAt(i); + changeInfos[i] = new CompatibilityChangeInfo(change.getId(), + change.getName(), + change.getEnableAfterTargetSdk(), + change.getDisabled()); + } + return changeInfos; + } + } + CompatConfig initConfigFromLib(File libraryDir) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { Slog.e(TAG, "No directory " + libraryDir + ", skipping"); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 9ac9955493cc..ae5ad7ea1261 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,15 +16,20 @@ package com.android.server.compat; +import android.app.ActivityManager; +import android.app.IActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; import android.util.StatsLog; import com.android.internal.compat.ChangeReporter; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.internal.compat.IPlatformCompat; import com.android.internal.util.DumpUtils; @@ -105,12 +110,75 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) { CompatConfig.get().addOverrides(overrides, packageName); + killPackage(packageName); + } + + @Override + public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) { + CompatConfig.get().addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) { CompatConfig config = CompatConfig.get(); config.removePackageOverrides(packageName); + killPackage(packageName); + } + + @Override + public void clearOverridesForTest(String packageName) { + CompatConfig config = CompatConfig.get(); + config.removePackageOverrides(packageName); + } + + @Override + public boolean clearOverride(long changeId, String packageName) { + boolean existed = CompatConfig.get().removeOverride(changeId, packageName); + killPackage(packageName); + return existed; + } + + @Override + public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { + return CompatConfig.get().getAppConfig(appInfo); + } + + @Override + public CompatibilityChangeInfo[] listAllChanges() { + return CompatConfig.get().dumpChanges(); + } + + /** + * Check whether the change is known to the compat config. + * @param changeId + * @return {@code true} if the change is known. + */ + public boolean isKnownChangeId(long changeId) { + return CompatConfig.get().isKnownChangeId(changeId); + + } + + /** + * Retrieves the set of disabled changes for a given app. Any change ID not in the returned + * array is by default enabled for the app. + * + * @param appInfo The app in question + * @return A sorted long array of change IDs. We use a primitive array to minimize memory + * footprint: Every app process will store this array statically so we aim to reduce + * overhead as much as possible. + */ + public long[] getDisabledChanges(ApplicationInfo appInfo) { + return CompatConfig.get().getDisabledChanges(appInfo); + } + + /** + * Look up a change ID by name. + * + * @param name Name of the change to look up + * @return The change ID, or {@code -1} if no change with that name exists. + */ + public long lookupChangeId(String name) { + return CompatConfig.get().lookupChangeId(name); } @Override @@ -140,4 +208,34 @@ public class PlatformCompat extends IPlatformCompat.Stub { private void reportChange(long changeId, int uid, int state) { mChangeReporter.reportChange(uid, changeId, state); } + + private void killPackage(String packageName) { + int uid = -1; + try { + uid = mContext.getPackageManager().getPackageUid(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Didn't find package " + packageName + " on device.", e); + return; + } + + Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ")."); + killUid(UserHandle.getAppId(uid), + UserHandle.USER_ALL, "PlatformCompat overrides"); + } + + private void killUid(int appId, int userId, String reason) { + final long identity = Binder.clearCallingIdentity(); + try { + IActivityManager am = ActivityManager.getService(); + if (am != null) { + try { + am.killUid(appId, userId, reason); + } catch (RemoteException e) { + /* ignore - same process */ + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 96b7cb315f58..24a5b7fa1489 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -28,6 +28,7 @@ import android.net.NetworkInfo; import android.net.NetworkMisc; import android.net.NetworkMonitorManager; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkState; import android.os.Handler; import android.os.INetworkManagementService; @@ -227,8 +228,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // validated). private boolean mLingering; - // This represents the last score received from the NetworkAgent. - private int currentScore; + // This represents the characteristics of a network that affects how good the network is + // considered for a particular use. + @NonNull + private NetworkScore mNetworkScore; // The list of NetworkRequests being satisfied by this Network. private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); @@ -257,8 +260,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { private final Handler mHandler; public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, - LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, - NetworkMisc misc, ConnectivityService connService, INetd netd, + LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context, + Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { this.messenger = messenger; asyncChannel = ac; @@ -266,7 +269,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { networkInfo = info; linkProperties = lp; networkCapabilities = nc; - currentScore = score; + mNetworkScore = ns; clatd = new Nat464Xlat(this, netd, dnsResolver, nms); mConnService = connService; mContext = context; @@ -483,7 +486,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } - int score = currentScore; + int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE); if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } @@ -512,8 +515,13 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { return getCurrentScore(true); } - public void setCurrentScore(int newScore) { - currentScore = newScore; + public void setNetworkScore(@NonNull NetworkScore ns) { + mNetworkScore = ns; + } + + @NonNull + public NetworkScore getNetworkScore() { + return mNetworkScore; } public NetworkState getNetworkState() { diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index b3804c4d7ec5..acedc3635730 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -286,8 +286,8 @@ public class Tethering extends BaseNetworkObserver { private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); - TelephonyManager.from(mContext).listen(mPhoneStateListener, - PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + mContext.getSystemService(TelephonyManager.class).listen( + mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_STATE); diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java index 2e72fbd95931..93227bd78a81 100644 --- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java @@ -321,7 +321,11 @@ class GnssNetworkConnectivityHandler { private void handleUpdateNetworkState(Network network, boolean isConnected, NetworkCapabilities capabilities) { - boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled(); + boolean networkAvailable = false; + TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); + if (telephonyManager != null) { + networkAvailable = isConnected && telephonyManager.getDataEnabled(); + } NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network, capabilities); String apn = networkAttributes.mApn; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 41806cabef3f..08c94267e969 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -337,7 +337,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), TelephonyManager.getDefault(), + wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); service.registerLocalService(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 0d9dcff51b49..faac78d68879 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -7234,7 +7234,7 @@ public class NotificationManagerService extends SystemService { } private void listenForCallState() { - TelephonyManager.from(getContext()).listen(new PhoneStateListener() { + getContext().getSystemService(TelephonyManager.class).listen(new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { if (mCallState == state) return; diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index a0c00f8c9b69..fd44cbb46065 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -11,7 +11,7 @@ * 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.s + * limitations under the License. */ package com.android.server.pm; @@ -29,17 +29,17 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageParser; -import android.content.pm.PackageParser.PackageParserException; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.ServiceManager.ServiceNotFoundException; import android.sysprop.ApexProperties; -import android.util.ArrayMap; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import java.io.File; @@ -56,117 +56,33 @@ import java.util.stream.Collectors; * ApexManager class handles communications with the apex service to perform operation and queries, * as well as providing caching to avoid unnecessary calls to the service. */ -class ApexManager { - static final String TAG = "ApexManager"; - private final IApexService mApexService; - private final Context mContext; - private final Object mLock = new Object(); - /** - * A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code - * AndroidManifest.xml} - * - * <p>Note that key of this map is {@code packageName} field of the corresponding {@code - * AndroidManifest.xml}. - */ - @GuardedBy("mLock") - private List<PackageInfo> mAllPackagesCache; - /** - * A map from {@code apexName} to the {@Link PackageInfo} generated from the {@code - * AndroidManifest.xml}. - * - * <p>Note that key of this map is {@code apexName} field which corresponds to the {@code name} - * field of {@code apex_manifest.json}. - */ - // TODO(b/132324953): remove. - @GuardedBy("mLock") - private ArrayMap<String, PackageInfo> mApexNameToPackageInfoCache; +abstract class ApexManager { - - ApexManager(Context context) { - mContext = context; - if (!isApexSupported()) { - mApexService = null; - return; - } - try { - mApexService = IApexService.Stub.asInterface( - ServiceManager.getServiceOrThrow("apexservice")); - } catch (ServiceNotFoundException e) { - throw new IllegalStateException("Required service apexservice not available"); - } - } + private static final String TAG = "ApexManager"; static final int MATCH_ACTIVE_PACKAGE = 1 << 0; static final int MATCH_FACTORY_PACKAGE = 1 << 1; - @IntDef( - flag = true, - prefix = { "MATCH_"}, - value = {MATCH_ACTIVE_PACKAGE, MATCH_FACTORY_PACKAGE}) - @Retention(RetentionPolicy.SOURCE) - @interface PackageInfoFlags{} - void systemReady() { - if (!isApexSupported()) return; - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - onBootCompleted(); - mContext.unregisterReceiver(this); - } - }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); - } - - private void populateAllPackagesCacheIfNeeded() { - synchronized (mLock) { - if (mAllPackagesCache != null) { - return; - } - mApexNameToPackageInfoCache = new ArrayMap<>(); + /** + * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerNoOp} depending + * on whenever this device supports APEX, i.e. {@link ApexProperties#updatable()} evaluates to + * {@code true}. + */ + static ApexManager create(Context systemContext) { + if (ApexProperties.updatable().orElse(false)) { try { - mAllPackagesCache = new ArrayList<>(); - HashSet<String> activePackagesSet = new HashSet<>(); - HashSet<String> factoryPackagesSet = new HashSet<>(); - final ApexInfo[] allPkgs = mApexService.getAllPackages(); - for (ApexInfo ai : allPkgs) { - // If the device is using flattened APEX, don't report any APEX - // packages since they won't be managed or updated by PackageManager. - if ((new File(ai.modulePath)).isDirectory()) { - break; - } - try { - final PackageInfo pkg = PackageParser.generatePackageInfoFromApex( - ai, PackageManager.GET_META_DATA - | PackageManager.GET_SIGNING_CERTIFICATES); - mAllPackagesCache.add(pkg); - if (ai.isActive) { - if (activePackagesSet.contains(pkg.packageName)) { - throw new IllegalStateException( - "Two active packages have the same name: " - + pkg.packageName); - } - activePackagesSet.add(pkg.packageName); - // TODO(b/132324953): remove. - mApexNameToPackageInfoCache.put(ai.moduleName, pkg); - } - if (ai.isFactory) { - if (factoryPackagesSet.contains(pkg.packageName)) { - throw new IllegalStateException( - "Two factory packages have the same name: " - + pkg.packageName); - } - factoryPackagesSet.add(pkg.packageName); - } - } catch (PackageParserException pe) { - throw new IllegalStateException("Unable to parse: " + ai, pe); - } - } - } catch (RemoteException re) { - Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); - throw new RuntimeException(re); + return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface( + ServiceManager.getServiceOrThrow("apexservice"))); + } catch (ServiceManager.ServiceNotFoundException e) { + throw new IllegalStateException("Required service apexservice not available"); } + } else { + return new ApexManagerNoOp(); } } + abstract void systemReady(); + /** * Retrieves information about an APEX package. * @@ -179,35 +95,8 @@ class ApexManager { * @return a PackageInfo object with the information about the package, or null if the package * is not found. */ - @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { - if (!isApexSupported()) return null; - populateAllPackagesCacheIfNeeded(); - boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; - boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; - for (PackageInfo packageInfo: mAllPackagesCache) { - if (!packageInfo.packageName.equals(packageName)) { - continue; - } - if ((!matchActive || isActive(packageInfo)) - && (!matchFactory || isFactory(packageInfo))) { - return packageInfo; - } - } - return null; - } - - /** - * Returns a {@link PackageInfo} for an active APEX package keyed by it's {@code apexName}. - * - * @deprecated this API will soon be deleted, please don't depend on it. - */ - // TODO(b/132324953): delete. - @Deprecated - @Nullable PackageInfo getPackageInfoForApexName(String apexName) { - if (!isApexSupported()) return null; - populateAllPackagesCacheIfNeeded(); - return mApexNameToPackageInfoCache.get(apexName); - } + @Nullable + abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); /** * Retrieves information about all active APEX packages. @@ -215,14 +104,7 @@ class ApexManager { * @return a List of PackageInfo object, each one containing information about a different * active package. */ - List<PackageInfo> getActivePackages() { - if (!isApexSupported()) return Collections.emptyList(); - populateAllPackagesCacheIfNeeded(); - return mAllPackagesCache - .stream() - .filter(item -> isActive(item)) - .collect(Collectors.toList()); - } + abstract List<PackageInfo> getActivePackages(); /** * Retrieves information about all active pre-installed APEX packages. @@ -230,14 +112,7 @@ class ApexManager { * @return a List of PackageInfo object, each one containing information about a different * active pre-installed package. */ - List<PackageInfo> getFactoryPackages() { - if (!isApexSupported()) return Collections.emptyList(); - populateAllPackagesCacheIfNeeded(); - return mAllPackagesCache - .stream() - .filter(item -> isFactory(item)) - .collect(Collectors.toList()); - } + abstract List<PackageInfo> getFactoryPackages(); /** * Retrieves information about all inactive APEX packages. @@ -245,14 +120,7 @@ class ApexManager { * @return a List of PackageInfo object, each one containing information about a different * inactive package. */ - List<PackageInfo> getInactivePackages() { - if (!isApexSupported()) return Collections.emptyList(); - populateAllPackagesCacheIfNeeded(); - return mAllPackagesCache - .stream() - .filter(item -> !isActive(item)) - .collect(Collectors.toList()); - } + abstract List<PackageInfo> getInactivePackages(); /** * Checks if {@code packageName} is an apex package. @@ -260,16 +128,7 @@ class ApexManager { * @param packageName package to check. * @return {@code true} if {@code packageName} is an apex package. */ - boolean isApexPackage(String packageName) { - if (!isApexSupported()) return false; - populateAllPackagesCacheIfNeeded(); - for (PackageInfo packageInfo : mAllPackagesCache) { - if (packageInfo.packageName.equals(packageName)) { - return true; - } - } - return false; - } + abstract boolean isApexPackage(String packageName); /** * Retrieves information about an apexd staged session i.e. the internal state used by apexd to @@ -278,19 +137,8 @@ class ApexManager { * @param sessionId the identifier of the session. * @return an ApexSessionInfo object, or null if the session is not known. */ - @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { - if (!isApexSupported()) return null; - try { - ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId); - if (apexSessionInfo.isUnknown) { - return null; - } - return apexSessionInfo; - } catch (RemoteException re) { - Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); - } - } + @Nullable + abstract ApexSessionInfo getStagedSessionInfo(int sessionId); /** * Submit a staged session to apex service. This causes the apex service to perform some initial @@ -302,47 +150,19 @@ class ApexManager { * @param childSessionIds if {@code sessionId} is a multi-package session, this should contain * an array of identifiers of all the child sessions. Otherwise it should * be an empty array. - * @param apexInfoList this is an output parameter, which needs to be initialized by tha caller - * and will be filled with a list of {@link ApexInfo} objects, each of which - * contains metadata about one of the packages being submitted as part of - * the session. - * @return whether the submission of the session was successful. + * @throws PackageManagerException if call to apexd fails */ - boolean submitStagedSession( - int sessionId, @NonNull int[] childSessionIds, @NonNull ApexInfoList apexInfoList) { - if (!isApexSupported()) return false; - try { - mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList); - return true; - } catch (RemoteException re) { - Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); - } catch (Exception e) { - Slog.e(TAG, "apexd verification failed", e); - return false; - } - } + abstract ApexInfoList submitStagedSession(int sessionId, @NonNull int[] childSessionIds) + throws PackageManagerException; /** * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be * applied at next reboot. * * @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready. - * @return true upon success, false if the session is unknown. + * @throws PackageManagerException if call to apexd fails */ - boolean markStagedSessionReady(int sessionId) { - if (!isApexSupported()) return false; - try { - mApexService.markStagedSessionReady(sessionId); - return true; - } catch (RemoteException re) { - Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); - } catch (Exception e) { - Slog.e(TAG, "Failed to mark session " + sessionId + " ready", e); - return false; - } - } + abstract void markStagedSessionReady(int sessionId) throws PackageManagerException; /** * Marks a staged session as successful. @@ -352,44 +172,21 @@ class ApexManager { * @param sessionId the identifier of the {@link PackageInstallerSession} being marked as * successful. */ - void markStagedSessionSuccessful(int sessionId) { - if (!isApexSupported()) return; - try { - mApexService.markStagedSessionSuccessful(sessionId); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); - } catch (Exception e) { - // It is fine to just log an exception in this case. APEXd will be able to recover in - // case markStagedSessionSuccessful fails. - Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e); - } - } + abstract void markStagedSessionSuccessful(int sessionId); /** * Whether the current device supports the management of APEX packages. * * @return true if APEX packages can be managed on this device, false otherwise. */ - boolean isApexSupported() { - return ApexProperties.updatable().orElse(false); - } + abstract boolean isApexSupported(); /** * Abandons the (only) active session previously submitted. * * @return {@code true} upon success, {@code false} if any remote exception occurs */ - boolean abortActiveSession() { - if (!isApexSupported()) return false; - try { - mApexService.abortActiveSession(); - return true; - } catch (RemoteException re) { - Slog.e(TAG, "Unable to contact apexservice", re); - return false; - } - } + abstract boolean abortActiveSession(); /** * Uninstalls given {@code apexPackage}. @@ -399,120 +196,431 @@ class ApexManager { * @param apexPackagePath package to uninstall. * @return {@code true} upon successful uninstall, {@code false} otherwise. */ - boolean uninstallApex(String apexPackagePath) { - if (!isApexSupported()) return false; - try { - mApexService.unstagePackages(Collections.singletonList(apexPackagePath)); - return true; - } catch (Exception e) { - return false; - } - } + abstract boolean uninstallApex(String apexPackagePath); /** - * Whether an APEX package is active or not. + * Dumps various state information to the provided {@link PrintWriter} object. * - * @param packageInfo the package to check - * @return {@code true} if this package is active, {@code false} otherwise. + * @param pw the {@link PrintWriter} object to send information to. + * @param packageName a {@link String} containing a package name, or {@code null}. If set, only + * information about that specific package will be dumped. */ - private static boolean isActive(PackageInfo packageInfo) { - return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; - } + abstract void dump(PrintWriter pw, @Nullable String packageName); - /** - * Whether the APEX package is pre-installed or not. - * - * @param packageInfo the package to check - * @return {@code true} if this package is pre-installed, {@code false} otherwise. - */ - private static boolean isFactory(PackageInfo packageInfo) { - return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; - } + @IntDef( + flag = true, + prefix = { "MATCH_"}, + value = {MATCH_ACTIVE_PACKAGE, MATCH_FACTORY_PACKAGE}) + @Retention(RetentionPolicy.SOURCE) + @interface PackageInfoFlags{} /** - * Dump information about the packages contained in a particular cache - * @param packagesCache the cache to print information about. - * @param packageName a {@link String} containing a package name, or {@code null}. If set, only - * information about that specific package will be dumped. - * @param ipw the {@link IndentingPrintWriter} object to send information to. + * An implementation of {@link ApexManager} that should be used in case device supports updating + * APEX packages. */ - void dumpFromPackagesCache( - List<PackageInfo> packagesCache, - @Nullable String packageName, - IndentingPrintWriter ipw) { - ipw.println(); - ipw.increaseIndent(); - for (PackageInfo pi : packagesCache) { - if (packageName != null && !packageName.equals(pi.packageName)) { - continue; + @VisibleForTesting + static class ApexManagerImpl extends ApexManager { + private final IApexService mApexService; + private final Context mContext; + private final Object mLock = new Object(); + /** + * A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code + * AndroidManifest.xml} + * + * <p>Note that key of this map is {@code packageName} field of the corresponding {@code + * AndroidManifest.xml}. + */ + @GuardedBy("mLock") + private List<PackageInfo> mAllPackagesCache; + + ApexManagerImpl(Context context, IApexService apexService) { + mContext = context; + mApexService = apexService; + } + + /** + * Whether an APEX package is active or not. + * + * @param packageInfo the package to check + * @return {@code true} if this package is active, {@code false} otherwise. + */ + private static boolean isActive(PackageInfo packageInfo) { + return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; + } + + /** + * Whether the APEX package is pre-installed or not. + * + * @param packageInfo the package to check + * @return {@code true} if this package is pre-installed, {@code false} otherwise. + */ + private static boolean isFactory(PackageInfo packageInfo) { + return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + + @Override + void systemReady() { + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // Post populateAllPackagesCacheIfNeeded to a background thread, since it's + // expensive to run it in broadcast handler thread. + BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded()); + mContext.unregisterReceiver(this); + } + }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); + } + + private void populateAllPackagesCacheIfNeeded() { + synchronized (mLock) { + if (mAllPackagesCache != null) { + return; + } + try { + mAllPackagesCache = new ArrayList<>(); + HashSet<String> activePackagesSet = new HashSet<>(); + HashSet<String> factoryPackagesSet = new HashSet<>(); + final ApexInfo[] allPkgs = mApexService.getAllPackages(); + for (ApexInfo ai : allPkgs) { + // If the device is using flattened APEX, don't report any APEX + // packages since they won't be managed or updated by PackageManager. + if ((new File(ai.modulePath)).isDirectory()) { + break; + } + int flags = PackageManager.GET_META_DATA + | PackageManager.GET_SIGNING_CERTIFICATES + | PackageManager.GET_SIGNATURES; + PackageParser.Package pkg; + try { + File apexFile = new File(ai.modulePath); + PackageParser pp = new PackageParser(); + pkg = pp.parsePackage(apexFile, flags, false); + PackageParser.collectCertificates(pkg, false); + } catch (PackageParser.PackageParserException pe) { + throw new IllegalStateException("Unable to parse: " + ai, pe); + } + + final PackageInfo packageInfo = + PackageParser.generatePackageInfo(pkg, ai, flags); + mAllPackagesCache.add(packageInfo); + if (ai.isActive) { + if (activePackagesSet.contains(packageInfo.packageName)) { + throw new IllegalStateException( + "Two active packages have the same name: " + + packageInfo.packageName); + } + activePackagesSet.add(packageInfo.packageName); + } + if (ai.isFactory) { + if (factoryPackagesSet.contains(packageInfo.packageName)) { + throw new IllegalStateException( + "Two factory packages have the same name: " + + packageInfo.packageName); + } + factoryPackagesSet.add(packageInfo.packageName); + } + + } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); + throw new RuntimeException(re); + } } - ipw.println(pi.packageName); - ipw.increaseIndent(); - ipw.println("Version: " + pi.versionCode); - ipw.println("Path: " + pi.applicationInfo.sourceDir); - ipw.println("IsActive: " + isActive(pi)); - ipw.println("IsFactory: " + isFactory(pi)); - ipw.decreaseIndent(); } - ipw.decreaseIndent(); - ipw.println(); - } - /** - * Dumps various state information to the provided {@link PrintWriter} object. - * - * @param pw the {@link PrintWriter} object to send information to. - * @param packageName a {@link String} containing a package name, or {@code null}. If set, only - * information about that specific package will be dumped. - */ - void dump(PrintWriter pw, @Nullable String packageName) { - if (!isApexSupported()) return; - final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); - try { + @Override + @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { populateAllPackagesCacheIfNeeded(); + boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; + boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; + for (PackageInfo packageInfo: mAllPackagesCache) { + if (!packageInfo.packageName.equals(packageName)) { + continue; + } + if ((matchActive && isActive(packageInfo)) + || (matchFactory && isFactory(packageInfo))) { + return packageInfo; + } + } + return null; + } + + @Override + List<PackageInfo> getActivePackages() { + populateAllPackagesCacheIfNeeded(); + return mAllPackagesCache + .stream() + .filter(item -> isActive(item)) + .collect(Collectors.toList()); + } + + @Override + List<PackageInfo> getFactoryPackages() { + populateAllPackagesCacheIfNeeded(); + return mAllPackagesCache + .stream() + .filter(item -> isFactory(item)) + .collect(Collectors.toList()); + } + + @Override + List<PackageInfo> getInactivePackages() { + populateAllPackagesCacheIfNeeded(); + return mAllPackagesCache + .stream() + .filter(item -> !isActive(item)) + .collect(Collectors.toList()); + } + + @Override + boolean isApexPackage(String packageName) { + if (!isApexSupported()) return false; + populateAllPackagesCacheIfNeeded(); + for (PackageInfo packageInfo : mAllPackagesCache) { + if (packageInfo.packageName.equals(packageName)) { + return true; + } + } + return false; + } + + @Override + @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { + try { + ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId); + if (apexSessionInfo.isUnknown) { + return null; + } + return apexSessionInfo; + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + throw new RuntimeException(re); + } + } + + @Override + ApexInfoList submitStagedSession(int sessionId, @NonNull int[] childSessionIds) + throws PackageManagerException { + try { + final ApexInfoList apexInfoList = new ApexInfoList(); + mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList); + return apexInfoList; + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + throw new RuntimeException(re); + } catch (Exception e) { + throw new PackageManagerException( + PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "apexd verification failed : " + e.getMessage()); + } + } + + @Override + void markStagedSessionReady(int sessionId) throws PackageManagerException { + try { + mApexService.markStagedSessionReady(sessionId); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + throw new RuntimeException(re); + } catch (Exception e) { + throw new PackageManagerException( + PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Failed to mark apexd session as ready : " + e.getMessage()); + } + } + + @Override + void markStagedSessionSuccessful(int sessionId) { + try { + mApexService.markStagedSessionSuccessful(sessionId); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + throw new RuntimeException(re); + } catch (Exception e) { + // It is fine to just log an exception in this case. APEXd will be able to recover + // in case markStagedSessionSuccessful fails. + Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e); + } + } + + @Override + boolean isApexSupported() { + return true; + } + + @Override + boolean abortActiveSession() { + try { + mApexService.abortActiveSession(); + return true; + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + return false; + } + } + + @Override + boolean uninstallApex(String apexPackagePath) { + try { + mApexService.unstagePackages(Collections.singletonList(apexPackagePath)); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Dump information about the packages contained in a particular cache + * @param packagesCache the cache to print information about. + * @param packageName a {@link String} containing a package name, or {@code null}. If set, + * only information about that specific package will be dumped. + * @param ipw the {@link IndentingPrintWriter} object to send information to. + */ + void dumpFromPackagesCache( + List<PackageInfo> packagesCache, + @Nullable String packageName, + IndentingPrintWriter ipw) { ipw.println(); - ipw.println("Active APEX packages:"); - dumpFromPackagesCache(getActivePackages(), packageName, ipw); - ipw.println("Inactive APEX packages:"); - dumpFromPackagesCache(getInactivePackages(), packageName, ipw); - ipw.println("Factory APEX packages:"); - dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); - ipw.increaseIndent(); - ipw.println("APEX session state:"); ipw.increaseIndent(); - final ApexSessionInfo[] sessions = mApexService.getSessions(); - for (ApexSessionInfo si : sessions) { - ipw.println("Session ID: " + si.sessionId); - ipw.increaseIndent(); - if (si.isUnknown) { - ipw.println("State: UNKNOWN"); - } else if (si.isVerified) { - ipw.println("State: VERIFIED"); - } else if (si.isStaged) { - ipw.println("State: STAGED"); - } else if (si.isActivated) { - ipw.println("State: ACTIVATED"); - } else if (si.isActivationFailed) { - ipw.println("State: ACTIVATION FAILED"); - } else if (si.isSuccess) { - ipw.println("State: SUCCESS"); - } else if (si.isRollbackInProgress) { - ipw.println("State: ROLLBACK IN PROGRESS"); - } else if (si.isRolledBack) { - ipw.println("State: ROLLED BACK"); - } else if (si.isRollbackFailed) { - ipw.println("State: ROLLBACK FAILED"); + for (PackageInfo pi : packagesCache) { + if (packageName != null && !packageName.equals(pi.packageName)) { + continue; } + ipw.println(pi.packageName); + ipw.increaseIndent(); + ipw.println("Version: " + pi.versionCode); + ipw.println("Path: " + pi.applicationInfo.sourceDir); + ipw.println("IsActive: " + isActive(pi)); + ipw.println("IsFactory: " + isFactory(pi)); ipw.decreaseIndent(); } ipw.decreaseIndent(); - } catch (RemoteException e) { - ipw.println("Couldn't communicate with apexd."); + ipw.println(); + } + + @Override + void dump(PrintWriter pw, @Nullable String packageName) { + final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); + try { + populateAllPackagesCacheIfNeeded(); + ipw.println(); + ipw.println("Active APEX packages:"); + dumpFromPackagesCache(getActivePackages(), packageName, ipw); + ipw.println("Inactive APEX packages:"); + dumpFromPackagesCache(getInactivePackages(), packageName, ipw); + ipw.println("Factory APEX packages:"); + dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); + ipw.increaseIndent(); + ipw.println("APEX session state:"); + ipw.increaseIndent(); + final ApexSessionInfo[] sessions = mApexService.getSessions(); + for (ApexSessionInfo si : sessions) { + ipw.println("Session ID: " + si.sessionId); + ipw.increaseIndent(); + if (si.isUnknown) { + ipw.println("State: UNKNOWN"); + } else if (si.isVerified) { + ipw.println("State: VERIFIED"); + } else if (si.isStaged) { + ipw.println("State: STAGED"); + } else if (si.isActivated) { + ipw.println("State: ACTIVATED"); + } else if (si.isActivationFailed) { + ipw.println("State: ACTIVATION FAILED"); + } else if (si.isSuccess) { + ipw.println("State: SUCCESS"); + } else if (si.isRollbackInProgress) { + ipw.println("State: ROLLBACK IN PROGRESS"); + } else if (si.isRolledBack) { + ipw.println("State: ROLLED BACK"); + } else if (si.isRollbackFailed) { + ipw.println("State: ROLLBACK FAILED"); + } + ipw.decreaseIndent(); + } + ipw.decreaseIndent(); + } catch (RemoteException e) { + ipw.println("Couldn't communicate with apexd."); + } } } - public void onBootCompleted() { - if (!isApexSupported()) return; - populateAllPackagesCacheIfNeeded(); + /** + * An implementation of {@link ApexManager} that should be used in case device does not support + * updating APEX packages. + */ + private static final class ApexManagerNoOp extends ApexManager { + + @Override + void systemReady() { + // No-op + } + + @Override + PackageInfo getPackageInfo(String packageName, int flags) { + return null; + } + + @Override + List<PackageInfo> getActivePackages() { + return Collections.emptyList(); + } + + @Override + List<PackageInfo> getFactoryPackages() { + return Collections.emptyList(); + } + + @Override + List<PackageInfo> getInactivePackages() { + return Collections.emptyList(); + } + + @Override + boolean isApexPackage(String packageName) { + return false; + } + + @Override + ApexSessionInfo getStagedSessionInfo(int sessionId) { + throw new UnsupportedOperationException(); + } + + @Override + ApexInfoList submitStagedSession(int sessionId, int[] childSessionIds) + throws PackageManagerException { + throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, + "Device doesn't support updating APEX"); + } + + @Override + void markStagedSessionReady(int sessionId) { + throw new UnsupportedOperationException(); + } + + @Override + void markStagedSessionSuccessful(int sessionId) { + throw new UnsupportedOperationException(); + } + + @Override + boolean isApexSupported() { + return false; + } + + @Override + boolean abortActiveSession() { + throw new UnsupportedOperationException(); + } + + @Override + boolean uninstallApex(String apexPackagePath) { + throw new UnsupportedOperationException(); + } + + @Override + void dump(PrintWriter pw, String packageName) { + // No-op + } } } diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index 8facce112b52..dbe83670d3a0 100644 --- a/services/core/java/com/android/server/pm/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/ComponentResolver.java @@ -49,6 +49,7 @@ import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ArrayUtils; import com.android.server.IntentResolver; import java.io.PrintWriter; @@ -375,8 +376,11 @@ public class ComponentResolver { addProvidersLocked(pkg, chatty); addServicesLocked(pkg, chatty); } - final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName( - PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM); + // expect single setupwizard package + final String setupWizardPackage = ArrayUtils.firstOrNull( + sPackageManagerInternal.getKnownPackageNames( + PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); + for (int i = newIntents.size() - 1; i >= 0; --i) { final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i); final PackageParser.Package disabledPkg = sPackageManagerInternal @@ -410,8 +414,11 @@ public class ComponentResolver { final List<ActivityIntentInfo> protectedFilters = mProtectedFilters; mProtectedFilters = null; - final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName( - PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM); + // expect single setupwizard package + final String setupWizardPackage = ArrayUtils.firstOrNull( + sPackageManagerInternal.getKnownPackageNames( + PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); + if (DEBUG_FILTERS && setupWizardPackage == null) { Slog.i(TAG, "No setup wizard;" + " All protected intents capped to priority 0"); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0460a80b1dc0..54051ba64f8c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1406,6 +1406,7 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mConfiguratorPackage; final @Nullable String mAppPredictionServicePackage; final @Nullable String mIncidentReportApproverPackage; + final @Nullable String[] mTelephonyPackages; final @NonNull String mServicesSystemSharedLibraryPackageName; final @NonNull String mSharedSystemSharedLibraryPackageName; @@ -2474,7 +2475,8 @@ public class PackageManagerService extends IPackageManager.Stub mProtectedPackages = new ProtectedPackages(mContext); - mApexManager = new ApexManager(context); + mApexManager = ApexManager.create(context); + // CHECKSTYLE:OFF IndentationCheck synchronized (mInstallLock) { // writer synchronized (mPackages) { @@ -3115,6 +3117,7 @@ public class PackageManagerService extends IPackageManager.Stub mContext.getString(R.string.config_deviceConfiguratorPackageName); mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); + mTelephonyPackages = getTelephonyPackageNames(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -4262,7 +4265,7 @@ public class PackageManagerService extends IPackageManager.Stub } return generatePackageInfo(ps, flags, userId); } - if (!matchFactoryOnly && (flags & MATCH_APEX) != 0) { + if ((flags & MATCH_APEX) != 0) { return mApexManager.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); } } @@ -9334,6 +9337,16 @@ public class PackageManagerService extends IPackageManager.Stub pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting; pkgAlreadyExists = pkgSetting != null; final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName; + if (scanSystemPartition && !pkgAlreadyExists + && mSettings.getDisabledSystemPkgLPr(disabledPkgName) != null) { + // The updated-package data for /system apk remains inconsistently + // after the package data for /data apk is lost accidentally. + // To recover it, enable /system apk and install it as non-updated system app. + Slog.w(TAG, "Inconsistent package setting of updated system app for " + + disabledPkgName + ". To recover it, enable the system app" + + "and install it as non-updated system app."); + mSettings.removeDisabledSystemPackageLPw(disabledPkgName); + } disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(disabledPkgName); isSystemPkgUpdated = disabledPkgSetting != null; @@ -21164,6 +21177,16 @@ public class PackageManagerService extends IPackageManager.Stub } @Override + public String[] getTelephonyPackageNames() { + String names = mContext.getString(R.string.config_telephonyPackages); + String[] telephonyPackageNames = null; + if (!TextUtils.isEmpty(names)) { + telephonyPackageNames = names.trim().split(","); + } + return telephonyPackageNames; + } + + @Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return; @@ -24312,34 +24335,36 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public String getKnownPackageName(int knownPackage, int userId) { + public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) { switch(knownPackage) { case PackageManagerInternal.PACKAGE_BROWSER: - return getDefaultBrowserPackageName(userId); + return new String[]{getDefaultBrowserPackageName(userId)}; case PackageManagerInternal.PACKAGE_INSTALLER: - return mRequiredInstallerPackage; + return new String[]{mRequiredInstallerPackage}; case PackageManagerInternal.PACKAGE_SETUP_WIZARD: - return mSetupWizardPackage; + return new String[]{mSetupWizardPackage}; case PackageManagerInternal.PACKAGE_SYSTEM: - return "android"; + return new String[]{"android"}; case PackageManagerInternal.PACKAGE_VERIFIER: - return mRequiredVerifierPackage; + return new String[]{mRequiredVerifierPackage}; case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER: - return mSystemTextClassifierPackage; + return new String[]{mSystemTextClassifierPackage}; case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER: - return mRequiredPermissionControllerPackage; + return new String[]{mRequiredPermissionControllerPackage}; case PackageManagerInternal.PACKAGE_WELLBEING: - return mWellbeingPackage; + return new String[]{mWellbeingPackage}; case PackageManagerInternal.PACKAGE_DOCUMENTER: - return mDocumenterPackage; + return new String[]{mDocumenterPackage}; case PackageManagerInternal.PACKAGE_CONFIGURATOR: - return mConfiguratorPackage; + return new String[]{mConfiguratorPackage}; case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER: - return mIncidentReportApproverPackage; + return new String[]{mIncidentReportApproverPackage}; case PackageManagerInternal.PACKAGE_APP_PREDICTOR: - return mAppPredictionServicePackage; + return new String[]{mAppPredictionServicePackage}; + case PackageManagerInternal.PACKAGE_TELEPHONY: + return mTelephonyPackages; } - return null; + return ArrayUtils.emptyArray(String.class); } @Override @@ -24495,6 +24520,12 @@ public class PackageManagerService extends IPackageManager.Stub public List<ResolveInfo> queryIntentActivities( Intent intent, int flags, int filterCallingUid, int userId) { final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver()); + return queryIntentActivities(intent, resolvedType, flags, filterCallingUid, userId); + } + + @Override + public List<ResolveInfo> queryIntentActivities( + Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) { return PackageManagerService.this .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid, userId, false /*resolveForStart*/, true /*allowDynamicSplits*/); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 3bc2236a8221..4ecfbfee6e65 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3337,7 +3337,8 @@ public final class Settings { int flags, ComponentName cn, String scheme, PatternMatcher ssp, IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) { final List<ResolveInfo> ri = - pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0); + pmInternal.queryIntentActivities( + intent, intent.getType(), flags, Binder.getCallingUid(), 0); if (PackageManagerService.DEBUG_PREFERRED) { Log.d(TAG, "Queried " + intent + " results: " + ri); } diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 88d681f973c4..2705455078ff 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -30,6 +30,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageParser.SigningDetails; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; @@ -43,6 +44,7 @@ import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.apk.ApkSignatureVerifier; @@ -104,21 +106,22 @@ public class StagingManager { return new ParceledListSlice<>(result); } - private boolean validateApexSignature(String apexPath, String apexModuleName) { + private void validateApexSignature(String apexPath, String packageName) + throws PackageManagerException { final SigningDetails signingDetails; try { signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR); } catch (PackageParserException e) { - Slog.e(TAG, "Unable to parse APEX package: " + apexPath, e); - return false; + throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Failed to parse APEX package " + apexPath, e); } - final PackageInfo packageInfo = mApexManager.getPackageInfoForApexName(apexModuleName); - + final PackageInfo packageInfo = mApexManager.getPackageInfo(packageName, + ApexManager.MATCH_ACTIVE_PACKAGE); if (packageInfo == null) { - // Don't allow installation of new APEX. - Slog.e(TAG, "Attempted to install a new apex " + apexModuleName + ". Rejecting"); - return false; + // This should never happen, because submitSessionToApexService ensures that no new + // apexes were installed. + throw new IllegalStateException("Unknown apex package " + packageName); } final SigningDetails existingSigningDetails; @@ -126,73 +129,99 @@ public class StagingManager { existingSigningDetails = ApkSignatureVerifier.verify( packageInfo.applicationInfo.sourceDir, SignatureSchemeVersion.JAR); } catch (PackageParserException e) { - Slog.e(TAG, "Unable to parse APEX package: " - + packageInfo.applicationInfo.sourceDir, e); - return false; + throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Failed to parse APEX package " + packageInfo.applicationInfo.sourceDir, e); } // Now that we have both sets of signatures, demand that they're an exact match. if (Signature.areExactMatch(existingSigningDetails.signatures, signingDetails.signatures)) { - return true; + return; } - return false; + throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "APK-container signature verification failed for package " + + packageName + ". Signature of file " + + apexPath + " does not match the signature of " + + " the package already installed."); } - private boolean submitSessionToApexService(@NonNull PackageInstallerSession session, - List<PackageInstallerSession> childSessions, - ApexInfoList apexInfoList) { - boolean submittedToApexd = mApexManager.submitStagedSession( - session.sessionId, - childSessions != null - ? childSessions.stream().mapToInt(s -> s.sessionId).toArray() : - new int[]{}, - apexInfoList); - if (!submittedToApexd) { - session.setStagedSessionFailed( - SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "APEX staging failed, check logcat messages from apexd for more details."); - return false; + private List<PackageInfo> submitSessionToApexService( + @NonNull PackageInstallerSession session) throws PackageManagerException { + final IntArray childSessionsIds = new IntArray(); + if (session.isMultiPackage()) { + for (int id : session.getChildSessionIds()) { + if (isApexSession(mStagedSessions.get(id))) { + childSessionsIds.add(id); + } + } } - for (ApexInfo newModule : apexInfoList.apexInfos) { - PackageInfo activePackage = mApexManager.getPackageInfoForApexName( - newModule.moduleName); + // submitStagedSession will throw a PackageManagerException if apexd verification fails, + // which will be propagated to populate stagedSessionErrorMessage of this session. + final ApexInfoList apexInfoList = mApexManager.submitStagedSession(session.sessionId, + childSessionsIds.toArray()); + final List<PackageInfo> result = new ArrayList<>(); + for (ApexInfo apexInfo : apexInfoList.apexInfos) { + final PackageInfo packageInfo; + int flags = PackageManager.GET_META_DATA; + PackageParser.Package pkg; + try { + File apexFile = new File(apexInfo.modulePath); + PackageParser pp = new PackageParser(); + pkg = pp.parsePackage(apexFile, flags, false); + } catch (PackageParserException e) { + throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Failed to parse APEX package " + apexInfo.modulePath, e); + } + packageInfo = PackageParser.generatePackageInfo(pkg, apexInfo, flags); + final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName, + ApexManager.MATCH_ACTIVE_PACKAGE); if (activePackage == null) { - continue; - } - long activeVersion = activePackage.applicationInfo.longVersionCode; - if (session.params.requiredInstalledVersionCode - != PackageManager.VERSION_CODE_HIGHEST) { - if (activeVersion != session.params.requiredInstalledVersionCode) { - session.setStagedSessionFailed( - SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Installed version of APEX package " + activePackage.packageName - + " does not match required. Active version: " + activeVersion - + " required: " + session.params.requiredInstalledVersionCode); - - if (!mApexManager.abortActiveSession()) { - Slog.e(TAG, "Failed to abort apex session " + session.sessionId); - } - return false; - } + Slog.w(TAG, "Attempting to install new APEX package " + packageInfo.packageName); + throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "It is forbidden to install new APEX packages."); } + checkRequiredVersionCode(session, activePackage); + checkDowngrade(session, activePackage, packageInfo); + result.add(packageInfo); + } + return result; + } - boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( - session.params.installFlags, activePackage.applicationInfo.flags); - if (activeVersion > newModule.versionCode && !allowsDowngrade) { - session.setStagedSessionFailed( - SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Downgrade of APEX package " + activePackage.packageName - + " is not allowed. Active version: " + activeVersion - + " attempted: " + newModule.versionCode); + private void checkRequiredVersionCode(final PackageInstallerSession session, + final PackageInfo activePackage) throws PackageManagerException { + if (session.params.requiredInstalledVersionCode == PackageManager.VERSION_CODE_HIGHEST) { + return; + } + final long activeVersion = activePackage.applicationInfo.longVersionCode; + if (activeVersion != session.params.requiredInstalledVersionCode) { + if (!mApexManager.abortActiveSession()) { + Slog.e(TAG, "Failed to abort apex session " + session.sessionId); + } + throw new PackageManagerException( + SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Installed version of APEX package " + activePackage.packageName + + " does not match required. Active version: " + activeVersion + + " required: " + session.params.requiredInstalledVersionCode); + } + } - if (!mApexManager.abortActiveSession()) { - Slog.e(TAG, "Failed to abort apex session " + session.sessionId); - } - return false; + private void checkDowngrade(final PackageInstallerSession session, + final PackageInfo activePackage, final PackageInfo newPackage) + throws PackageManagerException { + final long activeVersion = activePackage.applicationInfo.longVersionCode; + final long newVersionCode = newPackage.applicationInfo.longVersionCode; + boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( + session.params.installFlags, activePackage.applicationInfo.flags); + if (activeVersion > newVersionCode && !allowsDowngrade) { + if (!mApexManager.abortActiveSession()) { + Slog.e(TAG, "Failed to abort apex session " + session.sessionId); } + throw new PackageManagerException( + SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, + "Downgrade of APEX package " + newPackage.packageName + + " is not allowed. Active version: " + activeVersion + + " attempted: " + newVersionCode); } - return true; } private static boolean isApexSession(@NonNull PackageInstallerSession session) { @@ -200,31 +229,20 @@ public class StagingManager { } private void preRebootVerification(@NonNull PackageInstallerSession session) { - boolean success = true; - - final ApexInfoList apexInfoList = new ApexInfoList(); + final boolean hasApex = sessionContainsApex(session); // APEX checks. For single-package sessions, check if they contain an APEX. For // multi-package sessions, find all the child sessions that contain an APEX. - if (!session.isMultiPackage() - && isApexSession(session)) { - success = submitSessionToApexService(session, null, apexInfoList); - - } else if (session.isMultiPackage()) { - List<PackageInstallerSession> childSessions = - Arrays.stream(session.getChildSessionIds()) - // Retrieve cached sessions matching ids. - .mapToObj(i -> mStagedSessions.get(i)) - // Filter only the ones containing APEX. - .filter(childSession -> isApexSession(childSession)) - .collect(Collectors.toList()); - if (!childSessions.isEmpty()) { - success = submitSessionToApexService(session, childSessions, apexInfoList); - } // else this is a staged multi-package session with no APEX files. - } - - if (!success) { - // submitSessionToApexService will populate error. - return; + if (hasApex) { + try { + final List<PackageInfo> apexPackages = submitSessionToApexService(session); + for (PackageInfo apexPackage : apexPackages) { + validateApexSignature(apexPackage.applicationInfo.sourceDir, + apexPackage.packageName); + } + } catch (PackageManagerException e) { + session.setStagedSessionFailed(e.error, e.getMessage()); + return; + } } if (sessionContainsApk(session)) { @@ -237,25 +255,6 @@ public class StagingManager { } } - if (apexInfoList.apexInfos != null && apexInfoList.apexInfos.length > 0) { - // For APEXes, we validate the signature here before we mark the session as ready, - // so we fail the session early if there is a signature mismatch. For APKs, the - // signature verification will be done by the package manager at the point at which - // it applies the staged install. - for (ApexInfo apexModule : apexInfoList.apexInfos) { - if (!validateApexSignature(apexModule.modulePath, - apexModule.moduleName)) { - session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "APK-container signature verification failed for package " - + apexModule.moduleName + ". Signature of file " - + apexModule.modulePath + " does not match the signature of " - + " the package already installed."); - // TODO(b/118865310): abort the session on apexd. - return; - } - } - } - if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) { // If rollback is enabled for this session, we call through to the RollbackManager // with the list of sessions it must enable rollback for. Note that notifyStagedSession @@ -273,12 +272,24 @@ public class StagingManager { } } + // Proactively mark session as ready before calling apexd. Although this call order looks + // counter-intuitive, this is the easiest way to ensure that session won't end up in the + // inconsistent state: + // - If device gets rebooted right before call to apexd, then apexd will never activate + // apex files of this staged session. This will result in StagingManager failing the + // session. + // On the other hand, if the order of the calls was inverted (first call apexd, then mark + // session as ready), then if a device gets rebooted right after the call to apexd, only + // apex part of the train will be applied, leaving device in an inconsistent state. session.setStagedSessionReady(); - if (sessionContainsApex(session) - && !mApexManager.markStagedSessionReady(session.sessionId)) { - session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "APEX staging failed, check logcat messages from apexd for more " - + "details."); + if (!hasApex) { + // Session doesn't contain apex, nothing to do. + return; + } + try { + mApexManager.markStagedSessionReady(session.sessionId); + } catch (PackageManagerException e) { + session.setStagedSessionFailed(e.error, e.getMessage()); } } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 9948a3ad47da..b8d3ca56e368 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -317,9 +317,13 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { case ArtManager.PROFILE_APPS : return SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); case ArtManager.PROFILE_BOOT_IMAGE: + // The device config property overrides the system property version. + boolean profileBootClassPath = SystemProperties.getBoolean( + "persist.device_config.runtime_native_boot.profilebootclasspath", + SystemProperties.getBoolean("dalvik.vm.profilebootclasspath", false)); return (Build.IS_USERDEBUG || Build.IS_ENG) && SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false) && - SystemProperties.getBoolean("dalvik.vm.profilebootimage", false); + profileBootClassPath; default: throw new IllegalArgumentException("Invalid profile type:" + profileType); } diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 6d22faa7032e..c39dcfefb2e8 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -276,6 +276,9 @@ public final class BasePermission { public boolean isAppPredictor() { return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0; } + public boolean isTelephony() { + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0; + } public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { if (!origPackageName.equals(sourcePackageName)) { diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index f76298592c2b..5870986a264f 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -436,17 +436,20 @@ public final class DefaultPermissionGrantPolicy { // Installer grantSystemFixedPermissionsToSystemPackage( - getKnownPackage(PackageManagerInternal.PACKAGE_INSTALLER, userId), + ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_INSTALLER, userId)), userId, STORAGE_PERMISSIONS); // Verifier - final String verifier = getKnownPackage(PackageManagerInternal.PACKAGE_VERIFIER, userId); + final String verifier = ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_VERIFIER, userId)); grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS); grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS); // SetupWizard grantPermissionsToSystemPackage( - getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId, + ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId, PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CAMERA_PERMISSIONS); @@ -595,7 +598,8 @@ public final class DefaultPermissionGrantPolicy { userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS); // Browser - String browserPackage = getKnownPackage(PackageManagerInternal.PACKAGE_BROWSER, userId); + String browserPackage = ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_BROWSER, userId)); if (browserPackage == null) { browserPackage = getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_BROWSER, userId); @@ -760,8 +764,8 @@ public final class DefaultPermissionGrantPolicy { } } - private String getKnownPackage(int knownPkgId, int userId) { - return mServiceInternal.getKnownPackageName(knownPkgId, userId); + private @NonNull String[] getKnownPackages(int knownPkgId, int userId) { + return mServiceInternal.getKnownPackageNames(knownPkgId, userId); } private void grantDefaultPermissionsToDefaultSystemDialerApp( diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 6d1f2d3e1e57..6a7c622b7e33 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1706,8 +1706,9 @@ public class PermissionManagerService { } } } - final String systemPackageName = mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM); + // expect single system package + String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM)); final PackageParser.Package systemPackage = mPackageManagerInt.getPackage(systemPackageName); @@ -1823,18 +1824,19 @@ public class PermissionManagerService { // need a separate flag anymore. Hence we need to check which // permissions are needed by the permission controller if (!allowed && bp.isInstaller() - && (pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM)) - || pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM), + pkg.packageName) || ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER, - UserHandle.USER_SYSTEM)))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // If this permission is to be granted to the system installer and // this app is an installer, then it gets the permission. allowed = true; } if (!allowed && bp.isVerifier() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the system verifier and // this app is a verifier, then it gets the permission. allowed = true; @@ -1850,53 +1852,64 @@ public class PermissionManagerService { allowed = origPermissions.hasInstallPermission(perm); } if (!allowed && bp.isSetup() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the system setup wizard and // this app is a setup wizard, then it gets the permission. allowed = true; } if (!allowed && bp.isSystemTextClassifier() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER, - UserHandle.USER_SYSTEM))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // Special permissions for the system default text classifier. allowed = true; } if (!allowed && bp.isConfigurator() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_CONFIGURATOR, - UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_CONFIGURATOR, + UserHandle.USER_SYSTEM), pkg.packageName)) { // Special permissions for the device configurator. allowed = true; } if (!allowed && bp.isWellbeing() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM), + pkg.packageName)) { // Special permission granted only to the OEM specified wellbeing app allowed = true; } if (!allowed && bp.isDocumenter() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the documenter and // this app is the documenter, then it gets the permission. allowed = true; } if (!allowed && bp.isIncidentReportApprover() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER, - UserHandle.USER_SYSTEM))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // If this permission is to be granted to the incident report approver and // this app is the incident report approver, then it gets the permission. allowed = true; } if (!allowed && bp.isAppPredictor() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM), + pkg.packageName)) { // Special permissions for the system app predictor. allowed = true; } + if (!allowed && bp.isTelephony() + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_TELEPHONY, UserHandle.USER_SYSTEM), + pkg.packageName)) { + // Special permissions for the system telephony apps. + allowed = true; + } } return allowed; } diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 28c171bdeb98..9347d2194b68 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -32,6 +32,7 @@ import android.app.timezone.IRulesManager; import android.app.timezone.RulesManager; import android.app.timezone.RulesState; import android.content.Context; +import android.icu.util.TimeZone; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Slog; @@ -45,7 +46,6 @@ import com.android.timezone.distro.StagedDistroOperation; import com.android.timezone.distro.TimeZoneDistro; import com.android.timezone.distro.installer.TimeZoneDistroInstaller; -import libcore.icu.ICU; import libcore.timezone.TimeZoneDataFiles; import libcore.timezone.TimeZoneFinder; import libcore.timezone.TzDataSetVersion; @@ -519,7 +519,7 @@ public final class RulesManagerService extends IRulesManager.Stub { // Report the active rules version (i.e. the rules in use by the current // process). pw.println("Active rules version (ICU, ZoneInfoDB, TimeZoneFinder): " - + ICU.getTZDataVersion() + "," + + TimeZone.getTZDataVersion() + "," + ZoneInfoDB.getInstance().getVersion() + "," + TimeZoneFinder.getInstance().getIanaVersion()); break; @@ -535,7 +535,7 @@ public final class RulesManagerService extends IRulesManager.Stub { pw.println("RulesManagerService state: " + toString()); pw.println("Active rules version (ICU, ZoneInfoDB, TimeZoneFinder): " - + ICU.getTZDataVersion() + "," + + TimeZone.getTZDataVersion() + "," + ZoneInfoDB.getInstance().getVersion() + "," + TimeZoneFinder.getInstance().getIanaVersion()); pw.println("Distro state: " + rulesState.toString()); diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java index 852f70779f77..cb0b45ceaf05 100644 --- a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java +++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java @@ -18,6 +18,7 @@ package com.android.server.updates; import android.content.Context; import android.content.Intent; +import android.telephony.TelephonyManager; import android.util.Slog; /** @@ -34,6 +35,11 @@ public class EmergencyNumberDbInstallReceiver extends ConfigUpdateInstallReceive @Override protected void postInstall(Context context, Intent intent) { Slog.i(TAG, "Emergency number database is updated in file partition"); - // TODO Send a notification to EmergencyNumberTracker for updating of emergency number db. + + // Notify EmergencyNumberTracker for emergency number installation complete. + Intent notifyInstallComplete = new Intent( + TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED); + context.sendBroadcast( + notifyInstallComplete, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); } } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 3bc239b53529..6175d4183020 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -23,7 +23,6 @@ cc_library_static { "com_android_server_AlarmManagerService.cpp", "com_android_server_am_BatteryStatsService.cpp", "com_android_server_connectivity_Vpn.cpp", - "com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp", "com_android_server_ConsumerIrService.cpp", "com_android_server_devicepolicy_CryptoTestHelper.cpp", "com_android_server_HardwarePropertiesManagerService.cpp", @@ -54,6 +53,7 @@ cc_library_static { "com_android_server_am_LowMemDetector.cpp", "onload.cpp", ":lib_networkStatsFactory_native", + ":tethering-jni-srcs", ], include_dirs: [ @@ -130,11 +130,13 @@ cc_defaults { "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", "android.hardware.vibrator@1.3", + "android.hardware.vibrator@1.4", "android.hardware.vr@1.0", "android.frameworks.schedulerservice@1.0", "android.frameworks.sensorservice@1.0", "android.system.suspend@1.0", "suspend_control_aidl_interface-cpp", + "vintf-vibrator-cpp", ], static_libs: [ diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index c59e6056b72e..372622801aa0 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -16,17 +16,15 @@ #define LOG_TAG "VibratorService" -#include <android/hardware/vibrator/1.0/IVibrator.h> -#include <android/hardware/vibrator/1.0/types.h> -#include <android/hardware/vibrator/1.0/IVibrator.h> -#include <android/hardware/vibrator/1.1/types.h> -#include <android/hardware/vibrator/1.2/IVibrator.h> -#include <android/hardware/vibrator/1.2/types.h> -#include <android/hardware/vibrator/1.3/IVibrator.h> +#include <android/hardware/vibrator/1.4/IVibrator.h> +#include <android/hardware/vibrator/BnVibratorCallback.h> +#include <android/hardware/vibrator/IVibrator.h> +#include <binder/IServiceManager.h> #include "jni.h" #include <nativehelper/JNIHelp.h> #include "android_runtime/AndroidRuntime.h" +#include "core_jni_helpers.h" #include <utils/misc.h> #include <utils/Log.h> @@ -36,6 +34,7 @@ #include <stdio.h> using android::hardware::Return; +using android::hardware::Void; using android::hardware::vibrator::V1_0::EffectStrength; using android::hardware::vibrator::V1_0::Status; using android::hardware::vibrator::V1_1::Effect_1_1; @@ -44,9 +43,185 @@ namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; namespace V1_3 = android::hardware::vibrator::V1_3; +namespace V1_4 = android::hardware::vibrator::V1_4; +namespace aidl = android::hardware::vibrator; namespace android { +static jmethodID sMethodIdOnComplete; + +// TODO(b/141828236): remove HIDL 1.4 and re-write all of this code to remove +// shim +class VibratorShim : public V1_4::IVibrator { + public: + VibratorShim(const sp<aidl::IVibrator>& vib) : mVib(vib) {} + + Return<V1_0::Status> on(uint32_t timeoutMs) override { + return on_1_4(timeoutMs, nullptr); + } + + Return<V1_0::Status> off() override { + return toHidlStatus(mVib->off()); + } + + Return<bool> supportsAmplitudeControl() override { + int32_t cap = 0; + if (!mVib->getCapabilities(&cap).isOk()) return false; + if (mUnderExternalControl) { + return (cap & aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0; + } else { + return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0; + } + } + + Return<V1_0::Status> setAmplitude(uint8_t amplitude) override { + return toHidlStatus(mVib->setAmplitude(amplitude)); + } + + Return<void> perform(V1_0::Effect effect, V1_0::EffectStrength strength, + perform_cb _hidl_cb) override { + return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); + } + + Return<void> perform_1_1(V1_1::Effect_1_1 effect, V1_0::EffectStrength strength, + perform_1_1_cb _hidl_cb) override { + return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); + } + + Return<void> perform_1_2(V1_2::Effect effect, V1_0::EffectStrength strength, + perform_1_2_cb _hidl_cb) override { + return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); + } + + Return<bool> supportsExternalControl() override { + int32_t cap = 0; + if (!mVib->getCapabilities(&cap).isOk()) return false; + return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0; + } + + Return<V1_0::Status> setExternalControl(bool enabled) override { + Return<V1_0::Status> status = toHidlStatus(mVib->setExternalControl(enabled)); + if (status.isOk() && status == V1_0::Status::OK) { + mUnderExternalControl = enabled; + } + return status; + } + + Return<void> perform_1_3(V1_3::Effect effect, V1_0::EffectStrength strength, + perform_1_3_cb _hidl_cb) override { + return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); + } + + Return<uint32_t> getCapabilities() override { + static_assert(static_cast<int32_t>(V1_4::Capabilities::ON_COMPLETION_CALLBACK) == + static_cast<int32_t>(aidl::IVibrator::CAP_ON_CALLBACK)); + static_assert(static_cast<int32_t>(V1_4::Capabilities::PERFORM_COMPLETION_CALLBACK) == + static_cast<int32_t>(aidl::IVibrator::CAP_PERFORM_CALLBACK)); + + int32_t cap; + if (!mVib->getCapabilities(&cap).isOk()) return 0; + return (cap & (aidl::IVibrator::CAP_ON_CALLBACK | + aidl::IVibrator::CAP_PERFORM_CALLBACK)) > 0; + } + + Return<V1_0::Status> on_1_4(uint32_t timeoutMs, + const sp<V1_4::IVibratorCallback>& callback) override { + sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr; + return toHidlStatus(mVib->on(timeoutMs, cb)); + } + + Return<void> perform_1_4(V1_3::Effect effect, V1_0::EffectStrength strength, + const sp<V1_4::IVibratorCallback>& callback, + perform_1_4_cb _hidl_cb) override { + static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == + static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); + static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == + static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); + static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == + static_cast<uint8_t>(aidl::EffectStrength::STRONG)); + static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == + static_cast<uint8_t>(aidl::Effect::CLICK)); + static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == + static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); + static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == + static_cast<uint8_t>(aidl::Effect::TICK)); + static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == + static_cast<uint8_t>(aidl::Effect::THUD)); + static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == + static_cast<uint8_t>(aidl::Effect::POP)); + static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == + static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); + static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); + static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); + static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); + static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == + static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); + + sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr; + int timeoutMs = 0; + Return<V1_0::Status> status = toHidlStatus( + mVib->perform(static_cast<aidl::Effect>(effect), + static_cast<aidl::EffectStrength>(strength), cb, &timeoutMs)); + + if (status.isOk()) { + _hidl_cb(status, timeoutMs); + return android::hardware::Status::ok(); + } else { + return android::hardware::details::StatusOf<V1_0::Status, void>(status); + } + } + private: + sp<aidl::IVibrator> mVib; + bool mUnderExternalControl = false; + + Return<V1_0::Status> toHidlStatus(const android::binder::Status& status) { + switch(status.exceptionCode()) { + using android::hardware::Status; + case Status::EX_NONE: return V1_0::Status::OK; + case Status::EX_ILLEGAL_ARGUMENT: return V1_0::Status::BAD_VALUE; + case Status::EX_UNSUPPORTED_OPERATION: return V1_0::Status::UNSUPPORTED_OPERATION; + case Status::EX_TRANSACTION_FAILED: { + return Status::fromStatusT(status.transactionError()); + } + } + return V1_0::Status::UNKNOWN_ERROR; + } + + class CallbackShim : public aidl::BnVibratorCallback { + public: + CallbackShim(const sp<V1_4::IVibratorCallback>& cb) : mCb(cb) {} + binder::Status onComplete() { + mCb->onComplete(); + return binder::Status::ok(); // oneway, local call + } + private: + sp<V1_4::IVibratorCallback> mCb; + }; +}; + +class VibratorCallback : public V1_4::IVibratorCallback { + public: + VibratorCallback(JNIEnv *env, jobject vibration) : + mVibration(MakeGlobalRefOrDie(env, vibration)) {} + + ~VibratorCallback() { + JNIEnv *env = AndroidRuntime::getJNIEnv(); + env->DeleteGlobalRef(mVibration); + } + + Return<void> onComplete() override { + auto env = AndroidRuntime::getJNIEnv(); + env->CallVoidMethod(mVibration, sMethodIdOnComplete); + return Void(); + } + + private: + jobject mVibration; +}; + static constexpr int NUM_TRIES = 2; // Creates a Return<R> with STATUS::EX_NULL_POINTER. @@ -56,37 +231,68 @@ inline Return<R> NullptrStatus() { return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)}; } -// Helper used to transparently deal with the vibrator HAL becoming unavailable. -template<class R, class I, class... Args0, class... Args1> -Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) { - // Assume that if getService returns a nullptr, HAL is not available on the - // device. - static sp<I> sHal = I::getService(); - static bool sAvailable = sHal != nullptr; +template <typename I> +class HalWrapper { + public: + static std::unique_ptr<HalWrapper> Create() { + sp<aidl::IVibrator> aidlVib = waitForVintfService<aidl::IVibrator>(); + if (aidlVib) { + return std::unique_ptr<HalWrapper>(new HalWrapper(new VibratorShim(aidlVib))); + } - if (!sAvailable) { - return NullptrStatus<R>(); + // Assume that if getService returns a nullptr, HAL is not available on the + // device. + auto hal = I::getService(); + return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; } - // Return<R> doesn't have a default constructor, so make a Return<R> with - // STATUS::EX_NONE. - using ::android::hardware::Status; - Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)}; + // Helper used to transparently deal with the vibrator HAL becoming unavailable. + template<class R, class... Args0, class... Args1> + Return<R> call(Return<R> (I::* fn)(Args0...), Args1&&... args1) { + // Return<R> doesn't have a default constructor, so make a Return<R> with + // STATUS::EX_NONE. + using ::android::hardware::Status; + Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)}; + + // Note that ret is guaranteed to be changed after this loop. + for (int i = 0; i < NUM_TRIES; ++i) { + ret = (mHal == nullptr) ? NullptrStatus<R>() + : (*mHal.*fn)(std::forward<Args1>(args1)...); + + if (ret.isOk()) { + break; + } + + ALOGE("Failed to issue command to vibrator HAL. Retrying."); + + // Restoring connection to the HAL. + sp<aidl::IVibrator> aidlVib = checkVintfService<aidl::IVibrator>(); + if (aidlVib) { + mHal = new VibratorShim(aidlVib); + } else { + mHal = I::tryGetService(); + } + } + return ret; + } - // Note that ret is guaranteed to be changed after this loop. - for (int i = 0; i < NUM_TRIES; ++i) { - ret = (sHal == nullptr) ? NullptrStatus<R>() - : (*sHal.*fn)(std::forward<Args1>(args1)...); + private: + HalWrapper(sp<I> &&hal) : mHal(std::move(hal)) {} - if (ret.isOk()) { - break; - } + private: + sp<I> mHal; +}; - ALOGE("Failed to issue command to vibrator HAL. Retrying."); - // Restoring connection to the HAL. - sHal = I::tryGetService(); - } - return ret; +template <typename I> +static auto getHal() { + static auto sHalWrapper = HalWrapper<I>::Create(); + return sHalWrapper.get(); +} + +template<class R, class I, class... Args0, class... Args1> +Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) { + auto hal = getHal<I>(); + return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>(); } template<class R> @@ -99,17 +305,17 @@ bool isValidEffect(jlong effect) { return val >= *iter.begin() && val <= *std::prev(iter.end()); } -static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) +static void vibratorInit(JNIEnv *env, jclass clazz) { halCall(&V1_0::IVibrator::ping).isOk(); } -static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) +static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */) { return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE; } -static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) +static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms) { Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR); if (retStatus != Status::OK) { @@ -117,7 +323,7 @@ static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) } } -static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) +static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */) { Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR); if (retStatus != Status::OK) { @@ -125,11 +331,11 @@ static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) } } -static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { +static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) { return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false); } -static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { +static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) { Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude)) .withDefault(Status::UNKNOWN_ERROR); if (status != Status::OK) { @@ -138,11 +344,11 @@ static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { } } -static jboolean vibratorSupportsExternalControl(JNIEnv*, jobject) { +static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) { return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false); } -static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) { +static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) { Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled)) .withDefault(Status::UNKNOWN_ERROR); if (status != Status::OK) { @@ -151,7 +357,8 @@ static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) { } } -static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jlong strength) { +static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength, + jobject vibration) { Status status; uint32_t lengthMs; auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { @@ -161,7 +368,11 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jlong strengt EffectStrength effectStrength(static_cast<EffectStrength>(strength)); Return<void> ret; - if (isValidEffect<V1_0::Effect>(effect)) { + if (auto hal = getHal<V1_4::IVibrator>(); hal && isValidEffect<V1_3::Effect>(effect)) { + sp<VibratorCallback> effectCallback = new VibratorCallback(env, vibration); + ret = hal->call(&V1_4::IVibrator::perform_1_4, static_cast<V1_3::Effect>(effect), + effectStrength, effectCallback, callback); + } else if (isValidEffect<V1_0::Effect>(effect)) { ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect), effectStrength, callback); } else if (isValidEffect<Effect_1_1>(effect)) { @@ -198,6 +409,10 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jlong strengt return -1; } +static jlong vibratorGetCapabilities(JNIEnv*, jclass) { + return halCall(&V1_4::IVibrator::getCapabilities).withDefault(0); +} + static const JNINativeMethod method_table[] = { { "vibratorExists", "()Z", (void*)vibratorExists }, { "vibratorInit", "()V", (void*)vibratorInit }, @@ -205,13 +420,18 @@ static const JNINativeMethod method_table[] = { { "vibratorOff", "()V", (void*)vibratorOff }, { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl}, { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude}, - { "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect}, + { "vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;)J", + (void*)vibratorPerformEffect}, { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl}, { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl}, + { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities}, }; int register_android_server_VibratorService(JNIEnv *env) { + sMethodIdOnComplete = GetMethodIDOrDie(env, + FindClassOrDie(env, "com/android/server/VibratorService$Vibration"), + "onComplete", "()V"); return jniRegisterNativeMethods(env, "com/android/server/VibratorService", method_table, NELEM(method_table)); } diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp index 47790ce68dc1..dbe0d811dbb6 100644 --- a/services/devicepolicy/Android.bp +++ b/services/devicepolicy/Android.bp @@ -4,5 +4,6 @@ java_library_static { libs: [ "services.core", + "app-compat-annotations", ], } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 37931be4eb10..2e56fb096e3b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1939,7 +1939,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } TelephonyManager getTelephonyManager() { - return TelephonyManager.from(mContext); + return mContext.getSystemService(TelephonyManager.class); } TrustManager getTrustManager() { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f465855017cd..16c60ca3997a 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -24,6 +24,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import android.annotation.NonNull; import android.app.ActivityThread; +import android.app.AppCompatCallbacks; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; @@ -644,6 +645,7 @@ public final class SystemServer { ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, new PlatformCompatNative(platformCompat)); + AppCompatCallbacks.install(new long[0]); traceEnd(); // Wait for installd to finish starting up so that it has a chance to diff --git a/services/net/Android.bp b/services/net/Android.bp index e24dec562a46..c56ecd6e19e7 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -29,6 +29,7 @@ filegroup { "java/android/net/ConnectivityModuleConnector.java", "java/android/net/NetworkStackClient.java", "java/android/net/ip/InterfaceController.java", + "java/android/net/netlink/*.java", "java/android/net/util/InterfaceParams.java", "java/android/net/util/NetdService.java", "java/android/net/util/NetworkConstants.java", diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java index 69e24063210d..865e3b8cc109 100644 --- a/services/net/java/android/net/NetworkStackClient.java +++ b/services/net/java/android/net/NetworkStackClient.java @@ -103,7 +103,7 @@ public class NetworkStackClient { // checks here should be kept in sync with PermissionUtil. if (caller != Process.SYSTEM_UID && caller != Process.NETWORK_STACK_UID - && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) { + && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) { throw new SecurityException( "Only the system server should try to bind to the network stack."); } diff --git a/services/tests/servicestests/res/raw/apex_test.apex b/services/tests/servicestests/res/raw/apex_test.apex Binary files differnew file mode 100644 index 000000000000..19b1c5e2e1c6 --- /dev/null +++ b/services/tests/servicestests/res/raw/apex_test.apex diff --git a/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java index 0605d9e18069..50437b4d5f3e 100644 --- a/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java @@ -36,7 +36,7 @@ public class DynamicSystemServiceTest extends AndroidTestCase { public void test1() { assertTrue("dynamic_system service available", mService != null); try { - mService.startInstallation("userdata", 8L << 30, false); + mService.startInstallation(); fail("DynamicSystemService did not throw SecurityException as expected"); } catch (SecurityException e) { // expected diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java new file mode 100644 index 000000000000..6bb4202fa759 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2019 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.pm; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; + +import android.apex.ApexInfo; +import android.apex.ApexSessionInfo; +import android.apex.IApexService; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.os.FileUtils; +import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import com.android.frameworks.servicestests.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +@SmallTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class ApexManagerTest { + private static final String TEST_APEX_PKG = "com.android.apex.test"; + private static final int TEST_SESSION_ID = 99999999; + private static final int[] TEST_CHILD_SESSION_ID = {8888, 7777}; + private ApexManager mApexManager; + private Context mContext; + + private IApexService mApexService = mock(IApexService.class); + + @Before + public void setUp() throws RemoteException { + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService); + } + + @Test + public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false)); + final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexManager.MATCH_ACTIVE_PACKAGE); + + assertThat(activePkgPi).isNotNull(); + assertThat(activePkgPi.packageName).contains(TEST_APEX_PKG); + + final PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexManager.MATCH_FACTORY_PACKAGE); + + assertThat(factoryPkgPi).isNull(); + } + + @Test + public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexManager.MATCH_FACTORY_PACKAGE); + + assertThat(factoryPkgPi).isNotNull(); + assertThat(factoryPkgPi.packageName).contains(TEST_APEX_PKG); + + final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexManager.MATCH_ACTIVE_PACKAGE); + + assertThat(activePkgPi).isNull(); + } + + @Test + public void testGetPackageInfo_setFlagsNone() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + + assertThat(mApexManager.getPackageInfo(TEST_APEX_PKG, 0)).isNull(); + } + + @Test + public void testGetActivePackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true)); + + assertThat(mApexManager.getActivePackages()).isNotEmpty(); + } + + @Test + public void testGetActivePackages_noneActivePackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + + assertThat(mApexManager.getActivePackages()).isEmpty(); + } + + @Test + public void testGetFactoryPackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + + assertThat(mApexManager.getFactoryPackages()).isNotEmpty(); + } + + @Test + public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false)); + + assertThat(mApexManager.getFactoryPackages()).isEmpty(); + } + + @Test + public void testGetInactivePackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + + assertThat(mApexManager.getInactivePackages()).isNotEmpty(); + } + + @Test + public void testGetInactivePackages_noneInactivePackages() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false)); + + assertThat(mApexManager.getInactivePackages()).isEmpty(); + } + + @Test + public void testIsApexPackage() throws RemoteException { + when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true)); + + assertThat(mApexManager.isApexPackage(TEST_APEX_PKG)).isTrue(); + } + + @Test + public void testIsApexSupported() { + assertThat(mApexManager.isApexSupported()).isTrue(); + } + + @Test + public void testGetStagedSessionInfo() throws RemoteException { + when(mApexService.getStagedSessionInfo(anyInt())).thenReturn( + getFakeStagedSessionInfo()); + + mApexManager.getStagedSessionInfo(TEST_SESSION_ID); + verify(mApexService, times(1)).getStagedSessionInfo(TEST_SESSION_ID); + } + + @Test + public void testGetStagedSessionInfo_unKnownStagedSessionId() throws RemoteException { + when(mApexService.getStagedSessionInfo(anyInt())).thenReturn( + getFakeUnknownSessionInfo()); + + assertThat(mApexManager.getStagedSessionInfo(TEST_SESSION_ID)).isNull(); + } + + @Test + public void testSubmitStagedSession_throwPackageManagerException() throws RemoteException { + doAnswer(invocation -> { + throw new Exception(); + }).when(mApexService).submitStagedSession(anyInt(), any(), any()); + + assertThrows(PackageManagerException.class, + () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID)); + } + + @Test + public void testSubmitStagedSession_throwRunTimeException() throws RemoteException { + doThrow(RemoteException.class).when(mApexService).submitStagedSession(anyInt(), any(), + any()); + + assertThrows(RuntimeException.class, + () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID)); + } + + @Test + public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException { + doAnswer(invocation -> { + throw new Exception(); + }).when(mApexService).markStagedSessionReady(anyInt()); + + assertThrows(PackageManagerException.class, + () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID)); + } + + @Test + public void testMarkStagedSessionReady_throwRunTimeException() throws RemoteException { + doThrow(RemoteException.class).when(mApexService).markStagedSessionReady(anyInt()); + + assertThrows(RuntimeException.class, + () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID)); + } + + @Test + public void testAbortActiveSession_remoteException() throws RemoteException { + doThrow(RemoteException.class).when(mApexService).abortActiveSession(); + + try { + assertThat(mApexManager.abortActiveSession()).isFalse(); + } catch (Exception e) { + throw new AssertionError("ApexManager should not raise Exception"); + } + } + + @Test + public void testMarkStagedSessionSuccessful_throwRemoteException() throws RemoteException { + doThrow(RemoteException.class).when(mApexService).markStagedSessionSuccessful(anyInt()); + + assertThrows(RuntimeException.class, + () -> mApexManager.markStagedSessionSuccessful(TEST_SESSION_ID)); + } + + @Test + public void testUninstallApex_throwException_returnFalse() throws RemoteException { + doAnswer(invocation -> { + throw new Exception(); + }).when(mApexService).unstagePackages(any()); + + assertThat(mApexManager.uninstallApex(TEST_APEX_PKG)).isFalse(); + } + + private ApexInfo[] createApexInfo(boolean isActive, boolean isFactory) { + File apexFile = copyRawResourceToFile(TEST_APEX_PKG, R.raw.apex_test); + ApexInfo apexInfo = new ApexInfo(); + apexInfo.isActive = isActive; + apexInfo.isFactory = isFactory; + apexInfo.moduleName = TEST_APEX_PKG; + apexInfo.modulePath = apexFile.getPath(); + apexInfo.versionCode = 191000070; + + return new ApexInfo[]{apexInfo}; + } + + private ApexSessionInfo getFakeStagedSessionInfo() { + ApexSessionInfo stagedSessionInfo = new ApexSessionInfo(); + stagedSessionInfo.sessionId = TEST_SESSION_ID; + stagedSessionInfo.isStaged = true; + + return stagedSessionInfo; + } + + private ApexSessionInfo getFakeUnknownSessionInfo() { + ApexSessionInfo stagedSessionInfo = new ApexSessionInfo(); + stagedSessionInfo.sessionId = TEST_SESSION_ID; + stagedSessionInfo.isUnknown = true; + + return stagedSessionInfo; + } + + /** + * Copies a specified {@code resourceId} to a temp file. Returns a non-null file if the copy + * succeeded + */ + File copyRawResourceToFile(String baseName, int resourceId) { + File outFile; + try { + outFile = File.createTempFile(baseName, ".apex"); + } catch (IOException e) { + throw new AssertionError("CreateTempFile IOException" + e); + } + + try (InputStream is = mContext.getResources().openRawResource(resourceId); + FileOutputStream os = new FileOutputStream(outFile)) { + assertThat(FileUtils.copy(is, os)).isGreaterThan(0L); + } catch (FileNotFoundException e) { + throw new AssertionError("File not found exception " + e); + } catch (IOException e) { + throw new AssertionError("IOException" + e); + } + + return outFile; + } +} diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index dcab78ede287..8cd6ef9c132f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -98,7 +98,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT; Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders, - priorityMessageSenders, suppressedVisualEffects); + priorityMessageSenders, suppressedVisualEffects, 0); assertEquals(expectedPolicy, config.toNotificationPolicy(zenPolicy)); } diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index c380d291d573..7cc233b2439e 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -16,7 +16,6 @@ cc_defaults { name: "viewcompiler_defaults", - defaults: ["libdexfile_static_defaults"], header_libs: [ "libbase_headers", ], @@ -30,6 +29,7 @@ cc_defaults { "liblog", "libutils", "libziparchive", + "libz", ], cppflags: ["-std=c++17"], target: { diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc index 48b44d0fc99b..50cf5a50d7a8 100644 --- a/startop/view_compiler/dex_builder.cc +++ b/startop/view_compiler/dex_builder.cc @@ -16,8 +16,6 @@ #include "dex_builder.h" -#include "dex/descriptors_names.h" - #include <fstream> #include <memory> @@ -30,8 +28,6 @@ using std::string; using ::dex::kAccPublic; using Op = Instruction::Op; -using Opcode = ::art::Instruction::Code; - const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; }; const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; }; @@ -43,20 +39,29 @@ constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00 constexpr size_t kMaxEncodedStringLength{5}; // Converts invoke-* to invoke-*/range -constexpr Opcode InvokeToInvokeRange(Opcode opcode) { +constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) { switch (opcode) { - case ::art::Instruction::INVOKE_VIRTUAL: - return ::art::Instruction::INVOKE_VIRTUAL_RANGE; - case ::art::Instruction::INVOKE_DIRECT: - return ::art::Instruction::INVOKE_DIRECT_RANGE; - case ::art::Instruction::INVOKE_STATIC: - return ::art::Instruction::INVOKE_STATIC_RANGE; - case ::art::Instruction::INVOKE_INTERFACE: - return ::art::Instruction::INVOKE_INTERFACE_RANGE; + case ::dex::Opcode::OP_INVOKE_VIRTUAL: + return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE; + case ::dex::Opcode::OP_INVOKE_DIRECT: + return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE; + case ::dex::Opcode::OP_INVOKE_STATIC: + return ::dex::Opcode::OP_INVOKE_STATIC_RANGE; + case ::dex::Opcode::OP_INVOKE_INTERFACE: + return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE; default: LOG(FATAL) << opcode << " is not a recognized invoke opcode."; - UNREACHABLE(); + __builtin_unreachable(); + } +} + +std::string DotToDescriptor(const char* class_name) { + std::string descriptor(class_name); + std::replace(descriptor.begin(), descriptor.end(), '.', '/'); + if (descriptor.length() > 0 && descriptor[0] != '[') { + descriptor = "L" + descriptor + ";"; } + return descriptor; } } // namespace @@ -178,7 +183,7 @@ void WriteTestDexFile(const string& filename) { } TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) { - return TypeDescriptor{art::DotToDescriptor(name.c_str())}; + return TypeDescriptor{DotToDescriptor(name.c_str())}; } DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} { @@ -219,11 +224,11 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) { ClassBuilder DexBuilder::MakeClass(const std::string& name) { auto* class_def = Alloc<ir::Class>(); - ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str())); + ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str())); type_def->class_def = class_def; class_def->type = type_def; - class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object")); + class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object")); class_def->access_flags = kAccPublic; return ClassBuilder{this, name, class_def}; } @@ -378,26 +383,26 @@ void MethodBuilder::EncodeInstructions() { void MethodBuilder::EncodeInstruction(const Instruction& instruction) { switch (instruction.opcode()) { case Instruction::Op::kReturn: - return EncodeReturn(instruction, ::art::Instruction::RETURN); + return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN); case Instruction::Op::kReturnObject: - return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT); + return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT); case Instruction::Op::kMove: case Instruction::Op::kMoveObject: return EncodeMove(instruction); case Instruction::Op::kInvokeVirtual: - return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL); + return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL); case Instruction::Op::kInvokeDirect: - return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT); + return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT); case Instruction::Op::kInvokeStatic: - return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC); + return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC); case Instruction::Op::kInvokeInterface: - return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE); + return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE); case Instruction::Op::kBindLabel: return BindLabel(instruction.args()[0]); case Instruction::Op::kBranchEqz: - return EncodeBranch(art::Instruction::IF_EQZ, instruction); + return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction); case Instruction::Op::kBranchNEqz: - return EncodeBranch(art::Instruction::IF_NEZ, instruction); + return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction); case Instruction::Op::kNew: return EncodeNew(instruction); case Instruction::Op::kCheckCast: @@ -410,10 +415,10 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { } } -void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) { +void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) { CHECK(!instruction.dest().has_value()); if (instruction.args().size() == 0) { - Encode10x(art::Instruction::RETURN_VOID); + Encode10x(::dex::Opcode::OP_RETURN_VOID); } else { CHECK_EQ(1, instruction.args().size()); size_t source = RegisterValue(instruction.args()[0]); @@ -433,27 +438,27 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) { if (source.is_immediate()) { // TODO: support more registers CHECK_LT(RegisterValue(*instruction.dest()), 16); - Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value()); + Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_string()) { constexpr size_t kMaxRegisters = 256; CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters); CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string - Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value()); + Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_variable()) { // For the moment, we only use this when we need to reshuffle registers for // an invoke instruction, meaning we are too big for the 4-bit version. // We'll err on the side of caution and always generate the 16-bit form of // the instruction. - Opcode opcode = instruction.opcode() == Instruction::Op::kMove - ? ::art::Instruction::MOVE_16 - : ::art::Instruction::MOVE_OBJECT_16; + auto opcode = instruction.opcode() == Instruction::Op::kMove + ? ::dex::Opcode::OP_MOVE_16 + : ::dex::Opcode::OP_MOVE_OBJECT_16; Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source)); } else { UNIMPLEMENTED(FATAL); } } -void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) { +void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) { constexpr size_t kMaxArgs = 5; // Currently, we only support up to 5 arguments. @@ -480,8 +485,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct for (size_t i = 0; i < instruction.args().size(); ++i) { Instruction::Op move_op; - if (opcode == ::art::Instruction::INVOKE_VIRTUAL || - opcode == ::art::Instruction::INVOKE_DIRECT) { + if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL || + opcode == ::dex::Opcode::OP_INVOKE_DIRECT) { // In this case, there is an implicit `this` argument, which is always an object. if (i == 0) { move_op = Instruction::Op::kMoveObject; @@ -514,8 +519,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct // If there is a return value, add a move-result instruction if (instruction.dest().has_value()) { - Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT - : art::Instruction::MOVE_RESULT, + Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT + : ::dex::Opcode::OP_MOVE_RESULT, RegisterValue(*instruction.dest())); } @@ -523,7 +528,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct } // Encodes a conditional branch that tests a single argument. -void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) { +void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) { const auto& args = instruction.args(); const auto& test_value = args[0]; const auto& branch_target = args[1]; @@ -546,7 +551,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); - Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); + Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeCast(const Instruction& instruction) { @@ -558,7 +563,7 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); - Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); + Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { @@ -569,7 +574,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(0, instruction.args().size()); - Encode21c(::art::Instruction::SGET, + Encode21c(::dex::Opcode::OP_SGET, RegisterValue(*instruction.dest()), instruction.index_argument()); break; @@ -579,7 +584,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK_EQ(1, args.size()); CHECK(args[0].is_variable()); - Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument()); + Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument()); break; } case Instruction::Op::kGetInstanceField: { @@ -587,7 +592,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(1, instruction.args().size()); - Encode22c(::art::Instruction::IGET, + Encode22c(::dex::Opcode::OP_IGET, RegisterValue(*instruction.dest()), RegisterValue(args[0]), instruction.index_argument()); @@ -599,7 +604,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(args[0].is_variable()); CHECK(args[1].is_variable()); - Encode22c(::art::Instruction::IPUT, + Encode22c(::dex::Opcode::OP_IPUT, RegisterValue(args[1]), RegisterValue(args[0]), instruction.index_argument()); diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index 3924e77fab59..eb2dc88835d4 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -24,7 +24,9 @@ #include <unordered_map> #include <vector> -#include "dex/dex_instruction.h" +#include "android-base/logging.h" + +#include "slicer/dex_bytecode.h" #include "slicer/dex_ir.h" #include "slicer/writer.h" @@ -364,11 +366,11 @@ class MethodBuilder { // Encodes a return instruction. For instructions with no return value, the opcode field is // ignored. Otherwise, this specifies which return instruction will be used (return, // return-object, etc.) - void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode); + void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode); void EncodeMove(const Instruction& instruction); - void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode); - void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); + void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode); + void EncodeBranch(::dex::Opcode op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); void EncodeCast(const Instruction& instruction); void EncodeFieldOp(const Instruction& instruction); @@ -377,17 +379,23 @@ class MethodBuilder { // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of // formats. - inline void Encode10x(art::Instruction::Code opcode) { + inline uint8_t ToBits(::dex::Opcode opcode) { + static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode)); + return static_cast<uint8_t>(opcode); + } + + inline void Encode10x(::dex::Opcode opcode) { // 00|op - buffer_.push_back(opcode); + static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode)); + buffer_.push_back(ToBits(opcode)); } - inline void Encode11x(art::Instruction::Code opcode, uint8_t a) { + inline void Encode11x(::dex::Opcode opcode, uint8_t a) { // aa|op - buffer_.push_back((a << 8) | opcode); + buffer_.push_back((a << 8) | ToBits(opcode)); } - inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) { + inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) { // b|a|op // Make sure the fields are in bounds (4 bits for a, 4 bits for b). @@ -395,30 +403,30 @@ class MethodBuilder { CHECK_LE(-8, b); CHECK_LT(b, 8); - buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode); + buffer_.push_back(((b & 0xf) << 12) | (a << 8) | ToBits(opcode)); } - inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) { + inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) { // aa|op|bbbb - buffer_.push_back((a << 8) | opcode); + buffer_.push_back((a << 8) | ToBits(opcode)); buffer_.push_back(b); } - inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) { + inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) { // b|a|op|bbbb CHECK(IsShortRegister(a)); CHECK(IsShortRegister(b)); - buffer_.push_back((b << 12) | (a << 8) | opcode); + buffer_.push_back((b << 12) | (a << 8) | ToBits(opcode)); buffer_.push_back(c); } - inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) { - buffer_.push_back(opcode); + inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) { + buffer_.push_back(ToBits(opcode)); buffer_.push_back(a); buffer_.push_back(b); } - inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, + inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f, uint8_t g) { // a|g|op|bbbb|f|e|d|c @@ -428,14 +436,14 @@ class MethodBuilder { CHECK(IsShortRegister(e)); CHECK(IsShortRegister(f)); CHECK(IsShortRegister(g)); - buffer_.push_back((a << 12) | (g << 8) | opcode); + buffer_.push_back((a << 12) | (g << 8) | ToBits(opcode)); buffer_.push_back(b); buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c); } - inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) { + inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) { CHECK_LE(a, 255); - buffer_.push_back((a << 8) | opcode); + buffer_.push_back((a << 8) | ToBits(opcode)); buffer_.push_back(b); buffer_.push_back(c); } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 60290e3b785d..3ecf8d73d0a6 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -25,8 +25,11 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.ParcelFileDescriptor; +import com.android.internal.telecom.IVideoProvider; + import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; @@ -512,8 +515,8 @@ public final class Call { /** * Indicates the call used Assisted Dialing. - * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED} - * @hide + * + * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING */ public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200; @@ -1181,7 +1184,8 @@ public final class Call { public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {} /** - * Invoked when a {@link Call} receives an event from its associated {@link Connection}. + * Invoked when a {@link Call} receives an event from its associated {@link Connection} or + * {@link Conference}. * <p> * Where possible, the Call should make an attempt to handle {@link Connection} events which * are part of the {@code android.telecom.*} namespace. The Call should ignore any events @@ -1189,7 +1193,8 @@ public final class Call { * possible that a {@link ConnectionService} has defined its own Connection events which a * Call is not aware of. * <p> - * See {@link Connection#sendConnectionEvent(String, Bundle)}. + * See {@link Connection#sendConnectionEvent(String, Bundle)}, + * {@link Conference#sendConferenceEvent(String, Bundle)}. * * @param call The {@code Call} receiving the event. * @param event The event. @@ -2130,13 +2135,22 @@ public final class Call { cannedTextResponsesChanged = true; } - VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage, - mTargetSdkVersion); - boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() && - !Objects.equals(mVideoCallImpl, newVideoCallImpl); + IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null : + mVideoCallImpl.getVideoProvider(); + IVideoProvider newVideoProvider = parcelableCall.getVideoProvider(); + + // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider + // specified; so we should check if the actual IVideoProvider changes as well. + boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() + && !Objects.equals(previousVideoProvider, newVideoProvider); if (videoCallChanged) { - mVideoCallImpl = newVideoCallImpl; + if (mVideoCallImpl != null) { + mVideoCallImpl.destroy(); + } + mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ? + parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null; } + if (mVideoCallImpl != null) { mVideoCallImpl.setVideoState(getDetails().getVideoState()); } diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java index ef1c790dcc83..b91787ccff83 100644 --- a/telecomm/java/android/telecom/CallScreeningService.java +++ b/telecomm/java/android/telecom/CallScreeningService.java @@ -106,8 +106,14 @@ public abstract class CallScreeningService extends Service { SomeArgs args = (SomeArgs) msg.obj; try { mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1; - onScreenCall( - Call.Details.createFromParcelableCall((ParcelableCall) args.arg2)); + Call.Details callDetails = Call.Details + .createFromParcelableCall((ParcelableCall) args.arg2); + onScreenCall(callDetails); + if (callDetails.getCallDirection() == Call.Details.DIRECTION_OUTGOING) { + mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); + } + } catch (RemoteException e) { + Log.w(this, "Exception when screening call: " + e); } finally { args.recycle(); } diff --git a/telephony/java/android/telephony/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java index f87ac503bbc5..a5d25e2ce4bb 100644 --- a/telephony/java/android/telephony/CallerInfo.java +++ b/telecomm/java/android/telecom/CallerInfo.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package android.telephony; +package android.telecom; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.ContentResolver; @@ -33,8 +32,10 @@ import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.PhoneLookup; import android.provider.ContactsContract.RawContacts; +import android.telephony.PhoneNumberUtils; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.Log; import com.android.i18n.phonenumbers.NumberParseException; import com.android.i18n.phonenumbers.PhoneNumberUtil; @@ -50,10 +51,9 @@ import java.util.Locale; * * {@hide} */ -@SystemApi public class CallerInfo { private static final String TAG = "CallerInfo"; - private static final boolean VDBG = Rlog.isLoggable(TAG, Log.VERBOSE); + private static final boolean VDBG = Log.VERBOSE; /** @hide */ public static final long USER_TYPE_CURRENT = 0; @@ -215,7 +215,7 @@ public class CallerInfo { info.contactExists = false; info.userType = USER_TYPE_CURRENT; - if (VDBG) Rlog.v(TAG, "getCallerInfo() based on cursor..."); + if (VDBG) Log.v(TAG, "getCallerInfo() based on cursor..."); if (cursor != null) { if (cursor.moveToFirst()) { @@ -263,7 +263,7 @@ public class CallerInfo { if (contactId != 0 && !Contacts.isEnterpriseContactId(contactId)) { info.contactIdOrZero = contactId; if (VDBG) { - Rlog.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero); + Log.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero); } } if (Contacts.isEnterpriseContactId(contactId)) { @@ -271,7 +271,7 @@ public class CallerInfo { } } else { // No valid columnIndex, so we can't look up person_id. - Rlog.w(TAG, "Couldn't find contact_id column for " + contactRef); + Log.w(TAG, "Couldn't find contact_id column for " + contactRef); // Watch out: this means that anything that depends on // person_id will be broken (like contact photo lookups in // the in-call UI, for example.) @@ -356,7 +356,7 @@ public class CallerInfo { info = getCallerInfo(context, contactRef, cr.query(contactRef, null, null, null, null)); } catch (RuntimeException re) { - Rlog.e(TAG, "Error getting caller info.", re); + Log.e(TAG, re, "Error getting caller info."); } } return info; @@ -376,7 +376,7 @@ public class CallerInfo { */ @UnsupportedAppUsage public static CallerInfo getCallerInfo(Context context, String number) { - if (VDBG) Rlog.v(TAG, "getCallerInfo() based on number..."); + if (VDBG) Log.v(TAG, "getCallerInfo() based on number..."); int subId = SubscriptionManager.getDefaultSubscriptionId(); return getCallerInfo(context, number, subId); @@ -407,8 +407,8 @@ public class CallerInfo { // shortcut and skip the query. if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) { return new CallerInfo().markAsEmergency(context); - } else if (PhoneNumberUtils.isVoiceMailNumber(subId, number)) { - return new CallerInfo().markAsVoiceMail(); + } else if (PhoneNumberUtils.isVoiceMailNumber(null, subId, number)) { + return new CallerInfo().markAsVoiceMail(context, subId); } Uri contactUri = Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, @@ -542,36 +542,20 @@ public class CallerInfo { } - /** - * Mark this CallerInfo as a voicemail call. The voicemail label - * is obtained from the telephony manager. Caller must hold the - * READ_PHONE_STATE permission otherwise the phoneNumber will be - * set to null. - * @return this instance. - */ - // TODO: As in the emergency number handling, we end up writing a - // string in the phone number field. - /* package */ CallerInfo markAsVoiceMail() { - - int subId = SubscriptionManager.getDefaultSubscriptionId(); - return markAsVoiceMail(subId); - - } - - /* package */ CallerInfo markAsVoiceMail(int subId) { + /* package */ CallerInfo markAsVoiceMail(Context context, int subId) { mIsVoiceMail = true; try { - String voiceMailLabel = TelephonyManager.getDefault().getVoiceMailAlphaTag(subId); - - phoneNumber = voiceMailLabel; + phoneNumber = context.getSystemService(TelephonyManager.class) + .createForSubscriptionId(subId) + .getVoiceMailAlphaTag(); } catch (SecurityException se) { // Should never happen: if this process does not have // permission to retrieve VM tag, it should not have // permission to retrieve VM number and would not call // this method. // Leave phoneNumber untouched. - Rlog.e(TAG, "Cannot access VoiceMail.", se); + Log.e(TAG, se, "Cannot access VoiceMail."); } // TODO: There is no voicemail picture? // FIXME: FIND ANOTHER ICON @@ -630,10 +614,10 @@ public class CallerInfo { // So instead, figure out the column to use for person_id by just // looking at the URI itself. - if (VDBG) Rlog.v(TAG, "- getColumnIndexForPersonId: contactRef URI = '" + if (VDBG) Log.v(TAG, "- getColumnIndexForPersonId: contactRef URI = '" + contactRef + "'..."); // Warning: Do not enable the following logging (due to ANR risk.) - // if (VDBG) Rlog.v(TAG, "- MIME type: " + // if (VDBG) Log.v(TAG, "- MIME type: " // + context.getContentResolver().getType(contactRef)); String url = contactRef.toString(); @@ -641,25 +625,25 @@ public class CallerInfo { if (url.startsWith("content://com.android.contacts/data/phones")) { // Direct lookup in the Phone table. // MIME type: Phone.CONTENT_ITEM_TYPE (= "vnd.android.cursor.item/phone_v2") - if (VDBG) Rlog.v(TAG, "'data/phones' URI; using RawContacts.CONTACT_ID"); + if (VDBG) Log.v(TAG, "'data/phones' URI; using RawContacts.CONTACT_ID"); columnName = RawContacts.CONTACT_ID; } else if (url.startsWith("content://com.android.contacts/data")) { // Direct lookup in the Data table. // MIME type: Data.CONTENT_TYPE (= "vnd.android.cursor.dir/data") - if (VDBG) Rlog.v(TAG, "'data' URI; using Data.CONTACT_ID"); + if (VDBG) Log.v(TAG, "'data' URI; using Data.CONTACT_ID"); // (Note Data.CONTACT_ID and RawContacts.CONTACT_ID are equivalent.) columnName = Data.CONTACT_ID; } else if (url.startsWith("content://com.android.contacts/phone_lookup")) { // Lookup in the PhoneLookup table, which provides "fuzzy matching" // for phone numbers. // MIME type: PhoneLookup.CONTENT_TYPE (= "vnd.android.cursor.dir/phone_lookup") - if (VDBG) Rlog.v(TAG, "'phone_lookup' URI; using PhoneLookup._ID"); + if (VDBG) Log.v(TAG, "'phone_lookup' URI; using PhoneLookup._ID"); columnName = PhoneLookup._ID; } else { - Rlog.w(TAG, "Unexpected prefix for contactRef '" + url + "'"); + Log.w(TAG, "Unexpected prefix for contactRef '" + url + "'"); } int columnIndex = (columnName != null) ? cursor.getColumnIndex(columnName) : -1; - if (VDBG) Rlog.v(TAG, "==> Using column '" + columnName + if (VDBG) Log.v(TAG, "==> Using column '" + columnName + "' (columnIndex = " + columnIndex + ") for person_id lookup..."); return columnIndex; } @@ -689,7 +673,7 @@ public class CallerInfo { * @hide */ public static String getGeoDescription(Context context, String number) { - if (VDBG) Rlog.v(TAG, "getGeoDescription('" + number + "')..."); + if (VDBG) Log.v(TAG, "getGeoDescription('" + number + "')..."); if (TextUtils.isEmpty(number)) { return null; @@ -702,18 +686,18 @@ public class CallerInfo { String countryIso = getCurrentCountryIso(context, locale); PhoneNumber pn = null; try { - if (VDBG) Rlog.v(TAG, "parsing '" + number + if (VDBG) Log.v(TAG, "parsing '" + number + "' for countryIso '" + countryIso + "'..."); pn = util.parse(number, countryIso); - if (VDBG) Rlog.v(TAG, "- parsed number: " + pn); + if (VDBG) Log.v(TAG, "- parsed number: " + pn); } catch (NumberParseException e) { - Rlog.w(TAG, "getGeoDescription: NumberParseException for incoming number '" - + Rlog.pii(TAG, number) + "'"); + Log.w(TAG, "getGeoDescription: NumberParseException for incoming number '" + + Log.pii(number) + "'"); } if (pn != null) { String description = geocoder.getDescriptionForNumber(pn, locale); - if (VDBG) Rlog.v(TAG, "- got description: '" + description + "'"); + if (VDBG) Log.v(TAG, "- got description: '" + description + "'"); return description; } else { return null; @@ -733,12 +717,12 @@ public class CallerInfo { if (country != null) { countryIso = country.getCountryIso(); } else { - Rlog.e(TAG, "CountryDetector.detectCountry() returned null."); + Log.e(TAG, new Exception(), "CountryDetector.detectCountry() returned null."); } } if (countryIso == null) { countryIso = locale.getCountry(); - Rlog.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + countryIso); } return countryIso; diff --git a/telephony/java/android/telephony/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java index 87a637668d44..f38b34e85d89 100644 --- a/telephony/java/android/telephony/CallerInfoAsyncQuery.java +++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.telephony; +package android.telecom; import android.app.ActivityManager; import android.content.AsyncQueryHandler; @@ -31,6 +31,8 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.PhoneLookup; +import android.telephony.PhoneNumberUtils; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import java.util.ArrayList; import java.util.List; @@ -100,12 +102,12 @@ public class CallerInfoAsyncQuery { */ static ContentResolver getCurrentProfileContentResolver(Context context) { - if (DBG) Rlog.d(LOG_TAG, "Trying to get current content resolver..."); + if (DBG) Log.d(LOG_TAG, "Trying to get current content resolver..."); final int currentUser = ActivityManager.getCurrentUser(); final int myUser = UserManager.get(context).getUserHandle(); - if (DBG) Rlog.d(LOG_TAG, "myUser=" + myUser + "currentUser=" + currentUser); + if (DBG) Log.d(LOG_TAG, "myUser=" + myUser + "currentUser=" + currentUser); if (myUser != currentUser) { final Context otherContext; @@ -114,7 +116,7 @@ public class CallerInfoAsyncQuery { /* flags =*/ 0, UserHandle.of(currentUser)); return otherContext.getContentResolver(); } catch (NameNotFoundException e) { - Rlog.e(LOG_TAG, "Can't find self package", e); + Log.e(LOG_TAG, e, "Can't find self package"); // Fall back to the primary user. } } @@ -179,13 +181,13 @@ public class CallerInfoAsyncQuery { // However, if there is any code that this Handler calls (such as in // super.handleMessage) that DOES place unexpected messages on the // queue, then we need pass these messages on. - Rlog.i(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what + + Log.i(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what + " ignored by CallerInfoWorkerHandler, passing onto parent."); super.handleMessage(msg); } else { - Rlog.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 + + Log.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 + " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri)); switch (cw.event) { @@ -226,7 +228,7 @@ public class CallerInfoAsyncQuery { cw.geoDescription = CallerInfo.getGeoDescription(mContext, cw.number); final long duration = SystemClock.elapsedRealtime() - startTimeMillis; if (duration > 500) { - if (DBG) Rlog.d(LOG_TAG, "[handleGeoDescription]" + + if (DBG) Log.d(LOG_TAG, "[handleGeoDescription]" + "Spends long time to retrieve Geo description: " + duration); } } @@ -263,7 +265,7 @@ public class CallerInfoAsyncQuery { */ @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { - Rlog.d(LOG_TAG, "##### onQueryComplete() ##### query complete for token: " + token); + Log.d(LOG_TAG, "##### onQueryComplete() ##### query complete for token: " + token); //get the cookie and notify the listener. CookieWrapper cw = (CookieWrapper) cookie; @@ -272,7 +274,7 @@ public class CallerInfoAsyncQuery { // from within this code. // However, if there is any code that calls this method, we should // check the parameters to make sure they're viable. - Rlog.i(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request."); + Log.i(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request."); if (cursor != null) { cursor.close(); } @@ -321,16 +323,16 @@ public class CallerInfoAsyncQuery { // comments at the top of CallerInfo class). mCallerInfo = new CallerInfo().markAsEmergency(mContext); } else if (cw.event == EVENT_VOICEMAIL_NUMBER) { - mCallerInfo = new CallerInfo().markAsVoiceMail(cw.subId); + mCallerInfo = new CallerInfo().markAsVoiceMail(mContext, cw.subId); } else { mCallerInfo = CallerInfo.getCallerInfo(mContext, mQueryUri, cursor); - if (DBG) Rlog.d(LOG_TAG, "==> Got mCallerInfo: " + mCallerInfo); + if (DBG) Log.d(LOG_TAG, "==> Got mCallerInfo: " + mCallerInfo); CallerInfo newCallerInfo = CallerInfo.doSecondaryLookupIfNecessary( mContext, cw.number, mCallerInfo); if (newCallerInfo != mCallerInfo) { mCallerInfo = newCallerInfo; - if (DBG) Rlog.d(LOG_TAG, "#####async contact look up with numeric username" + if (DBG) Log.d(LOG_TAG, "#####async contact look up with numeric username" + mCallerInfo); } @@ -346,7 +348,7 @@ public class CallerInfoAsyncQuery { // the geo description, so it would be unnecessary to query it. if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) { if (TextUtils.isEmpty(mCallerInfo.getName())) { - if (DBG) Rlog.d(LOG_TAG, "start querying geo description"); + if (DBG) Log.d(LOG_TAG, "start querying geo description"); cw.event = EVENT_GET_GEO_DESCRIPTION; startQuery(token, cw, null, null, null, null, null); return; @@ -354,7 +356,7 @@ public class CallerInfoAsyncQuery { } } - if (DBG) Rlog.d(LOG_TAG, "constructing CallerInfo object for token: " + token); + if (DBG) Log.d(LOG_TAG, "constructing CallerInfo object for token: " + token); //notify that we can clean up the queue after this. CookieWrapper endMarker = new CookieWrapper(); @@ -367,14 +369,14 @@ public class CallerInfoAsyncQuery { mPendingListenerCallbacks.add(new Runnable() { @Override public void run() { - if (DBG) Rlog.d(LOG_TAG, "notifying listener: " + if (DBG) Log.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() + " for token: " + token + mCallerInfo); cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo); } }); } else { - Rlog.w(LOG_TAG, "There is no listener to notify for this query."); + Log.w(LOG_TAG, "There is no listener to notify for this query."); } if (cursor != null) { @@ -399,7 +401,7 @@ public class CallerInfoAsyncQuery { CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); c.allocate(context, contactRef); - if (DBG) Rlog.d(LOG_TAG, "starting query for URI: " + contactRef + " handler: " + c.toString()); + if (DBG) Log.d(LOG_TAG, "starting query for URI: " + contactRef + " handler: " + c.toString()); //create cookieWrapper, start query CookieWrapper cw = new CookieWrapper(); @@ -445,9 +447,9 @@ public class CallerInfoAsyncQuery { OnQueryCompleteListener listener, Object cookie, int subId) { if (DBG) { - Rlog.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####"); - Rlog.d(LOG_TAG, "- number: " + /*number*/ "xxxxxxx"); - Rlog.d(LOG_TAG, "- cookie: " + cookie); + Log.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####"); + Log.d(LOG_TAG, "- number: " + /*number*/ "xxxxxxx"); + Log.d(LOG_TAG, "- cookie: " + cookie); } // Construct the URI object and query params, and start the query. @@ -459,7 +461,7 @@ public class CallerInfoAsyncQuery { .build(); if (DBG) { - Rlog.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef)); + Log.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef)); } CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); @@ -496,8 +498,8 @@ public class CallerInfoAsyncQuery { */ public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) { - if (DBG) Rlog.d(LOG_TAG, "adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) + - " handler: " + mHandler.toString()); + if (DBG) Log.d(LOG_TAG, "adding listener to query: " + + sanitizeUriToString(mHandler.mQueryUri) + " handler: " + mHandler.toString()); //create cookieWrapper, add query request to end of queue. CookieWrapper cw = new CookieWrapper(); diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index cd5fd971a065..d669e905e4df 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -49,7 +49,7 @@ public abstract class Conference extends Conferenceable { public static final long CONNECT_TIME_NOT_SPECIFIED = 0; /** @hide */ - public abstract static class Listener { + abstract static class Listener { public void onStateChanged(Conference conference, int oldState, int newState) {} public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {} public void onConnectionAdded(Conference conference, Connection connection) {} @@ -120,11 +120,17 @@ public abstract class Conference extends Conferenceable { /** * Returns the telecom internal call ID associated with this conference. + * <p> + * Note: This is ONLY used for debugging purposes so that the Telephony stack can better + * associate logs in Telephony with those in Telecom. + * The ID returned should not be used for any other purpose. * * @return The telecom call ID. * @hide */ - public final String getTelecomCallId() { + @SystemApi + @TestApi + public final @NonNull String getTelecomCallId() { return mTelecomCallId; } @@ -186,55 +192,6 @@ public abstract class Conference extends Conferenceable { } /** - * Whether the given capabilities support the specified capability. - * - * @param capabilities A capability bit field. - * @param capability The capability to check capabilities for. - * @return Whether the specified capability is supported. - * @hide - */ - public static boolean can(int capabilities, int capability) { - return (capabilities & capability) != 0; - } - - /** - * Whether the capabilities of this {@code Connection} supports the specified capability. - * - * @param capability The capability to check capabilities for. - * @return Whether the specified capability is supported. - * @hide - */ - public boolean can(int capability) { - return can(mConnectionCapabilities, capability); - } - - /** - * Removes the specified capability from the set of capabilities of this {@code Conference}. - * - * @param capability The capability to remove from the set. - * @hide - */ - public void removeCapability(int capability) { - int newCapabilities = mConnectionCapabilities; - newCapabilities &= ~capability; - - setConnectionCapabilities(newCapabilities); - } - - /** - * Adds the specified capability to the set of capabilities of this {@code Conference}. - * - * @param capability The capability to add to the set. - * @hide - */ - public void addCapability(int capability) { - int newCapabilities = mConnectionCapabilities; - newCapabilities |= capability; - - setConnectionCapabilities(newCapabilities); - } - - /** * @return The audio state of the conference, describing how its audio is currently * being routed by the system. This is {@code null} if this Conference * does not directly know about its audio state. @@ -553,7 +510,7 @@ public abstract class Conference extends Conferenceable { * @return This conference. * @hide */ - public final Conference addListener(Listener listener) { + final Conference addListener(Listener listener) { mListeners.add(listener); return this; } @@ -565,7 +522,7 @@ public abstract class Conference extends Conferenceable { * @return This conference. * @hide */ - public final Conference removeListener(Listener listener) { + final Conference removeListener(Listener listener) { mListeners.remove(listener); return this; } @@ -587,20 +544,6 @@ public abstract class Conference extends Conferenceable { } /** - * Updates RIL voice radio technology used for current conference after its creation. - * - * @hide - */ - public void updateCallRadioTechAfterCreation() { - final Connection primaryConnection = getPrimaryConnection(); - if (primaryConnection != null) { - setCallRadioTech(primaryConnection.getCallRadioTech()); - } else { - Log.w(this, "No primary connection found while updateCallRadioTechAfterCreation"); - } - } - - /** * @hide * @deprecated Use {@link #setConnectionTime}. */ @@ -668,49 +611,24 @@ public abstract class Conference extends Conferenceable { * Retrieves the connection start time of the {@link Conference}, if specified. A value of * {@link #CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the start time * of the conference. - * + * <p> * This is based on the value of {@link SystemClock#elapsedRealtime()} to ensure that it is not * impacted by wall clock changes (user initiated, network initiated, time zone change, etc). + * <p> + * Note: This is only exposed for use by the Telephony framework which needs it to copy + * conference start times among conference participants. It is exposed as a system API since it + * has no general use other than to the Telephony framework. * * @return The elapsed time at which the {@link Conference} was connected. * @hide */ + @SystemApi + @TestApi public final long getConnectionStartElapsedRealTime() { return mConnectionStartElapsedRealTime; } /** - * Sets RIL voice radio technology used for current conference. - * - * @param vrat the RIL voice radio technology used for current conference, - * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. - * - * @hide - */ - public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) { - putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE, - ServiceState.rilRadioTechnologyToNetworkType(vrat)); - } - - /** - * Returns RIL voice radio technology used for current conference. - * - * @return the RIL voice radio technology used for current conference, - * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. - * - * @hide - */ - public final @ServiceState.RilRadioTechnology int getCallRadioTech() { - int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - Bundle extras = getExtras(); - if (extras != null) { - voiceNetworkType = extras.getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, - TelephonyManager.NETWORK_TYPE_UNKNOWN); - } - return ServiceState.networkTypeToRilRadioTechnology(voiceNetworkType); - } - - /** * Inform this Conference that the state of its audio output has been changed externally. * * @param state The new audio state. @@ -969,11 +887,15 @@ public abstract class Conference extends Conferenceable { * single-party call when the participant count drops to 1. Although the dialer/phone app * could perform this trickery, it makes sense to do this in Telephony since a fix there will * ensure that bluetooth head units, auto and wearable apps all behave consistently. + * <p> + * This API is intended for use by the platform Telephony stack only. * * @param isConference {@code true} if this {@link Conference} should be treated like a * conference call, {@code false} if it should be treated like a single-party call. * @hide */ + @SystemApi + @TestApi public void setConferenceState(boolean isConference) { for (Listener l : mListeners) { l.onConferenceStateChanged(this, isConference); @@ -983,13 +905,19 @@ public abstract class Conference extends Conferenceable { /** * Sets the address of this {@link Conference}. Used when {@link #setConferenceState(boolean)} * is called to mark a conference temporarily as NOT a conference. + * <p> + * Note: This is a Telephony-specific implementation detail related to IMS conferences. It is + * not intended for use outside of the Telephony stack. * * @param address The new address. * @param presentation The presentation requirements for the address. * See {@link TelecomManager} for valid values. * @hide */ - public final void setAddress(Uri address, int presentation) { + @SystemApi + @TestApi + public final void setAddress(@NonNull Uri address, + @TelecomManager.Presentation int presentation) { Log.d(this, "setAddress %s", address); mAddress = address; mAddressPresentation = presentation; @@ -1055,13 +983,19 @@ public abstract class Conference extends Conferenceable { * Sets the caller display name (CNAP) of this {@link Conference}. Used when * {@link #setConferenceState(boolean)} is called to mark a conference temporarily as NOT a * conference. + * <p> + * Note: This is a Telephony-specific implementation detail related to IMS conferences. It is + * not intended for use outside of the Telephony stack. * * @param callerDisplayName The new display name. * @param presentation The presentation requirements for the handle. * See {@link TelecomManager} for valid values. * @hide */ - public final void setCallerDisplayName(String callerDisplayName, int presentation) { + @SystemApi + @TestApi + public final void setCallerDisplayName(@NonNull String callerDisplayName, + @TelecomManager.Presentation int presentation) { Log.d(this, "setCallerDisplayName %s", callerDisplayName); mCallerDisplayName = callerDisplayName; mCallerDisplayNamePresentation = presentation; @@ -1088,10 +1022,15 @@ public abstract class Conference extends Conferenceable { } /** - * See {@link Connection#sendConnectionEvent(String, Bundle)} - * @hide + * Sends an event associated with this {@code Conference} with associated event extras to the + * {@link InCallService} (note: this is identical in concept to + * {@link Connection#sendConnectionEvent(String, Bundle)}). + * @see Connection#sendConnectionEvent(String, Bundle) + * + * @param event The connection event. + * @param extras Optional bundle containing extra information associated with the event. */ - public void sendConnectionEvent(String event, Bundle extras) { + public void sendConferenceEvent(@NonNull String event, @Nullable Bundle extras) { for (Listener l : mListeners) { l.onConnectionEvent(this, event, extras); } diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java deleted file mode 100644 index 5e4818a67b31..000000000000 --- a/telecomm/java/android/telecom/ConferenceParticipant.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2014 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.telecom; - -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.telephony.PhoneConstants; - -/** - * Parcelable representation of a participant's state in a conference call. - * @hide - */ -public class ConferenceParticipant implements Parcelable { - - /** - * RFC5767 states that a SIP URI with an unknown number should use an address of - * {@code anonymous@anonymous.invalid}. E.g. the host name is anonymous.invalid. - */ - private static final String ANONYMOUS_INVALID_HOST = "anonymous.invalid"; - /** - * The conference participant's handle (e.g., phone number). - */ - private final Uri mHandle; - - /** - * The display name for the participant. - */ - private final String mDisplayName; - - /** - * The endpoint Uri which uniquely identifies this conference participant. E.g. for an IMS - * conference call, this is the endpoint URI for the participant on the IMS conference server. - */ - private final Uri mEndpoint; - - /** - * The state of the participant in the conference. - * - * @see android.telecom.Connection - */ - private final int mState; - - /** - * The connect time of the participant. - */ - private long mConnectTime; - - /** - * The connect elapsed time of the participant. - */ - private long mConnectElapsedTime; - - /** - * The direction of the call; - * {@link Call.Details#DIRECTION_INCOMING} for incoming calls, or - * {@link Call.Details#DIRECTION_OUTGOING} for outgoing calls. - */ - private int mCallDirection; - - /** - * Creates an instance of {@code ConferenceParticipant}. - * - * @param handle The conference participant's handle (e.g., phone number). - * @param displayName The display name for the participant. - * @param endpoint The enpoint Uri which uniquely identifies this conference participant. - * @param state The state of the participant in the conference. - * @param callDirection The direction of the call (incoming/outgoing). - */ - public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state, - int callDirection) { - mHandle = handle; - mDisplayName = displayName; - mEndpoint = endpoint; - mState = state; - mCallDirection = callDirection; - } - - /** - * Responsible for creating {@code ConferenceParticipant} objects for deserialized Parcels. - */ - public static final @android.annotation.NonNull Parcelable.Creator<ConferenceParticipant> CREATOR = - new Parcelable.Creator<ConferenceParticipant>() { - - @Override - public ConferenceParticipant createFromParcel(Parcel source) { - ClassLoader classLoader = ParcelableCall.class.getClassLoader(); - Uri handle = source.readParcelable(classLoader); - String displayName = source.readString(); - Uri endpoint = source.readParcelable(classLoader); - int state = source.readInt(); - long connectTime = source.readLong(); - long elapsedRealTime = source.readLong(); - int callDirection = source.readInt(); - ConferenceParticipant participant = - new ConferenceParticipant(handle, displayName, endpoint, state, - callDirection); - participant.setConnectTime(connectTime); - participant.setConnectElapsedTime(elapsedRealTime); - participant.setCallDirection(callDirection); - return participant; - } - - @Override - public ConferenceParticipant[] newArray(int size) { - return new ConferenceParticipant[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - /** - * Determines the number presentation for a conference participant. Per RFC5767, if the host - * name contains {@code anonymous.invalid} we can assume that there is no valid caller ID - * information for the caller, otherwise we'll assume that the URI can be shown. - * - * @return The number presentation. - */ - @VisibleForTesting - public int getParticipantPresentation() { - Uri address = getHandle(); - if (address == null) { - return PhoneConstants.PRESENTATION_RESTRICTED; - } - - String number = address.getSchemeSpecificPart(); - // If no number, bail early and set restricted presentation. - if (TextUtils.isEmpty(number)) { - return PhoneConstants.PRESENTATION_RESTRICTED; - } - // Per RFC3261, the host name portion can also potentially include extra information: - // E.g. sip:anonymous1@anonymous.invalid;legid=1 - // In this case, hostName will be anonymous.invalid and there is an extra parameter for - // legid=1. - // Parameters are optional, and the address (e.g. test@test.com) will always be the first - // part, with any parameters coming afterwards. - String [] hostParts = number.split("[;]"); - String addressPart = hostParts[0]; - - // Get the number portion from the address part. - // This will typically be formatted similar to: 6505551212@test.com - String [] numberParts = addressPart.split("[@]"); - - // If we can't parse the host name out of the URI, then there is probably other data - // present, and is likely a valid SIP URI. - if (numberParts.length != 2) { - return PhoneConstants.PRESENTATION_ALLOWED; - } - String hostName = numberParts[1]; - - // If the hostname portion of the SIP URI is the invalid host string, presentation is - // restricted. - if (hostName.equals(ANONYMOUS_INVALID_HOST)) { - return PhoneConstants.PRESENTATION_RESTRICTED; - } - - return PhoneConstants.PRESENTATION_ALLOWED; - } - - /** - * Writes the {@code ConferenceParticipant} to a parcel. - * - * @param dest The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mHandle, 0); - dest.writeString(mDisplayName); - dest.writeParcelable(mEndpoint, 0); - dest.writeInt(mState); - dest.writeLong(mConnectTime); - dest.writeLong(mConnectElapsedTime); - dest.writeInt(mCallDirection); - } - - /** - * Builds a string representation of this instance. - * - * @return String representing the conference participant. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[ConferenceParticipant Handle: "); - sb.append(Log.pii(mHandle)); - sb.append(" DisplayName: "); - sb.append(Log.pii(mDisplayName)); - sb.append(" Endpoint: "); - sb.append(Log.pii(mEndpoint)); - sb.append(" State: "); - sb.append(Connection.stateToString(mState)); - sb.append(" ConnectTime: "); - sb.append(getConnectTime()); - sb.append(" ConnectElapsedTime: "); - sb.append(getConnectElapsedTime()); - sb.append(" Direction: "); - sb.append(getCallDirection() == Call.Details.DIRECTION_INCOMING ? "Incoming" : "Outgoing"); - sb.append("]"); - return sb.toString(); - } - - /** - * The conference participant's handle (e.g., phone number). - */ - public Uri getHandle() { - return mHandle; - } - - /** - * The display name for the participant. - */ - public String getDisplayName() { - return mDisplayName; - } - - /** - * The enpoint Uri which uniquely identifies this conference participant. E.g. for an IMS - * conference call, this is the endpoint URI for the participant on the IMS conference server. - */ - public Uri getEndpoint() { - return mEndpoint; - } - - /** - * The state of the participant in the conference. - * - * @see android.telecom.Connection - */ - public int getState() { - return mState; - } - - /** - * The connect time of the participant to the conference. - */ - public long getConnectTime() { - return mConnectTime; - } - - public void setConnectTime(long connectTime) { - this.mConnectTime = connectTime; - } - - /** - * The connect elapsed time of the participant to the conference. - */ - public long getConnectElapsedTime() { - return mConnectElapsedTime; - } - - public void setConnectElapsedTime(long connectElapsedTime) { - mConnectElapsedTime = connectElapsedTime; - } - - /** - * @return The direction of the call (incoming/outgoing). - */ - public @Call.Details.CallDirection int getCallDirection() { - return mCallDirection; - } - - /** - * Sets the direction of the call. - * @param callDirection Whether the call is incoming or outgoing. - */ - public void setCallDirection(@Call.Details.CallDirection int callDirection) { - mCallDirection = callDirection; - } - - /** - * Attempts to build a tel: style URI from a conference participant. - * Conference event package data contains SIP URIs, so we try to extract the phone number and - * format into a typical tel: style URI. - * - * @param address The conference participant's address. - * @param countryIso The country ISO of the current subscription; used when formatting the - * participant phone number to E.164 format. - * @return The participant's address URI. - * @hide - */ - @VisibleForTesting - public static Uri getParticipantAddress(Uri address, String countryIso) { - if (address == null) { - return address; - } - // Even if address is already in tel: format, still parse it and rebuild. - // This is to recognize tel URIs such as: - // tel:6505551212;phone-context=ims.mnc012.mcc034.3gppnetwork.org - - // Conference event package participants are identified using SIP URIs (see RFC3261). - // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers - // Per RFC3261, the "user" can be a telephone number. - // For example: sip:1650555121;phone-context=blah.com@host.com - // In this case, the phone number is in the user field of the URI, and the parameters can be - // ignored. - // - // A SIP URI can also specify a phone number in a format similar to: - // sip:+1-212-555-1212@something.com;user=phone - // In this case, the phone number is again in user field and the parameters can be ignored. - // We can get the user field in these instances by splitting the string on the @, ;, or : - // and looking at the first found item. - String number = address.getSchemeSpecificPart(); - if (TextUtils.isEmpty(number)) { - return address; - } - - String numberParts[] = number.split("[@;:]"); - if (numberParts.length == 0) { - return address; - } - number = numberParts[0]; - - // Attempt to format the number in E.164 format and use that as part of the TEL URI. - // RFC2806 recommends to format telephone numbers using E.164 since it is independent of - // how the dialing of said numbers takes place. - // If conversion to E.164 fails, the returned value is null. In that case, fallback to the - // number which was in the CEP data. - String formattedNumber = null; - if (!TextUtils.isEmpty(countryIso)) { - formattedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); - } - - return Uri.fromParts(PhoneAccount.SCHEME_TEL, - formattedNumber != null ? formattedNumber : number, null); - } -} diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 2ce84fbc0dc7..e2f5d0bba0b0 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -19,6 +19,7 @@ package android.telecom; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.Notification; import android.bluetooth.BluetoothDevice; @@ -273,6 +274,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; /** @@ -310,6 +312,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000; /** @@ -356,6 +359,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0; /** @@ -366,6 +370,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1; /** @@ -417,6 +422,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6; /** @@ -435,7 +441,10 @@ public abstract class Connection extends Conferenceable { /** * Set by the framework to indicate that a connection is using assisted dialing. - * @hide + * <p> + * This is used for outgoing calls. + * + * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING */ public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9; @@ -457,6 +466,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11; //********************************************************************************************** @@ -515,6 +525,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL"; @@ -857,7 +868,7 @@ public abstract class Connection extends Conferenceable { } /** @hide */ - public abstract static class Listener { + abstract static class Listener { public void onStateChanged(Connection c, int state) {} public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} public void onCallerDisplayNameChanged( @@ -1806,6 +1817,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final @Nullable String getTelecomCallId() { return mTelecomCallId; } @@ -1922,6 +1934,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final long getConnectTimeMillis() { return mConnectTimeMillis; } @@ -1941,32 +1954,12 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final long getConnectElapsedTimeMillis() { return mConnectElapsedTimeMillis; } /** - * Returns RIL voice radio technology used for current connection. - * <p> - * Used by the Telephony {@link ConnectionService}. - * - * @return the RIL voice radio technology used for current connection, - * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. - * - * @hide - */ - @SystemApi - public final @ServiceState.RilRadioTechnology int getCallRadioTech() { - int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - Bundle extras = getExtras(); - if (extras != null) { - voiceNetworkType = extras.getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, - TelephonyManager.NETWORK_TYPE_UNKNOWN); - } - return ServiceState.networkTypeToRilRadioTechnology(voiceNetworkType); - } - - /** * @return The status hints for this connection. */ public final StatusHints getStatusHints() { @@ -2005,7 +1998,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection addConnectionListener(Listener l) { + final Connection addConnectionListener(Listener l) { mListeners.add(l); return this; } @@ -2018,7 +2011,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection removeConnectionListener(Listener l) { + final Connection removeConnectionListener(Listener l) { if (l != null) { mListeners.remove(l); } @@ -2044,6 +2037,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public void setTelecomCallId(@NonNull String callId) { mTelecomCallId = callId; } @@ -2390,6 +2384,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final void setConnectTimeMillis(long connectTimeMillis) { mConnectTimeMillis = connectTimeMillis; } @@ -2405,39 +2400,12 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) { mConnectElapsedTimeMillis = connectElapsedTimeMillis; } /** - * Sets RIL voice radio technology used for current connection. - * <p> - * This property is set by the Telephony {@link ConnectionService}. - * - * @param vrat the RIL Voice Radio Technology used for current connection, - * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. - * - * @hide - */ - @SystemApi - public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) { - Bundle extras = getExtras(); - if (extras == null) { - extras = new Bundle(); - } - extras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, - ServiceState.rilRadioTechnologyToNetworkType(vrat)); - putExtras(extras); - // Propagates the call radio technology to its parent {@link android.telecom.Conference} - // This action only covers non-IMS CS conference calls. - // For IMS PS call conference call, it can be updated via its host connection - // {@link #Listener.onExtrasChanged} event. - if (getConference() != null) { - getConference().setCallRadioTech(vrat); - } - } - - /** * Sets the label and icon status to display in the in-call UI. * * @param statusHints The status label and icon to set. @@ -2501,6 +2469,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public final void resetConnectionTime() { for (Listener l : mListeners) { l.onConnectionTimeReset(this); @@ -3245,6 +3214,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) { if (mPhoneAccountHandle != phoneAccountHandle) { mPhoneAccountHandle = phoneAccountHandle; @@ -3263,6 +3233,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public @Nullable PhoneAccountHandle getPhoneAccountHandle() { return mPhoneAccountHandle; } @@ -3328,6 +3299,7 @@ public abstract class Connection extends Conferenceable { * @hide */ @SystemApi + @TestApi public void setCallDirection(@Call.Details.CallDirection int callDirection) { mCallDirection = callDirection; } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 0abd9fc62b14..812b805675e5 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -16,7 +16,11 @@ package android.telecom; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.app.Service; import android.content.ComponentName; import android.content.Intent; @@ -2106,15 +2110,21 @@ public abstract class ConnectionService extends Service { /** * Adds a connection created by the {@link ConnectionService} and informs telecom of the new - * connection. + * connection, as well as adding that connection to the specified conference. + * <p> + * Note: This API is intended ONLY for use by the Telephony stack to provide an easy way to add + * IMS conference participants to be added to a conference in a single step; this helps ensure + * UI updates happen atomically, rather than adding the connection and then adding it to + * the conference in another step. * * @param phoneAccountHandle The phone account handle for the connection. * @param connection The connection to add. * @param conference The parent conference of the new connection. * @hide */ - public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle, - Connection connection, Conference conference) { + @SystemApi + public final void addExistingConnection(@NonNull PhoneAccountHandle phoneAccountHandle, + @NonNull Connection connection, @NonNull Conference conference) { String id = addExistingConnectionInternal(phoneAccountHandle, connection); if (id != null) { diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index ae924645d3da..bebbbd01fd88 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -97,6 +97,14 @@ public final class DisconnectCause implements Parcelable { */ public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; + /** + * This reason is set when a call is ended in order to place an emergency call when a + * {@link PhoneAccount} doesn't support holding an ongoing call to place an emergency call. This + * reason string should only be associated with the {@link #LOCAL} disconnect code returned from + * {@link #getCode()}. + */ + public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; + private int mDisconnectCode; private CharSequence mDisconnectLabel; private CharSequence mDisconnectDescription; diff --git a/telecomm/java/android/telecom/Logging/Session.java b/telecomm/java/android/telecom/Logging/Session.java index 95a47e131272..d82e93fac76d 100644 --- a/telecomm/java/android/telecom/Logging/Session.java +++ b/telecomm/java/android/telecom/Logging/Session.java @@ -237,7 +237,10 @@ public class Session { // keep track of calls and bail if we hit the recursion limit private String getFullSessionId(int parentCount) { if (parentCount >= SESSION_RECURSION_LIMIT) { - Log.w(LOG_TAG, "getFullSessionId: Hit recursion limit!"); + // Don't use Telecom's Log.w here or it will cause infinite recursion because it will + // try to add session information to this logging statement, which will cause it to hit + // this condition again and so on... + android.util.Slog.w(LOG_TAG, "getFullSessionId: Hit recursion limit!"); return TRUNCATE_STRING + mSessionId; } // Cache mParentSession locally to prevent a concurrency problem where @@ -265,7 +268,11 @@ public class Session { Session topNode = this; while (topNode.getParentSession() != null) { if (currParentCount >= SESSION_RECURSION_LIMIT) { - Log.w(LOG_TAG, "getRootSession: Hit recursion limit from " + callingMethod); + // Don't use Telecom's Log.w here or it will cause infinite recursion because it + // will try to add session information to this logging statement, which will cause + // it to hit this condition again and so on... + android.util.Slog.w(LOG_TAG, "getRootSession: Hit recursion limit from " + + callingMethod); break; } topNode = topNode.getParentSession(); @@ -289,7 +296,10 @@ public class Session { private void printSessionTree(int tabI, StringBuilder sb, int currChildCount) { // Prevent infinite recursion. if (currChildCount >= SESSION_RECURSION_LIMIT) { - Log.w(LOG_TAG, "printSessionTree: Hit recursion limit!"); + // Don't use Telecom's Log.w here or it will cause infinite recursion because it will + // try to add session information to this logging statement, which will cause it to hit + // this condition again and so on... + android.util.Slog.w(LOG_TAG, "printSessionTree: Hit recursion limit!"); sb.append(TRUNCATE_STRING); return; } @@ -315,7 +325,10 @@ public class Session { private synchronized void getFullMethodPath(StringBuilder sb, boolean truncatePath, int parentCount) { if (parentCount >= SESSION_RECURSION_LIMIT) { - Log.w(LOG_TAG, "getFullMethodPath: Hit recursion limit!"); + // Don't use Telecom's Log.w here or it will cause infinite recursion because it will + // try to add session information to this logging statement, which will cause it to hit + // this condition again and so on... + android.util.Slog.w(LOG_TAG, "getFullMethodPath: Hit recursion limit!"); sb.append(TRUNCATE_STRING); return; } diff --git a/telecomm/java/android/telecom/Logging/SessionManager.java b/telecomm/java/android/telecom/Logging/SessionManager.java index 49c3a7205d59..ac300587cef8 100644 --- a/telecomm/java/android/telecom/Logging/SessionManager.java +++ b/telecomm/java/android/telecom/Logging/SessionManager.java @@ -202,7 +202,18 @@ public class SessionManager { return createSubsession(false); } - private synchronized Session createSubsession(boolean isStartedFromActiveSession) { + /** + * Creates a new subsession based on an existing session. Will not be started until + * {@link #continueSession(Session, String)} or {@link #cancelSubsession(Session)} is called. + * <p> + * Only public for testing! + * @param isStartedFromActiveSession true if this subsession is being created for a task on the + * same thread, false if it is being created for a related task on another thread. + * @return a new {@link Session}, call {@link #continueSession(Session, String)} to continue the + * session and {@link #endSession()} when done with this subsession. + */ + @VisibleForTesting + public synchronized Session createSubsession(boolean isStartedFromActiveSession) { int threadId = getCallingThreadId(); Session threadSession = mSessionMapper.get(threadId); if (threadSession == null) { diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index aa50991b118c..fdc324308d7a 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -21,6 +21,7 @@ import android.annotation.UnsupportedAppUsage; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; @@ -225,6 +226,10 @@ public final class ParcelableCall implements Parcelable { return mVideoCall; } + public IVideoProvider getVideoProvider() { + return mVideoCallProvider; + } + public boolean getIsRttCallChanged() { return mIsRttCallChanged; } diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index 2ecdb3035685..61a639a1a235 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -152,13 +152,20 @@ public final class Phone { return; } - Call call = new Call(this, parcelableCall.getId(), mInCallAdapter, - parcelableCall.getState(), mCallingPackage, mTargetSdkVersion); - mCallByTelecomCallId.put(parcelableCall.getId(), call); - mCalls.add(call); - checkCallTree(parcelableCall); - call.internalUpdate(parcelableCall, mCallByTelecomCallId); - fireCallAdded(call); + Call call = mCallByTelecomCallId.get(parcelableCall.getId()); + if (call == null) { + call = new Call(this, parcelableCall.getId(), mInCallAdapter, + parcelableCall.getState(), mCallingPackage, mTargetSdkVersion); + mCallByTelecomCallId.put(parcelableCall.getId(), call); + mCalls.add(call); + checkCallTree(parcelableCall); + call.internalUpdate(parcelableCall, mCallByTelecomCallId); + fireCallAdded(call); + } else { + Log.w(this, "Call %s added, but it was already present", call.internalGetCallId()); + checkCallTree(parcelableCall); + call.internalUpdate(parcelableCall, mCallByTelecomCallId); + } } final void internalRemoveCall(Call call) { @@ -190,7 +197,11 @@ public final class Phone { } else { // This call may have come out of audio processing. Try adding it if our target sdk // version is low enough. - if (mTargetSdkVersion < SDK_VERSION_R) { + // The only two allowable states coming out of audio processing are ACTIVE and + // SIMULATED_RINGING. + if (mTargetSdkVersion < SDK_VERSION_R && (parcelableCall.getState() == Call.STATE_ACTIVE + || parcelableCall.getState() == Call.STATE_SIMULATED_RINGING)) { + Log.i(this, "adding call during update for sdk compatibility"); internalAddCall(parcelableCall); } } diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 1b783b7beb7f..bb858cb0761b 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -16,7 +16,9 @@ package android.telecom; +import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.Intent; import android.graphics.drawable.Icon; import android.net.Uri; @@ -592,12 +594,17 @@ public final class PhoneAccount implements Parcelable { * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced. + * <p> + * Note: This is an API specific to the Telephony stack. + * * @param groupId The group Id of the {@link PhoneAccount} that will replace any other * registered {@link PhoneAccount} in Telecom with the same Group Id. * @return The builder * @hide */ - public Builder setGroupId(String groupId) { + @SystemApi + @TestApi + public @NonNull Builder setGroupId(@NonNull String groupId) { if (groupId != null) { mGroupId = groupId; } else { diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 12066c4caeb6..cda3387b8fac 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -14,6 +14,8 @@ package android.telecom; +import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; + import android.Manifest; import android.annotation.IntDef; import android.annotation.Nullable; @@ -33,6 +35,7 @@ import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.telephony.Annotation.CallState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -695,7 +698,17 @@ public class TelecomManager { /** * The boolean indicated by this extra controls whether or not a call is eligible to undergo * assisted dialing. This extra is stored under {@link #EXTRA_OUTGOING_CALL_EXTRAS}. - * @hide + * <p> + * The call initiator can use this extra to indicate that a call used assisted dialing to help + * place the call. This is most commonly used by a Dialer app which provides the ability to + * automatically add dialing prefixes when placing international calls. + * <p> + * Setting this extra on the outgoing call extras will cause the + * {@link Connection#PROPERTY_ASSISTED_DIALING_USED} property and + * {@link Call.Details#PROPERTY_ASSISTED_DIALING_USED} property to be set on the + * {@link Connection}/{@link Call} in question. When the call is logged to the call log, the + * {@link android.provider.CallLog.Calls#FEATURES_ASSISTED_DIALING_USED} call feature is set to + * indicate that assisted dialing was used for the call. */ public static final String EXTRA_USE_ASSISTED_DIALING = "android.telecom.extra.USE_ASSISTED_DIALING"; @@ -737,6 +750,14 @@ public class TelecomManager { */ public static final int PRESENTATION_PAYPHONE = 4; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = { "PRESENTATION_" }, + value = {PRESENTATION_ALLOWED, PRESENTATION_RESTRICTED, PRESENTATION_UNKNOWN, + PRESENTATION_PAYPHONE}) + public @interface Presentation {} + private static final String TAG = "TelecomManager"; private final Context mContext; @@ -882,9 +903,8 @@ public class TelecomManager { * queried for. * @return The phone account handle of the current sim call manager. * @see SubscriptionManager#getActiveSubscriptionInfoList() - * @hide */ - public PhoneAccountHandle getSimCallManagerForSubscription(int subscriptionId) { + public @Nullable PhoneAccountHandle getSimCallManagerForSubscription(int subscriptionId) { try { if (isServiceConnected()) { return getTelecomService().getSimCallManager(subscriptionId); @@ -946,7 +966,7 @@ public class TelecomManager { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE }) public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) { @@ -1233,6 +1253,28 @@ public class TelecomManager { } /** + * Used to determine the currently selected default dialer package for a specific user. + * + * @param userId the user id to query the default dialer package for. + * @return package name for the default dialer package or null if no package has been + * selected as the default dialer. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(READ_PRIVILEGED_PHONE_STATE) + public @Nullable String getDefaultDialerPackage(int userId) { + try { + if (isServiceConnected()) { + return getTelecomService().getDefaultDialerPackageForUser(userId); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException attempting to get the default dialer package name.", e); + } + return null; + } + + /** * Used to set the default dialer package. * * @param packageName to set the default dialer to, or {@code null} if the system provided @@ -1412,7 +1454,7 @@ public class TelecomManager { * @hide */ @SystemApi - public @TelephonyManager.CallState int getCallState() { + public @CallState int getCallState() { try { if (isServiceConnected()) { return getTelecomService().getCallState(); @@ -1431,7 +1473,7 @@ public class TelecomManager { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE }) public boolean isRinging() { @@ -1561,7 +1603,7 @@ public class TelecomManager { * Returns whether TTY is supported on this device. */ @RequiresPermission(anyOf = { - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE }) public boolean isTtySupported() { @@ -1587,7 +1629,7 @@ public class TelecomManager { */ @SystemApi @TestApi - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(READ_PRIVILEGED_PHONE_STATE) public @TtyMode int getCurrentTtyMode() { try { if (isServiceConnected()) { diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index cb74012e2b81..4a1aa0a8ffa4 100644 --- a/telecomm/java/android/telecom/VideoCallImpl.java +++ b/telecomm/java/android/telecom/VideoCallImpl.java @@ -32,6 +32,8 @@ import com.android.internal.os.SomeArgs; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; +import java.util.NoSuchElementException; + /** * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying * {@link Connection.VideoProvider}, and direct callbacks from the @@ -53,7 +55,11 @@ public class VideoCallImpl extends VideoCall { private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { - mVideoProvider.asBinder().unlinkToDeath(this, 0); + try { + mVideoProvider.asBinder().unlinkToDeath(this, 0); + } catch (NoSuchElementException nse) { + // Already unlinked in destroy below. + } } }; @@ -222,6 +228,11 @@ public class VideoCallImpl extends VideoCall { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196) public void destroy() { unregisterCallback(mCallback); + try { + mVideoProvider.asBinder().unlinkToDeath(mDeathRecipient, 0); + } catch (NoSuchElementException nse) { + // Already unlinked in binderDied above. + } } /** {@inheritDoc} */ @@ -353,4 +364,12 @@ public class VideoCallImpl extends VideoCall { public void setVideoState(int videoState) { mVideoState = videoState; } + + /** + * Get the video provider binder. + * @return the video provider binder. + */ + public IVideoProvider getVideoProvider() { + return mVideoProvider; + } } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 6a1b78fb79cf..33fdb9c5146e 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -146,6 +146,11 @@ interface ITelecomService { String getDefaultDialerPackage(); /** + * @see TelecomServiceImpl#getDefaultDialerPackage + */ + String getDefaultDialerPackageForUser(int userId); + + /** * @see TelecomServiceImpl#getSystemDialerPackage */ String getSystemDialerPackage(); diff --git a/telephony/common/com/android/internal/telephony/HbpcdLookup.java b/telephony/common/com/android/internal/telephony/HbpcdLookup.java new file mode 100644 index 000000000000..d9a3e725b6fb --- /dev/null +++ b/telephony/common/com/android/internal/telephony/HbpcdLookup.java @@ -0,0 +1,124 @@ +/* +** +** Copyright 2014, 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; + +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * @hide + */ +public class HbpcdLookup { + public static final String AUTHORITY = "hbpcd_lookup"; + + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY); + + public static final String PATH_MCC_IDD = "idd"; + public static final String PATH_MCC_LOOKUP_TABLE = "lookup"; + public static final String PATH_MCC_SID_CONFLICT = "conflict"; + public static final String PATH_MCC_SID_RANGE = "range"; + public static final String PATH_NANP_AREA_CODE = "nanp"; + public static final String PATH_ARBITRARY_MCC_SID_MATCH = "arbitrary"; + public static final String PATH_USERADD_COUNTRY = "useradd"; + + public static final String ID = "_id"; + public static final int IDINDEX = 0; + + /** + * @hide + */ + public static class MccIdd implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_IDD); + public static final String DEFAULT_SORT_ORDER = "MCC ASC"; + + public static final String MCC = "MCC"; + public static final String IDD = "IDD"; + + } + + /** + * @hide + */ + public static class MccLookup implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_LOOKUP_TABLE); + public static final String DEFAULT_SORT_ORDER = "MCC ASC"; + + public static final String MCC = "MCC"; + public static final String COUNTRY_CODE = "Country_Code"; + public static final String COUNTRY_NAME = "Country_Name"; + public static final String NDD = "NDD"; + public static final String NANPS = "NANPS"; + public static final String GMT_OFFSET_LOW = "GMT_Offset_Low"; + public static final String GMT_OFFSET_HIGH = "GMT_Offset_High"; + public static final String GMT_DST_LOW = "GMT_DST_Low"; + public static final String GMT_DST_HIGH = "GMT_DST_High"; + + } + + /** + * @hide + */ + public static class MccSidConflicts implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_SID_CONFLICT); + public static final String DEFAULT_SORT_ORDER = "MCC ASC"; + + public static final String MCC = "MCC"; + public static final String SID_CONFLICT = "SID_Conflict"; + + } + + /** + * @hide + */ + public static class MccSidRange implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_MCC_SID_RANGE); + public static final String DEFAULT_SORT_ORDER = "MCC ASC"; + + public static final String MCC = "MCC"; + public static final String RANGE_LOW = "SID_Range_Low"; + public static final String RANGE_HIGH = "SID_Range_High"; + } + + /** + * @hide + */ + public static class ArbitraryMccSidMatch implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_ARBITRARY_MCC_SID_MATCH); + public static final String DEFAULT_SORT_ORDER = "MCC ASC"; + + public static final String MCC = "MCC"; + public static final String SID = "SID"; + + } + + /** + * @hide + */ + public static class NanpAreaCode implements BaseColumns { + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/" + PATH_NANP_AREA_CODE); + public static final String DEFAULT_SORT_ORDER = "Area_Code ASC"; + + public static final String AREA_CODE = "Area_Code"; + } +} diff --git a/telephony/common/com/android/internal/telephony/HbpcdUtils.java b/telephony/common/com/android/internal/telephony/HbpcdUtils.java new file mode 100644 index 000000000000..2f3194214be6 --- /dev/null +++ b/telephony/common/com/android/internal/telephony/HbpcdUtils.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2014 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; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.telephony.Rlog; + +import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch; +import com.android.internal.telephony.HbpcdLookup.MccIdd; +import com.android.internal.telephony.HbpcdLookup.MccLookup; +import com.android.internal.telephony.HbpcdLookup.MccSidConflicts; +import com.android.internal.telephony.HbpcdLookup.MccSidRange; + +public final class HbpcdUtils { + private static final String LOG_TAG = "HbpcdUtils"; + private static final boolean DBG = false; + private ContentResolver resolver = null; + + public HbpcdUtils(Context context) { + resolver = context.getContentResolver(); + } + + /** + * Resolves the unknown MCC with SID and Timezone information. + */ + public int getMcc(int sid, int tz, int DSTflag, boolean isNitzTimeZone) { + int tmpMcc = 0; + + // check if SID exists in arbitrary_mcc_sid_match table. + // these SIDs are assigned to more than 1 operators, but they are known to + // be used by a specific operator, other operators having the same SID are + // not using it currently, if that SID is in this table, we don't need to + // check other tables. + String projection2[] = {ArbitraryMccSidMatch.MCC}; + Cursor c2 = resolver.query(ArbitraryMccSidMatch.CONTENT_URI, projection2, + ArbitraryMccSidMatch.SID + "=" + sid, null, null); + + if (c2 != null) { + int c2Counter = c2.getCount(); + if (DBG) { + Rlog.d(LOG_TAG, "Query unresolved arbitrary table, entries are " + c2Counter); + } + if (c2Counter == 1) { + if (DBG) { + Rlog.d(LOG_TAG, "Query Unresolved arbitrary returned the cursor " + c2); + } + c2.moveToFirst(); + tmpMcc = c2.getInt(0); + if (DBG) { + Rlog.d(LOG_TAG, "MCC found in arbitrary_mcc_sid_match: " + tmpMcc); + } + c2.close(); + return tmpMcc; + } + c2.close(); + } + + // Then check if SID exists in mcc_sid_conflict table. + // and use the timezone in mcc_lookup table to check which MCC matches. + String projection3[] = {MccSidConflicts.MCC}; + Cursor c3 = resolver.query(MccSidConflicts.CONTENT_URI, projection3, + MccSidConflicts.SID_CONFLICT + "=" + sid + " and (((" + + MccLookup.GMT_OFFSET_LOW + "<=" + tz + ") and (" + tz + "<=" + + MccLookup.GMT_OFFSET_HIGH + ") and (" + "0=" + DSTflag + ")) or ((" + + MccLookup.GMT_DST_LOW + "<=" + tz + ") and (" + tz + "<=" + + MccLookup.GMT_DST_HIGH + ") and (" + "1=" + DSTflag + ")))", + null, null); + if (c3 != null) { + int c3Counter = c3.getCount(); + if (c3Counter > 0) { + if (c3Counter > 1) { + Rlog.w(LOG_TAG, "something wrong, get more results for 1 conflict SID: " + c3); + } + if (DBG) Rlog.d(LOG_TAG, "Query conflict sid returned the cursor " + c3); + c3.moveToFirst(); + tmpMcc = c3.getInt(0); + if (DBG) { + Rlog.d(LOG_TAG, "MCC found in mcc_lookup_table. Return tmpMcc = " + tmpMcc); + } + if (!isNitzTimeZone) { + // time zone is not accurate, it may get wrong mcc, ignore it. + if (DBG) { + Rlog.d(LOG_TAG, "time zone is not accurate, mcc may be " + tmpMcc); + } + tmpMcc = 0; + } + c3.close(); + return tmpMcc; + } else { + c3.close(); + } + } + + // if there is no conflict, then check if SID is in mcc_sid_range. + String projection5[] = {MccSidRange.MCC}; + Cursor c5 = resolver.query(MccSidRange.CONTENT_URI, projection5, + MccSidRange.RANGE_LOW + "<=" + sid + " and " + + MccSidRange.RANGE_HIGH + ">=" + sid, + null, null); + if (c5 != null) { + if (c5.getCount() > 0) { + if (DBG) Rlog.d(LOG_TAG, "Query Range returned the cursor " + c5); + c5.moveToFirst(); + tmpMcc = c5.getInt(0); + if (DBG) Rlog.d(LOG_TAG, "SID found in mcc_sid_range. Return tmpMcc = " + tmpMcc); + c5.close(); + return tmpMcc; + } + c5.close(); + } + if (DBG) Rlog.d(LOG_TAG, "SID NOT found in mcc_sid_range."); + + if (DBG) Rlog.d(LOG_TAG, "Exit getMccByOtherFactors. Return tmpMcc = " + tmpMcc); + // If unknown MCC still could not be resolved, + return tmpMcc; + } + + /** + * Gets country information with given MCC. + */ + public String getIddByMcc(int mcc) { + if (DBG) Rlog.d(LOG_TAG, "Enter getHbpcdInfoByMCC."); + String idd = ""; + + Cursor c = null; + + String projection[] = {MccIdd.IDD}; + Cursor cur = resolver.query(MccIdd.CONTENT_URI, projection, + MccIdd.MCC + "=" + mcc, null, null); + if (cur != null) { + if (cur.getCount() > 0) { + if (DBG) Rlog.d(LOG_TAG, "Query Idd returned the cursor " + cur); + // TODO: for those country having more than 1 IDDs, need more information + // to decide which IDD would be used. currently just use the first 1. + cur.moveToFirst(); + idd = cur.getString(0); + if (DBG) Rlog.d(LOG_TAG, "IDD = " + idd); + + } + cur.close(); + } + if (c != null) c.close(); + + if (DBG) Rlog.d(LOG_TAG, "Exit getHbpcdInfoByMCC."); + return idd; + } +} diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index f17a1a5c694c..f79aef3ae5c9 100644 --- a/telephony/java/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -40,7 +40,6 @@ import android.os.UserHandle; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; import android.telephony.Rlog; -import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.util.Log; @@ -48,6 +47,8 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -57,6 +58,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; + + /** * Class for managing the primary application that we will deliver SMS/MMS messages to * @@ -91,6 +94,7 @@ public final class SmsApplication { /** * Name of this SMS app for display. */ + @UnsupportedAppUsage private String mApplicationName; /** @@ -224,6 +228,7 @@ public final class SmsApplication { * Implement ACTION_SENDTO intent. * Support smsto Uri scheme. */ + @UnsupportedAppUsage public static Collection<SmsApplicationData> getApplicationCollection(Context context) { return getApplicationCollectionAsUser(context, getIncomingUserId(context)); } @@ -579,6 +584,7 @@ public final class SmsApplication { * Sets the specified package as the default SMS/MMS application. The caller of this method * needs to have permission to set AppOps and write to secure settings. */ + @UnsupportedAppUsage public static void setDefaultApplication(String packageName, Context context) { setDefaultApplicationAsUser(packageName, context, getIncomingUserId(context)); } @@ -826,6 +832,7 @@ public final class SmsApplication { sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL, false); } + @UnsupportedAppUsage private static void configurePreferredActivity(PackageManager packageManager, ComponentName componentName, int userId) { // Add the four activity preferences we want to direct to this app. @@ -868,6 +875,7 @@ public final class SmsApplication { * Returns SmsApplicationData for this package if this package is capable of being set as the * default SMS application. */ + @UnsupportedAppUsage public static SmsApplicationData getSmsApplicationData(String packageName, Context context) { Collection<SmsApplicationData> applications = getApplicationCollection(context); return getApplicationForPackage(applications, packageName); @@ -879,6 +887,7 @@ public final class SmsApplication { * @param updateIfNeeded update the default app if there is no valid default app configured. * @return component name of the app and class to deliver SMS messages to */ + @UnsupportedAppUsage public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) { return getDefaultSmsApplicationAsUser(context, updateIfNeeded, getIncomingUserId(context)); } @@ -913,6 +922,7 @@ public final class SmsApplication { * @param updateIfNeeded update the default app if there is no valid default app configured. * @return component name of the app and class to deliver MMS messages to */ + @UnsupportedAppUsage public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) { int userId = getIncomingUserId(context); final long token = Binder.clearCallingIdentity(); @@ -936,6 +946,7 @@ public final class SmsApplication { * @param updateIfNeeded update the default app if there is no valid default app configured. * @return component name of the app and class to direct Respond Via Message intent to */ + @UnsupportedAppUsage public static ComponentName getDefaultRespondViaMessageApplication(Context context, boolean updateIfNeeded) { int userId = getIncomingUserId(context); @@ -1036,10 +1047,8 @@ public final class SmsApplication { * <p> * Caller must pass in the correct user context if calling from a singleton service. */ + @UnsupportedAppUsage public static boolean shouldWriteMessageForPackage(String packageName, Context context) { - if (SmsManager.getDefault().getAutoPersisting()) { - return true; - } return !isDefaultSmsApplication(context, packageName); } @@ -1050,6 +1059,7 @@ public final class SmsApplication { * @param packageName the name of the package to be checked * @return true if the package is default sms app or bluetooth */ + @UnsupportedAppUsage public static boolean isDefaultSmsApplication(Context context, String packageName) { if (packageName == null) { return false; diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java new file mode 100644 index 000000000000..0d33af639113 --- /dev/null +++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Context; +import android.database.Cursor; +import android.database.SQLException; +import android.os.Binder; +import android.os.Build; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.PhoneNumberUtils; +import android.telephony.Rlog; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +import com.android.internal.telephony.HbpcdLookup.MccIdd; +import com.android.internal.telephony.HbpcdLookup.MccLookup; + +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * This class implements handle the MO SMS target address before sending. + * This is special for VZW requirement. Follow the specifications of assisted dialing + * of MO SMS while traveling on VZW CDMA, international CDMA or GSM markets. + * {@hide} + */ +public class SmsNumberUtils { + private static final String TAG = "SmsNumberUtils"; + private static final boolean DBG = Build.IS_DEBUGGABLE; + + private static final String PLUS_SIGN = "+"; + + private static final int NANP_SHORT_LENGTH = 7; + private static final int NANP_MEDIUM_LENGTH = 10; + private static final int NANP_LONG_LENGTH = 11; + + private static final int NANP_CC = 1; + private static final String NANP_NDD = "1"; + private static final String NANP_IDD = "011"; + + private static final int MIN_COUNTRY_AREA_LOCAL_LENGTH = 10; + + private static final int GSM_UMTS_NETWORK = 0; + private static final int CDMA_HOME_NETWORK = 1; + private static final int CDMA_ROAMING_NETWORK = 2; + + private static final int NP_NONE = 0; + private static final int NP_NANP_BEGIN = 1; + + /* <Phone Number>, <NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_LOCAL = NP_NANP_BEGIN; + + /* <Area_code>-<Phone Number>, <NXX>-<NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_AREA_LOCAL = NP_NANP_BEGIN + 1; + + /* <1>-<Area_code>-<Phone Number>, 1-<NXX>-<NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_NDD_AREA_LOCAL = NP_NANP_BEGIN + 2; + + /* <+><U.S.Country_code><Area_code><Phone Number>, +1-<NXX>-<NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_NBPCD_CC_AREA_LOCAL = NP_NANP_BEGIN + 3; + + /* <Local_IDD><Country_code><Area_code><Phone Number>, 001-1-<NXX>-<NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_LOCALIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 4; + + /* <+><Home_IDD><Country_code><Area_code><Phone Number>, +011-1-<NXX>-<NXX>-<XXXX> N[2-9] */ + private static final int NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 5; + + private static final int NP_INTERNATIONAL_BEGIN = 100; + /* <+>-<Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, +011-86-25-86281234 */ + private static final int NP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN; + + /* <Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, 011-86-25-86281234 */ + private static final int NP_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 1; + + /* <NBPCD>-<Country_code>-<Area_code>-<Phone Number>, +1-86-25-86281234 */ + private static final int NP_NBPCD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 2; + + /* <Local_IDD>-<Country_code>-<Area_code>-<Phone Number>, 00-86-25-86281234 */ + private static final int NP_LOCALIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 3; + + /* <Country_code>-<Area_code>-<Phone Number>, 86-25-86281234*/ + private static final int NP_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 4; + + private static int[] ALL_COUNTRY_CODES = null; + private static int MAX_COUNTRY_CODES_LENGTH; + private static HashMap<String, ArrayList<String>> IDDS_MAPS = + new HashMap<String, ArrayList<String>>(); + + private static class NumberEntry { + public String number; + public String IDD; + public int countryCode; + public NumberEntry(String number) { + this.number = number; + } + } + + /** + * Breaks the given number down and formats it according to the rules + * for different number plans and different network. + * + * @param number destination number which need to be format + * @param activeMcc current network's mcc + * @param networkType current network type + * + * @return the number after formatting. + */ + private static String formatNumber(Context context, String number, + String activeMcc, + int networkType) { + if (number == null ) { + throw new IllegalArgumentException("number is null"); + } + + if (activeMcc == null || activeMcc.trim().length() == 0) { + throw new IllegalArgumentException("activeMcc is null or empty!"); + } + + String networkPortionNumber = PhoneNumberUtils.extractNetworkPortion(number); + if (networkPortionNumber == null || networkPortionNumber.length() == 0) { + throw new IllegalArgumentException("Number is invalid!"); + } + + NumberEntry numberEntry = new NumberEntry(networkPortionNumber); + ArrayList<String> allIDDs = getAllIDDs(context, activeMcc); + + // First check whether the number is a NANP number. + int nanpState = checkNANP(numberEntry, allIDDs); + if (DBG) Rlog.d(TAG, "NANP type: " + getNumberPlanType(nanpState)); + + if ((nanpState == NP_NANP_LOCAL) + || (nanpState == NP_NANP_AREA_LOCAL) + || (nanpState == NP_NANP_NDD_AREA_LOCAL)) { + return networkPortionNumber; + } else if (nanpState == NP_NANP_NBPCD_CC_AREA_LOCAL) { + if (networkType == CDMA_HOME_NETWORK + || networkType == CDMA_ROAMING_NETWORK) { + // Remove "+" + return networkPortionNumber.substring(1); + } else { + return networkPortionNumber; + } + } else if (nanpState == NP_NANP_LOCALIDD_CC_AREA_LOCAL) { + if (networkType == CDMA_HOME_NETWORK) { + return networkPortionNumber; + } else if (networkType == GSM_UMTS_NETWORK) { + // Remove the local IDD and replace with "+" + int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; + return PLUS_SIGN + networkPortionNumber.substring(iddLength); + } else if (networkType == CDMA_ROAMING_NETWORK) { + // Remove the local IDD + int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; + return networkPortionNumber.substring(iddLength); + } + } + + int internationalState = checkInternationalNumberPlan(context, numberEntry, allIDDs, + NANP_IDD); + if (DBG) Rlog.d(TAG, "International type: " + getNumberPlanType(internationalState)); + String returnNumber = null; + + switch (internationalState) { + case NP_NBPCD_HOMEIDD_CC_AREA_LOCAL: + if (networkType == GSM_UMTS_NETWORK) { + // Remove "+" + returnNumber = networkPortionNumber.substring(1); + } + break; + + case NP_NBPCD_CC_AREA_LOCAL: + // Replace "+" with "011" + returnNumber = NANP_IDD + networkPortionNumber.substring(1); + break; + + case NP_LOCALIDD_CC_AREA_LOCAL: + if (networkType == GSM_UMTS_NETWORK || networkType == CDMA_ROAMING_NETWORK) { + int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; + // Replace <Local IDD> to <Home IDD>("011") + returnNumber = NANP_IDD + networkPortionNumber.substring(iddLength); + } + break; + + case NP_CC_AREA_LOCAL: + int countryCode = numberEntry.countryCode; + + if (!inExceptionListForNpCcAreaLocal(numberEntry) + && networkPortionNumber.length() >= 11 && countryCode != NANP_CC) { + // Add "011" + returnNumber = NANP_IDD + networkPortionNumber; + } + break; + + case NP_HOMEIDD_CC_AREA_LOCAL: + returnNumber = networkPortionNumber; + break; + + default: + // Replace "+" with 011 in CDMA network if the number's country + // code is not in the HbpcdLookup database. + if (networkPortionNumber.startsWith(PLUS_SIGN) + && (networkType == CDMA_HOME_NETWORK || networkType == CDMA_ROAMING_NETWORK)) { + if (networkPortionNumber.startsWith(PLUS_SIGN + NANP_IDD)) { + // Only remove "+" + returnNumber = networkPortionNumber.substring(1); + } else { + // Replace "+" with "011" + returnNumber = NANP_IDD + networkPortionNumber.substring(1); + } + } + } + + if (returnNumber == null) { + returnNumber = networkPortionNumber; + } + return returnNumber; + } + + /** + * Query International direct dialing from HbpcdLookup.db + * for specified country code + * + * @param mcc current network's country code + * + * @return the IDD array list. + */ + private static ArrayList<String> getAllIDDs(Context context, String mcc) { + ArrayList<String> allIDDs = IDDS_MAPS.get(mcc); + if (allIDDs != null) { + return allIDDs; + } else { + allIDDs = new ArrayList<String>(); + } + + String projection[] = {MccIdd.IDD, MccIdd.MCC}; + String where = null; + + // if mcc is null : return all rows + // if mcc is empty-string : return those rows whose mcc is emptry-string + String[] selectionArgs = null; + if (mcc != null) { + where = MccIdd.MCC + "=?"; + selectionArgs = new String[] {mcc}; + } + + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(MccIdd.CONTENT_URI, projection, + where, selectionArgs, null); + if (cursor.getCount() > 0) { + while (cursor.moveToNext()) { + String idd = cursor.getString(0); + if (!allIDDs.contains(idd)) { + allIDDs.add(idd); + } + } + } + } catch (SQLException e) { + Rlog.e(TAG, "Can't access HbpcdLookup database", e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + + IDDS_MAPS.put(mcc, allIDDs); + + if (DBG) Rlog.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs); + return allIDDs; + } + + + /** + * Verify if the the destination number is a NANP number + * + * @param numberEntry including number and IDD array + * @param allIDDs the IDD array list of the current network's country code + * + * @return the number plan type related NANP + */ + private static int checkNANP(NumberEntry numberEntry, ArrayList<String> allIDDs) { + boolean isNANP = false; + String number = numberEntry.number; + + if (number.length() == NANP_SHORT_LENGTH) { + // 7 digits - Seven digit phone numbers + char firstChar = number.charAt(0); + if (firstChar >= '2' && firstChar <= '9') { + isNANP = true; + for (int i=1; i< NANP_SHORT_LENGTH; i++ ) { + char c= number.charAt(i); + if (!PhoneNumberUtils.isISODigit(c)) { + isNANP = false; + break; + } + } + } + if (isNANP) { + return NP_NANP_LOCAL; + } + } else if (number.length() == NANP_MEDIUM_LENGTH) { + // 10 digits - Three digit area code followed by seven digit phone numbers/ + if (isNANP(number)) { + return NP_NANP_AREA_LOCAL; + } + } else if (number.length() == NANP_LONG_LENGTH) { + // 11 digits - One digit U.S. NDD(National Direct Dial) prefix '1', + // followed by three digit area code and seven digit phone numbers + if (isNANP(number)) { + return NP_NANP_NDD_AREA_LOCAL; + } + } else if (number.startsWith(PLUS_SIGN)) { + number = number.substring(1); + if (number.length() == NANP_LONG_LENGTH) { + // '+' and 11 digits -'+', followed by NANP CC prefix '1' followed by + // three digit area code and seven digit phone numbers + if (isNANP(number)) { + return NP_NANP_NBPCD_CC_AREA_LOCAL; + } + } else if (number.startsWith(NANP_IDD) && number.length() == NANP_LONG_LENGTH + 3) { + // '+' and 14 digits -'+', followed by NANP IDD "011" followed by NANP CC + // prefix '1' followed by three digit area code and seven digit phone numbers + number = number.substring(3); + if (isNANP(number)) { + return NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL; + } + } + } else { + // Check whether it's NP_NANP_LOCALIDD_CC_AREA_LOCAL + for (String idd : allIDDs) { + if (number.startsWith(idd)) { + String number2 = number.substring(idd.length()); + if(number2 !=null && number2.startsWith(String.valueOf(NANP_CC))){ + if (isNANP(number2)) { + numberEntry.IDD = idd; + return NP_NANP_LOCALIDD_CC_AREA_LOCAL; + } + } + } + } + } + + return NP_NONE; + } + + private static boolean isNANP(String number) { + if (number.length() == NANP_MEDIUM_LENGTH + || (number.length() == NANP_LONG_LENGTH && number.startsWith(NANP_NDD))) { + if (number.length() == NANP_LONG_LENGTH) { + number = number.substring(1); + } + return (PhoneNumberUtils.isNanp(number)); + } + return false; + } + + /** + * Verify if the the destination number is an internal number + * + * @param numberEntry including number and IDD array + * @param allIDDs the IDD array list of the current network's country code + * + * @return the number plan type related international number + */ + private static int checkInternationalNumberPlan(Context context, NumberEntry numberEntry, + ArrayList<String> allIDDs,String homeIDD) { + String number = numberEntry.number; + int countryCode = -1; + + if (number.startsWith(PLUS_SIGN)) { + // +xxxxxxxxxx + String numberNoNBPCD = number.substring(1); + if (numberNoNBPCD.startsWith(homeIDD)) { + // +011xxxxxxxx + String numberCountryAreaLocal = numberNoNBPCD.substring(homeIDD.length()); + if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) { + numberEntry.countryCode = countryCode; + return NP_NBPCD_HOMEIDD_CC_AREA_LOCAL; + } + } else if ((countryCode = getCountryCode(context, numberNoNBPCD)) > 0) { + numberEntry.countryCode = countryCode; + return NP_NBPCD_CC_AREA_LOCAL; + } + + } else if (number.startsWith(homeIDD)) { + // 011xxxxxxxxx + String numberCountryAreaLocal = number.substring(homeIDD.length()); + if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) { + numberEntry.countryCode = countryCode; + return NP_HOMEIDD_CC_AREA_LOCAL; + } + } else { + for (String exitCode : allIDDs) { + if (number.startsWith(exitCode)) { + String numberNoIDD = number.substring(exitCode.length()); + if ((countryCode = getCountryCode(context, numberNoIDD)) > 0) { + numberEntry.countryCode = countryCode; + numberEntry.IDD = exitCode; + return NP_LOCALIDD_CC_AREA_LOCAL; + } + } + } + + if (!number.startsWith("0") && (countryCode = getCountryCode(context, number)) > 0) { + numberEntry.countryCode = countryCode; + return NP_CC_AREA_LOCAL; + } + } + return NP_NONE; + } + + /** + * Returns the country code from the given number. + */ + private static int getCountryCode(Context context, String number) { + int countryCode = -1; + if (number.length() >= MIN_COUNTRY_AREA_LOCAL_LENGTH) { + // Check Country code + int[] allCCs = getAllCountryCodes(context); + if (allCCs == null) { + return countryCode; + } + + int[] ccArray = new int[MAX_COUNTRY_CODES_LENGTH]; + for (int i = 0; i < MAX_COUNTRY_CODES_LENGTH; i ++) { + ccArray[i] = Integer.parseInt(number.substring(0, i+1)); + } + + for (int i = 0; i < allCCs.length; i ++) { + int tempCC = allCCs[i]; + for (int j = 0; j < MAX_COUNTRY_CODES_LENGTH; j ++) { + if (tempCC == ccArray[j]) { + if (DBG) Rlog.d(TAG, "Country code = " + tempCC); + return tempCC; + } + } + } + } + + return countryCode; + } + + /** + * Gets all country Codes information with given MCC. + */ + private static int[] getAllCountryCodes(Context context) { + if (ALL_COUNTRY_CODES != null) { + return ALL_COUNTRY_CODES; + } + + Cursor cursor = null; + try { + String projection[] = {MccLookup.COUNTRY_CODE}; + cursor = context.getContentResolver().query(MccLookup.CONTENT_URI, + projection, null, null, null); + + if (cursor.getCount() > 0) { + ALL_COUNTRY_CODES = new int[cursor.getCount()]; + int i = 0; + while (cursor.moveToNext()) { + int countryCode = cursor.getInt(0); + ALL_COUNTRY_CODES[i++] = countryCode; + int length = String.valueOf(countryCode).trim().length(); + if (length > MAX_COUNTRY_CODES_LENGTH) { + MAX_COUNTRY_CODES_LENGTH = length; + } + } + } + } catch (SQLException e) { + Rlog.e(TAG, "Can't access HbpcdLookup database", e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return ALL_COUNTRY_CODES; + } + + private static boolean inExceptionListForNpCcAreaLocal(NumberEntry numberEntry) { + int countryCode = numberEntry.countryCode; + boolean result = (numberEntry.number.length() == 12 + && (countryCode == 7 || countryCode == 20 + || countryCode == 65 || countryCode == 90)); + return result; + } + + private static String getNumberPlanType(int state) { + String numberPlanType = "Number Plan type (" + state + "): "; + + if (state == NP_NANP_LOCAL) { + numberPlanType = "NP_NANP_LOCAL"; + } else if (state == NP_NANP_AREA_LOCAL) { + numberPlanType = "NP_NANP_AREA_LOCAL"; + } else if (state == NP_NANP_NDD_AREA_LOCAL) { + numberPlanType = "NP_NANP_NDD_AREA_LOCAL"; + } else if (state == NP_NANP_NBPCD_CC_AREA_LOCAL) { + numberPlanType = "NP_NANP_NBPCD_CC_AREA_LOCAL"; + } else if (state == NP_NANP_LOCALIDD_CC_AREA_LOCAL) { + numberPlanType = "NP_NANP_LOCALIDD_CC_AREA_LOCAL"; + } else if (state == NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL) { + numberPlanType = "NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL"; + } else if (state == NP_NBPCD_HOMEIDD_CC_AREA_LOCAL) { + numberPlanType = "NP_NBPCD_HOMEIDD_CC_AREA_LOCAL"; + } else if (state == NP_HOMEIDD_CC_AREA_LOCAL) { + numberPlanType = "NP_HOMEIDD_CC_AREA_LOCAL"; + } else if (state == NP_NBPCD_CC_AREA_LOCAL) { + numberPlanType = "NP_NBPCD_CC_AREA_LOCAL"; + } else if (state == NP_LOCALIDD_CC_AREA_LOCAL) { + numberPlanType = "NP_LOCALIDD_CC_AREA_LOCAL"; + } else if (state == NP_CC_AREA_LOCAL) { + numberPlanType = "NP_CC_AREA_LOCAL"; + } else { + numberPlanType = "Unknown type"; + } + return numberPlanType; + } + + /** + * Filter the destination number if using VZW sim card. + */ + public static String filterDestAddr(Context context, int subId, String destAddr) { + if (DBG) Rlog.d(TAG, "enter filterDestAddr. destAddr=\"" + Rlog.pii(TAG, destAddr) + "\"" ); + + if (destAddr == null || !PhoneNumberUtils.isGlobalPhoneNumber(destAddr)) { + Rlog.w(TAG, "destAddr" + Rlog.pii(TAG, destAddr) + + " is not a global phone number! Nothing changed."); + return destAddr; + } + + final TelephonyManager telephonyManager = ((TelephonyManager) context + .getSystemService(Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId); + final String networkOperator = telephonyManager.getNetworkOperator(); + String result = null; + + if (needToConvert(context, subId)) { + final int networkType = getNetworkType(telephonyManager); + if (networkType != -1 && !TextUtils.isEmpty(networkOperator)) { + String networkMcc = networkOperator.substring(0, 3); + if (networkMcc != null && networkMcc.trim().length() > 0) { + result = formatNumber(context, destAddr, networkMcc, networkType); + } + } + } + + if (DBG) { + Rlog.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted.")); + Rlog.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? Rlog.pii(TAG, + result) : Rlog.pii(TAG, destAddr)) + "\""); + } + return result != null ? result : destAddr; + } + + /** + * Returns the current network type + */ + private static int getNetworkType(TelephonyManager telephonyManager) { + int networkType = -1; + int phoneType = telephonyManager.getPhoneType(); + + if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { + networkType = GSM_UMTS_NETWORK; + } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { + if (isInternationalRoaming(telephonyManager)) { + networkType = CDMA_ROAMING_NETWORK; + } else { + networkType = CDMA_HOME_NETWORK; + } + } else { + if (DBG) Rlog.w(TAG, "warning! unknown mPhoneType value=" + phoneType); + } + + return networkType; + } + + private static boolean isInternationalRoaming(TelephonyManager telephonyManager) { + String operatorIsoCountry = telephonyManager.getNetworkCountryIso(); + String simIsoCountry = telephonyManager.getSimCountryIso(); + boolean internationalRoaming = !TextUtils.isEmpty(operatorIsoCountry) + && !TextUtils.isEmpty(simIsoCountry) + && !simIsoCountry.equals(operatorIsoCountry); + if (internationalRoaming) { + if ("us".equals(simIsoCountry)) { + internationalRoaming = !"vi".equals(operatorIsoCountry); + } else if ("vi".equals(simIsoCountry)) { + internationalRoaming = !"us".equals(operatorIsoCountry); + } + } + return internationalRoaming; + } + + private static boolean needToConvert(Context context, int subId) { + // Calling package may not have READ_PHONE_STATE which is required for getConfig(). + // Clear the calling identity so that it is called as self. + final long identity = Binder.clearCallingIdentity(); + try { + CarrierConfigManager configManager = (CarrierConfigManager) + context.getSystemService(Context.CARRIER_CONFIG_SERVICE); + if (configManager != null) { + PersistableBundle bundle = configManager.getConfigForSubId(subId); + if (bundle != null) { + return bundle.getBoolean(CarrierConfigManager + .KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + // by default this value is false + return false; + } +} diff --git a/telephony/common/com/google/android/mms/ContentType.java b/telephony/common/com/google/android/mms/ContentType.java new file mode 100644 index 000000000000..12e4b7e26e1e --- /dev/null +++ b/telephony/common/com/google/android/mms/ContentType.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.util.ArrayList; + +public class ContentType { + public static final String MMS_MESSAGE = "application/vnd.wap.mms-message"; + // The phony content type for generic PDUs (e.g. ReadOrig.ind, + // Notification.ind, Delivery.ind). + public static final String MMS_GENERIC = "application/vnd.wap.mms-generic"; + public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed"; + public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related"; + public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative"; + + public static final String TEXT_PLAIN = "text/plain"; + public static final String TEXT_HTML = "text/html"; + public static final String TEXT_VCALENDAR = "text/x-vCalendar"; + public static final String TEXT_VCARD = "text/x-vCard"; + + public static final String IMAGE_UNSPECIFIED = "image/*"; + public static final String IMAGE_JPEG = "image/jpeg"; + public static final String IMAGE_JPG = "image/jpg"; + public static final String IMAGE_GIF = "image/gif"; + public static final String IMAGE_WBMP = "image/vnd.wap.wbmp"; + public static final String IMAGE_PNG = "image/png"; + public static final String IMAGE_X_MS_BMP = "image/x-ms-bmp"; + + public static final String AUDIO_UNSPECIFIED = "audio/*"; + public static final String AUDIO_AAC = "audio/aac"; + public static final String AUDIO_AMR = "audio/amr"; + public static final String AUDIO_IMELODY = "audio/imelody"; + public static final String AUDIO_MID = "audio/mid"; + public static final String AUDIO_MIDI = "audio/midi"; + public static final String AUDIO_MP3 = "audio/mp3"; + public static final String AUDIO_MPEG3 = "audio/mpeg3"; + public static final String AUDIO_MPEG = "audio/mpeg"; + public static final String AUDIO_MPG = "audio/mpg"; + public static final String AUDIO_MP4 = "audio/mp4"; + public static final String AUDIO_X_MID = "audio/x-mid"; + public static final String AUDIO_X_MIDI = "audio/x-midi"; + public static final String AUDIO_X_MP3 = "audio/x-mp3"; + public static final String AUDIO_X_MPEG3 = "audio/x-mpeg3"; + public static final String AUDIO_X_MPEG = "audio/x-mpeg"; + public static final String AUDIO_X_MPG = "audio/x-mpg"; + public static final String AUDIO_3GPP = "audio/3gpp"; + public static final String AUDIO_X_WAV = "audio/x-wav"; + public static final String AUDIO_OGG = "application/ogg"; + public static final String AUDIO_OGG2 = "audio/ogg"; + + public static final String VIDEO_UNSPECIFIED = "video/*"; + public static final String VIDEO_3GPP = "video/3gpp"; + public static final String VIDEO_3G2 = "video/3gpp2"; + public static final String VIDEO_H263 = "video/h263"; + public static final String VIDEO_MP4 = "video/mp4"; + + public static final String APP_SMIL = "application/smil"; + public static final String APP_WAP_XHTML = "application/vnd.wap.xhtml+xml"; + public static final String APP_XHTML = "application/xhtml+xml"; + + public static final String APP_DRM_CONTENT = "application/vnd.oma.drm.content"; + public static final String APP_DRM_MESSAGE = "application/vnd.oma.drm.message"; + + private static final ArrayList<String> sSupportedContentTypes = new ArrayList<String>(); + private static final ArrayList<String> sSupportedImageTypes = new ArrayList<String>(); + private static final ArrayList<String> sSupportedAudioTypes = new ArrayList<String>(); + private static final ArrayList<String> sSupportedVideoTypes = new ArrayList<String>(); + + static { + sSupportedContentTypes.add(TEXT_PLAIN); + sSupportedContentTypes.add(TEXT_HTML); + sSupportedContentTypes.add(TEXT_VCALENDAR); + sSupportedContentTypes.add(TEXT_VCARD); + + sSupportedContentTypes.add(IMAGE_JPEG); + sSupportedContentTypes.add(IMAGE_GIF); + sSupportedContentTypes.add(IMAGE_WBMP); + sSupportedContentTypes.add(IMAGE_PNG); + sSupportedContentTypes.add(IMAGE_JPG); + sSupportedContentTypes.add(IMAGE_X_MS_BMP); + //supportedContentTypes.add(IMAGE_SVG); not yet supported. + + sSupportedContentTypes.add(AUDIO_AAC); + sSupportedContentTypes.add(AUDIO_AMR); + sSupportedContentTypes.add(AUDIO_IMELODY); + sSupportedContentTypes.add(AUDIO_MID); + sSupportedContentTypes.add(AUDIO_MIDI); + sSupportedContentTypes.add(AUDIO_MP3); + sSupportedContentTypes.add(AUDIO_MP4); + sSupportedContentTypes.add(AUDIO_MPEG3); + sSupportedContentTypes.add(AUDIO_MPEG); + sSupportedContentTypes.add(AUDIO_MPG); + sSupportedContentTypes.add(AUDIO_X_MID); + sSupportedContentTypes.add(AUDIO_X_MIDI); + sSupportedContentTypes.add(AUDIO_X_MP3); + sSupportedContentTypes.add(AUDIO_X_MPEG3); + sSupportedContentTypes.add(AUDIO_X_MPEG); + sSupportedContentTypes.add(AUDIO_X_MPG); + sSupportedContentTypes.add(AUDIO_X_WAV); + sSupportedContentTypes.add(AUDIO_3GPP); + sSupportedContentTypes.add(AUDIO_OGG); + sSupportedContentTypes.add(AUDIO_OGG2); + + sSupportedContentTypes.add(VIDEO_3GPP); + sSupportedContentTypes.add(VIDEO_3G2); + sSupportedContentTypes.add(VIDEO_H263); + sSupportedContentTypes.add(VIDEO_MP4); + + sSupportedContentTypes.add(APP_SMIL); + sSupportedContentTypes.add(APP_WAP_XHTML); + sSupportedContentTypes.add(APP_XHTML); + + sSupportedContentTypes.add(APP_DRM_CONTENT); + sSupportedContentTypes.add(APP_DRM_MESSAGE); + + // add supported image types + sSupportedImageTypes.add(IMAGE_JPEG); + sSupportedImageTypes.add(IMAGE_GIF); + sSupportedImageTypes.add(IMAGE_WBMP); + sSupportedImageTypes.add(IMAGE_PNG); + sSupportedImageTypes.add(IMAGE_JPG); + sSupportedImageTypes.add(IMAGE_X_MS_BMP); + + // add supported audio types + sSupportedAudioTypes.add(AUDIO_AAC); + sSupportedAudioTypes.add(AUDIO_AMR); + sSupportedAudioTypes.add(AUDIO_IMELODY); + sSupportedAudioTypes.add(AUDIO_MID); + sSupportedAudioTypes.add(AUDIO_MIDI); + sSupportedAudioTypes.add(AUDIO_MP3); + sSupportedAudioTypes.add(AUDIO_MPEG3); + sSupportedAudioTypes.add(AUDIO_MPEG); + sSupportedAudioTypes.add(AUDIO_MPG); + sSupportedAudioTypes.add(AUDIO_MP4); + sSupportedAudioTypes.add(AUDIO_X_MID); + sSupportedAudioTypes.add(AUDIO_X_MIDI); + sSupportedAudioTypes.add(AUDIO_X_MP3); + sSupportedAudioTypes.add(AUDIO_X_MPEG3); + sSupportedAudioTypes.add(AUDIO_X_MPEG); + sSupportedAudioTypes.add(AUDIO_X_MPG); + sSupportedAudioTypes.add(AUDIO_X_WAV); + sSupportedAudioTypes.add(AUDIO_3GPP); + sSupportedAudioTypes.add(AUDIO_OGG); + sSupportedAudioTypes.add(AUDIO_OGG2); + + // add supported video types + sSupportedVideoTypes.add(VIDEO_3GPP); + sSupportedVideoTypes.add(VIDEO_3G2); + sSupportedVideoTypes.add(VIDEO_H263); + sSupportedVideoTypes.add(VIDEO_MP4); + } + + // This class should never be instantiated. + private ContentType() { + } + + @UnsupportedAppUsage + public static boolean isSupportedType(String contentType) { + return (null != contentType) && sSupportedContentTypes.contains(contentType); + } + + @UnsupportedAppUsage + public static boolean isSupportedImageType(String contentType) { + return isImageType(contentType) && isSupportedType(contentType); + } + + @UnsupportedAppUsage + public static boolean isSupportedAudioType(String contentType) { + return isAudioType(contentType) && isSupportedType(contentType); + } + + @UnsupportedAppUsage + public static boolean isSupportedVideoType(String contentType) { + return isVideoType(contentType) && isSupportedType(contentType); + } + + @UnsupportedAppUsage + public static boolean isTextType(String contentType) { + return (null != contentType) && contentType.startsWith("text/"); + } + + @UnsupportedAppUsage + public static boolean isImageType(String contentType) { + return (null != contentType) && contentType.startsWith("image/"); + } + + @UnsupportedAppUsage + public static boolean isAudioType(String contentType) { + return (null != contentType) && contentType.startsWith("audio/"); + } + + @UnsupportedAppUsage + public static boolean isVideoType(String contentType) { + return (null != contentType) && contentType.startsWith("video/"); + } + + @UnsupportedAppUsage + public static boolean isDrmType(String contentType) { + return (null != contentType) + && (contentType.equals(APP_DRM_CONTENT) + || contentType.equals(APP_DRM_MESSAGE)); + } + + public static boolean isUnspecified(String contentType) { + return (null != contentType) && contentType.endsWith("*"); + } + + @UnsupportedAppUsage + @SuppressWarnings("unchecked") + public static ArrayList<String> getImageTypes() { + return (ArrayList<String>) sSupportedImageTypes.clone(); + } + + @UnsupportedAppUsage + @SuppressWarnings("unchecked") + public static ArrayList<String> getAudioTypes() { + return (ArrayList<String>) sSupportedAudioTypes.clone(); + } + + @UnsupportedAppUsage + @SuppressWarnings("unchecked") + public static ArrayList<String> getVideoTypes() { + return (ArrayList<String>) sSupportedVideoTypes.clone(); + } + + @SuppressWarnings("unchecked") + public static ArrayList<String> getSupportedTypes() { + return (ArrayList<String>) sSupportedContentTypes.clone(); + } +} diff --git a/telephony/common/com/google/android/mms/InvalidHeaderValueException.java b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java new file mode 100644 index 000000000000..2836c3075b3b --- /dev/null +++ b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +/** + * Thrown when an invalid header value was set. + */ +public class InvalidHeaderValueException extends MmsException { + private static final long serialVersionUID = -2053384496042052262L; + + /** + * Constructs an InvalidHeaderValueException with no detailed message. + */ + public InvalidHeaderValueException() { + super(); + } + + /** + * Constructs an InvalidHeaderValueException with the specified detailed message. + * + * @param message the detailed message. + */ + @UnsupportedAppUsage + public InvalidHeaderValueException(String message) { + super(message); + } +} diff --git a/telephony/common/com/google/android/mms/MmsException.java b/telephony/common/com/google/android/mms/MmsException.java new file mode 100644 index 000000000000..5be33ed1fac9 --- /dev/null +++ b/telephony/common/com/google/android/mms/MmsException.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +/** + * A generic exception that is thrown by the Mms client. + */ +public class MmsException extends Exception { + private static final long serialVersionUID = -7323249827281485390L; + + /** + * Creates a new MmsException. + */ + @UnsupportedAppUsage + public MmsException() { + super(); + } + + /** + * Creates a new MmsException with the specified detail message. + * + * @param message the detail message. + */ + @UnsupportedAppUsage + public MmsException(String message) { + super(message); + } + + /** + * Creates a new MmsException with the specified cause. + * + * @param cause the cause. + */ + @UnsupportedAppUsage + public MmsException(Throwable cause) { + super(cause); + } + + /** + * Creates a new MmsException with the specified detail message and cause. + * + * @param message the detail message. + * @param cause the cause. + */ + @UnsupportedAppUsage + public MmsException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/telephony/common/com/google/android/mms/package.html b/telephony/common/com/google/android/mms/package.html new file mode 100755 index 000000000000..c9f96a66ab3b --- /dev/null +++ b/telephony/common/com/google/android/mms/package.html @@ -0,0 +1,5 @@ +<body> + +{@hide} + +</body> diff --git a/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java new file mode 100644 index 000000000000..ae447d7a7417 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * M-Acknowledge.ind PDU. + */ +public class AcknowledgeInd extends GenericPdu { + /** + * Constructor, used when composing a M-Acknowledge.ind pdu. + * + * @param mmsVersion current viersion of mms + * @param transactionId the transaction-id value + * @throws InvalidHeaderValueException if parameters are invalid. + * NullPointerException if transactionId is null. + */ + @UnsupportedAppUsage + public AcknowledgeInd(int mmsVersion, byte[] transactionId) + throws InvalidHeaderValueException { + super(); + + setMessageType(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND); + setMmsVersion(mmsVersion); + setTransactionId(transactionId); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + AcknowledgeInd(PduHeaders headers) { + super(headers); + } + + /** + * Get X-Mms-Report-Allowed field value. + * + * @return the X-Mms-Report-Allowed value + */ + public int getReportAllowed() { + return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED); + } + + /** + * Set X-Mms-Report-Allowed field value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setReportAllowed(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED); + } + + /** + * Get X-Mms-Transaction-Id field value. + * + * @return the X-Mms-Report-Allowed value + */ + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id field value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/Base64.java b/telephony/common/com/google/android/mms/pdu/Base64.java new file mode 100644 index 000000000000..483fa7f9842e --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/Base64.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +public class Base64 { + /** + * Used to get the number of Quadruples. + */ + static final int FOURBYTE = 4; + + /** + * Byte used to pad output. + */ + static final byte PAD = (byte) '='; + + /** + * The base length. + */ + static final int BASELENGTH = 255; + + // Create arrays to hold the base64 characters + private static byte[] base64Alphabet = new byte[BASELENGTH]; + + // Populating the character arrays + static { + for (int i = 0; i < BASELENGTH; i++) { + base64Alphabet[i] = (byte) -1; + } + for (int i = 'Z'; i >= 'A'; i--) { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + for (int i = '9'; i >= '0'; i--) { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + } + + /** + * Decodes Base64 data into octects + * + * @param base64Data Byte array containing Base64 data + * @return Array containing decoded data. + */ + @UnsupportedAppUsage + public static byte[] decodeBase64(byte[] base64Data) { + // RFC 2045 requires that we discard ALL non-Base64 characters + base64Data = discardNonBase64(base64Data); + + // handle the edge case, so we don't have to worry about it later + if (base64Data.length == 0) { + return new byte[0]; + } + + int numberQuadruple = base64Data.length / FOURBYTE; + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; + + // Throw away anything not in base64Data + + int encodedIndex = 0; + int dataIndex = 0; + { + // this sizes the output array properly - rlw + int lastData = base64Data.length; + // ignore the '=' padding + while (base64Data[lastData - 1] == PAD) { + if (--lastData == 0) { + return new byte[0]; + } + } + decodedData = new byte[lastData - numberQuadruple]; + } + + for (int i = 0; i < numberQuadruple; i++) { + dataIndex = i * 4; + marker0 = base64Data[dataIndex + 2]; + marker1 = base64Data[dataIndex + 3]; + + b1 = base64Alphabet[base64Data[dataIndex]]; + b2 = base64Alphabet[base64Data[dataIndex + 1]]; + + if (marker0 != PAD && marker1 != PAD) { + //No PAD e.g 3cQl + b3 = base64Alphabet[marker0]; + b4 = base64Alphabet[marker1]; + + decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex + 1] = + (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); + } else if (marker0 == PAD) { + //Two PAD e.g. 3c[Pad][Pad] + decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + } else if (marker1 == PAD) { + //One PAD e.g. 3cQ[Pad] + b3 = base64Alphabet[marker0]; + + decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex + 1] = + (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + } + encodedIndex += 3; + } + return decodedData; + } + + /** + * Check octect whether it is a base64 encoding. + * + * @param octect to be checked byte + * @return ture if it is base64 encoding, false otherwise. + */ + private static boolean isBase64(byte octect) { + if (octect == PAD) { + return true; + } else if (base64Alphabet[octect] == -1) { + return false; + } else { + return true; + } + } + + /** + * Discards any characters outside of the base64 alphabet, per + * the requirements on page 25 of RFC 2045 - "Any characters + * outside of the base64 alphabet are to be ignored in base64 + * encoded data." + * + * @param data The base-64 encoded data to groom + * @return The data, less non-base64 characters (see RFC 2045). + */ + static byte[] discardNonBase64(byte[] data) { + byte groomedData[] = new byte[data.length]; + int bytesCopied = 0; + + for (int i = 0; i < data.length; i++) { + if (isBase64(data[i])) { + groomedData[bytesCopied++] = data[i]; + } + } + + byte packedData[] = new byte[bytesCopied]; + + System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); + + return packedData; + } +} diff --git a/telephony/common/com/google/android/mms/pdu/CharacterSets.java b/telephony/common/com/google/android/mms/pdu/CharacterSets.java new file mode 100644 index 000000000000..27da35e2d928 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/CharacterSets.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; + +public class CharacterSets { + /** + * IANA assigned MIB enum numbers. + * + * From wap-230-wsp-20010705-a.pdf + * Any-charset = <Octet 128> + * Equivalent to the special RFC2616 charset value "*" + */ + public static final int ANY_CHARSET = 0x00; + public static final int US_ASCII = 0x03; + public static final int ISO_8859_1 = 0x04; + public static final int ISO_8859_2 = 0x05; + public static final int ISO_8859_3 = 0x06; + public static final int ISO_8859_4 = 0x07; + public static final int ISO_8859_5 = 0x08; + public static final int ISO_8859_6 = 0x09; + public static final int ISO_8859_7 = 0x0A; + public static final int ISO_8859_8 = 0x0B; + public static final int ISO_8859_9 = 0x0C; + public static final int SHIFT_JIS = 0x11; + public static final int UTF_8 = 0x6A; + public static final int BIG5 = 0x07EA; + public static final int UCS2 = 0x03E8; + public static final int UTF_16 = 0x03F7; + + /** + * If the encoding of given data is unsupported, use UTF_8 to decode it. + */ + public static final int DEFAULT_CHARSET = UTF_8; + + /** + * Array of MIB enum numbers. + */ + private static final int[] MIBENUM_NUMBERS = { + ANY_CHARSET, + US_ASCII, + ISO_8859_1, + ISO_8859_2, + ISO_8859_3, + ISO_8859_4, + ISO_8859_5, + ISO_8859_6, + ISO_8859_7, + ISO_8859_8, + ISO_8859_9, + SHIFT_JIS, + UTF_8, + BIG5, + UCS2, + UTF_16, + }; + + /** + * The Well-known-charset Mime name. + */ + public static final String MIMENAME_ANY_CHARSET = "*"; + public static final String MIMENAME_US_ASCII = "us-ascii"; + public static final String MIMENAME_ISO_8859_1 = "iso-8859-1"; + public static final String MIMENAME_ISO_8859_2 = "iso-8859-2"; + public static final String MIMENAME_ISO_8859_3 = "iso-8859-3"; + public static final String MIMENAME_ISO_8859_4 = "iso-8859-4"; + public static final String MIMENAME_ISO_8859_5 = "iso-8859-5"; + public static final String MIMENAME_ISO_8859_6 = "iso-8859-6"; + public static final String MIMENAME_ISO_8859_7 = "iso-8859-7"; + public static final String MIMENAME_ISO_8859_8 = "iso-8859-8"; + public static final String MIMENAME_ISO_8859_9 = "iso-8859-9"; + public static final String MIMENAME_SHIFT_JIS = "shift_JIS"; + public static final String MIMENAME_UTF_8 = "utf-8"; + public static final String MIMENAME_BIG5 = "big5"; + public static final String MIMENAME_UCS2 = "iso-10646-ucs-2"; + public static final String MIMENAME_UTF_16 = "utf-16"; + + public static final String DEFAULT_CHARSET_NAME = MIMENAME_UTF_8; + + /** + * Array of the names of character sets. + */ + private static final String[] MIME_NAMES = { + MIMENAME_ANY_CHARSET, + MIMENAME_US_ASCII, + MIMENAME_ISO_8859_1, + MIMENAME_ISO_8859_2, + MIMENAME_ISO_8859_3, + MIMENAME_ISO_8859_4, + MIMENAME_ISO_8859_5, + MIMENAME_ISO_8859_6, + MIMENAME_ISO_8859_7, + MIMENAME_ISO_8859_8, + MIMENAME_ISO_8859_9, + MIMENAME_SHIFT_JIS, + MIMENAME_UTF_8, + MIMENAME_BIG5, + MIMENAME_UCS2, + MIMENAME_UTF_16, + }; + + private static final HashMap<Integer, String> MIBENUM_TO_NAME_MAP; + private static final HashMap<String, Integer> NAME_TO_MIBENUM_MAP; + + static { + // Create the HashMaps. + MIBENUM_TO_NAME_MAP = new HashMap<Integer, String>(); + NAME_TO_MIBENUM_MAP = new HashMap<String, Integer>(); + assert(MIBENUM_NUMBERS.length == MIME_NAMES.length); + int count = MIBENUM_NUMBERS.length - 1; + for(int i = 0; i <= count; i++) { + MIBENUM_TO_NAME_MAP.put(MIBENUM_NUMBERS[i], MIME_NAMES[i]); + NAME_TO_MIBENUM_MAP.put(MIME_NAMES[i], MIBENUM_NUMBERS[i]); + } + } + + private CharacterSets() {} // Non-instantiatable + + /** + * Map an MIBEnum number to the name of the charset which this number + * is assigned to by IANA. + * + * @param mibEnumValue An IANA assigned MIBEnum number. + * @return The name string of the charset. + * @throws UnsupportedEncodingException + */ + @UnsupportedAppUsage + public static String getMimeName(int mibEnumValue) + throws UnsupportedEncodingException { + String name = MIBENUM_TO_NAME_MAP.get(mibEnumValue); + if (name == null) { + throw new UnsupportedEncodingException(); + } + return name; + } + + /** + * Map a well-known charset name to its assigned MIBEnum number. + * + * @param mimeName The charset name. + * @return The MIBEnum number assigned by IANA for this charset. + * @throws UnsupportedEncodingException + */ + @UnsupportedAppUsage + public static int getMibEnumValue(String mimeName) + throws UnsupportedEncodingException { + if(null == mimeName) { + return -1; + } + + Integer mibEnumValue = NAME_TO_MIBENUM_MAP.get(mimeName); + if (mibEnumValue == null) { + throw new UnsupportedEncodingException(); + } + return mibEnumValue; + } +} diff --git a/telephony/common/com/google/android/mms/pdu/DeliveryInd.java b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java new file mode 100644 index 000000000000..7093ac63338c --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * M-Delivery.Ind Pdu. + */ +public class DeliveryInd extends GenericPdu { + /** + * Empty constructor. + * Since the Pdu corresponding to this class is constructed + * by the Proxy-Relay server, this class is only instantiated + * by the Pdu Parser. + * + * @throws InvalidHeaderValueException if error occurs. + */ + public DeliveryInd() throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_DELIVERY_IND); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + DeliveryInd(PduHeaders headers) { + super(headers); + } + + /** + * Get Date value. + * + * @return the value + */ + @UnsupportedAppUsage + public long getDate() { + return mPduHeaders.getLongInteger(PduHeaders.DATE); + } + + /** + * Set Date value. + * + * @param value the value + */ + public void setDate(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.DATE); + } + + /** + * Get Message-ID value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageId() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID); + } + + /** + * Set Message-ID value. + * + * @param value the value, should not be null + * @throws NullPointerException if the value is null. + */ + public void setMessageId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID); + } + + /** + * Get Status value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getStatus() { + return mPduHeaders.getOctet(PduHeaders.STATUS); + } + + /** + * Set Status value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + public void setStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.STATUS); + } + + /** + * Get To value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue[] getTo() { + return mPduHeaders.getEncodedStringValues(PduHeaders.TO); + } + + /** + * set To value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setTo(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.TO); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + * + * public EncodedStringValue getStatusText() {return null;} + * public void setStatusText(EncodedStringValue value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java new file mode 100644 index 000000000000..41662750842f --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; + +/** + * Encoded-string-value = Text-string | Value-length Char-set Text-string + */ +public class EncodedStringValue implements Cloneable { + private static final String TAG = "EncodedStringValue"; + private static final boolean DEBUG = false; + private static final boolean LOCAL_LOGV = false; + + /** + * The Char-set value. + */ + private int mCharacterSet; + + /** + * The Text-string value. + */ + private byte[] mData; + + /** + * Constructor. + * + * @param charset the Char-set value + * @param data the Text-string value + * @throws NullPointerException if Text-string value is null. + */ + @UnsupportedAppUsage + public EncodedStringValue(int charset, byte[] data) { + // TODO: CharSet needs to be validated against MIBEnum. + if(null == data) { + throw new NullPointerException("EncodedStringValue: Text-string is null."); + } + + mCharacterSet = charset; + mData = new byte[data.length]; + System.arraycopy(data, 0, mData, 0, data.length); + } + + /** + * Constructor. + * + * @param data the Text-string value + * @throws NullPointerException if Text-string value is null. + */ + @UnsupportedAppUsage + public EncodedStringValue(byte[] data) { + this(CharacterSets.DEFAULT_CHARSET, data); + } + + @UnsupportedAppUsage + public EncodedStringValue(String data) { + try { + mData = data.getBytes(CharacterSets.DEFAULT_CHARSET_NAME); + mCharacterSet = CharacterSets.DEFAULT_CHARSET; + } catch (UnsupportedEncodingException e) { + Log.e(TAG, "Default encoding must be supported.", e); + } + } + + /** + * Get Char-set value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getCharacterSet() { + return mCharacterSet; + } + + /** + * Set Char-set value. + * + * @param charset the Char-set value + */ + @UnsupportedAppUsage + public void setCharacterSet(int charset) { + // TODO: CharSet needs to be validated against MIBEnum. + mCharacterSet = charset; + } + + /** + * Get Text-string value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getTextString() { + byte[] byteArray = new byte[mData.length]; + + System.arraycopy(mData, 0, byteArray, 0, mData.length); + return byteArray; + } + + /** + * Set Text-string value. + * + * @param textString the Text-string value + * @throws NullPointerException if Text-string value is null. + */ + @UnsupportedAppUsage + public void setTextString(byte[] textString) { + if(null == textString) { + throw new NullPointerException("EncodedStringValue: Text-string is null."); + } + + mData = new byte[textString.length]; + System.arraycopy(textString, 0, mData, 0, textString.length); + } + + /** + * Convert this object to a {@link java.lang.String}. If the encoding of + * the EncodedStringValue is null or unsupported, it will be + * treated as iso-8859-1 encoding. + * + * @return The decoded String. + */ + @UnsupportedAppUsage + public String getString() { + if (CharacterSets.ANY_CHARSET == mCharacterSet) { + return new String(mData); // system default encoding. + } else { + try { + String name = CharacterSets.getMimeName(mCharacterSet); + return new String(mData, name); + } catch (UnsupportedEncodingException e) { + if (LOCAL_LOGV) { + Log.v(TAG, e.getMessage(), e); + } + try { + return new String(mData, CharacterSets.MIMENAME_ISO_8859_1); + } catch (UnsupportedEncodingException e2) { + return new String(mData); // system default encoding. + } + } + } + } + + /** + * Append to Text-string. + * + * @param textString the textString to append + * @throws NullPointerException if the text String is null + * or an IOException occurred. + */ + @UnsupportedAppUsage + public void appendTextString(byte[] textString) { + if(null == textString) { + throw new NullPointerException("Text-string is null."); + } + + if(null == mData) { + mData = new byte[textString.length]; + System.arraycopy(textString, 0, mData, 0, textString.length); + } else { + ByteArrayOutputStream newTextString = new ByteArrayOutputStream(); + try { + newTextString.write(mData); + newTextString.write(textString); + } catch (IOException e) { + e.printStackTrace(); + throw new NullPointerException( + "appendTextString: failed when write a new Text-string"); + } + + mData = newTextString.toByteArray(); + } + } + + /* + * (non-Javadoc) + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + super.clone(); + int len = mData.length; + byte[] dstBytes = new byte[len]; + System.arraycopy(mData, 0, dstBytes, 0, len); + + try { + return new EncodedStringValue(mCharacterSet, dstBytes); + } catch (Exception e) { + Log.e(TAG, "failed to clone an EncodedStringValue: " + this); + e.printStackTrace(); + throw new CloneNotSupportedException(e.getMessage()); + } + } + + /** + * Split this encoded string around matches of the given pattern. + * + * @param pattern the delimiting pattern + * @return the array of encoded strings computed by splitting this encoded + * string around matches of the given pattern + */ + public EncodedStringValue[] split(String pattern) { + String[] temp = getString().split(pattern); + EncodedStringValue[] ret = new EncodedStringValue[temp.length]; + for (int i = 0; i < ret.length; ++i) { + try { + ret[i] = new EncodedStringValue(mCharacterSet, + temp[i].getBytes()); + } catch (NullPointerException e) { + // Can't arrive here + return null; + } + } + return ret; + } + + /** + * Extract an EncodedStringValue[] from a given String. + */ + @UnsupportedAppUsage + public static EncodedStringValue[] extract(String src) { + String[] values = src.split(";"); + + ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>(); + for (int i = 0; i < values.length; i++) { + if (values[i].length() > 0) { + list.add(new EncodedStringValue(values[i])); + } + } + + int len = list.size(); + if (len > 0) { + return list.toArray(new EncodedStringValue[len]); + } else { + return null; + } + } + + /** + * Concatenate an EncodedStringValue[] into a single String. + */ + @UnsupportedAppUsage + public static String concat(EncodedStringValue[] addr) { + StringBuilder sb = new StringBuilder(); + int maxIndex = addr.length - 1; + for (int i = 0; i <= maxIndex; i++) { + sb.append(addr[i].getString()); + if (i < maxIndex) { + sb.append(";"); + } + } + + return sb.toString(); + } + + @UnsupportedAppUsage + public static EncodedStringValue copy(EncodedStringValue value) { + if (value == null) { + return null; + } + + return new EncodedStringValue(value.mCharacterSet, value.mData); + } + + @UnsupportedAppUsage + public static EncodedStringValue[] encodeStrings(String[] array) { + int count = array.length; + if (count > 0) { + EncodedStringValue[] encodedArray = new EncodedStringValue[count]; + for (int i = 0; i < count; i++) { + encodedArray[i] = new EncodedStringValue(array[i]); + } + return encodedArray; + } + return null; + } +} diff --git a/telephony/common/com/google/android/mms/pdu/GenericPdu.java b/telephony/common/com/google/android/mms/pdu/GenericPdu.java new file mode 100644 index 000000000000..ebf16ac7e632 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/GenericPdu.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +public class GenericPdu { + /** + * The headers of pdu. + */ + @UnsupportedAppUsage + PduHeaders mPduHeaders = null; + + /** + * Constructor. + */ + @UnsupportedAppUsage + public GenericPdu() { + mPduHeaders = new PduHeaders(); + } + + /** + * Constructor. + * + * @param headers Headers for this PDU. + */ + GenericPdu(PduHeaders headers) { + mPduHeaders = headers; + } + + /** + * Get the headers of this PDU. + * + * @return A PduHeaders of this PDU. + */ + @UnsupportedAppUsage + PduHeaders getPduHeaders() { + return mPduHeaders; + } + + /** + * Get X-Mms-Message-Type field value. + * + * @return the X-Mms-Report-Allowed value + */ + @UnsupportedAppUsage + public int getMessageType() { + return mPduHeaders.getOctet(PduHeaders.MESSAGE_TYPE); + } + + /** + * Set X-Mms-Message-Type field value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if field's value is not Octet. + */ + @UnsupportedAppUsage + public void setMessageType(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.MESSAGE_TYPE); + } + + /** + * Get X-Mms-MMS-Version field value. + * + * @return the X-Mms-MMS-Version value + */ + public int getMmsVersion() { + return mPduHeaders.getOctet(PduHeaders.MMS_VERSION); + } + + /** + * Set X-Mms-MMS-Version field value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if field's value is not Octet. + */ + public void setMmsVersion(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.MMS_VERSION); + } + + /** + * Get From value. + * From-value = Value-length + * (Address-present-token Encoded-string-value | Insert-address-token) + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getFrom() { + return mPduHeaders.getEncodedStringValue(PduHeaders.FROM); + } + + /** + * Set From value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setFrom(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java new file mode 100644 index 000000000000..e108f7600baf --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * Multimedia message PDU. + */ +public class MultimediaMessagePdu extends GenericPdu{ + /** + * The body. + */ + private PduBody mMessageBody; + + /** + * Constructor. + */ + @UnsupportedAppUsage + public MultimediaMessagePdu() { + super(); + } + + /** + * Constructor. + * + * @param header the header of this PDU + * @param body the body of this PDU + */ + @UnsupportedAppUsage + public MultimediaMessagePdu(PduHeaders header, PduBody body) { + super(header); + mMessageBody = body; + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + MultimediaMessagePdu(PduHeaders headers) { + super(headers); + } + + /** + * Get body of the PDU. + * + * @return the body + */ + @UnsupportedAppUsage + public PduBody getBody() { + return mMessageBody; + } + + /** + * Set body of the PDU. + * + * @param body the body + */ + @UnsupportedAppUsage + public void setBody(PduBody body) { + mMessageBody = body; + } + + /** + * Get subject. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getSubject() { + return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT); + } + + /** + * Set subject. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setSubject(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT); + } + + /** + * Get To value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue[] getTo() { + return mPduHeaders.getEncodedStringValues(PduHeaders.TO); + } + + /** + * Add a "To" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void addTo(EncodedStringValue value) { + mPduHeaders.appendEncodedStringValue(value, PduHeaders.TO); + } + + /** + * Get X-Mms-Priority value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getPriority() { + return mPduHeaders.getOctet(PduHeaders.PRIORITY); + } + + /** + * Set X-Mms-Priority value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setPriority(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.PRIORITY); + } + + /** + * Get Date value. + * + * @return the value + */ + @UnsupportedAppUsage + public long getDate() { + return mPduHeaders.getLongInteger(PduHeaders.DATE); + } + + /** + * Set Date value in seconds. + * + * @param value the value + */ + @UnsupportedAppUsage + public void setDate(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.DATE); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/NotificationInd.java b/telephony/common/com/google/android/mms/pdu/NotificationInd.java new file mode 100644 index 000000000000..b561bd4ab3a7 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/NotificationInd.java @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * M-Notification.ind PDU. + */ +public class NotificationInd extends GenericPdu { + /** + * Empty constructor. + * Since the Pdu corresponding to this class is constructed + * by the Proxy-Relay server, this class is only instantiated + * by the Pdu Parser. + * + * @throws InvalidHeaderValueException if error occurs. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public NotificationInd() throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + NotificationInd(PduHeaders headers) { + super(headers); + } + + /** + * Get X-Mms-Content-Class Value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getContentClass() { + return mPduHeaders.getOctet(PduHeaders.CONTENT_CLASS); + } + + /** + * Set X-Mms-Content-Class Value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setContentClass(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.CONTENT_CLASS); + } + + /** + * Get X-Mms-Content-Location value. + * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf: + * Content-location-value = Uri-value + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentLocation() { + return mPduHeaders.getTextString(PduHeaders.CONTENT_LOCATION); + } + + /** + * Set X-Mms-Content-Location value. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setContentLocation(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.CONTENT_LOCATION); + } + + /** + * Get X-Mms-Expiry value. + * + * Expiry-value = Value-length + * (Absolute-token Date-value | Relative-token Delta-seconds-value) + * + * @return the value + */ + @UnsupportedAppUsage + public long getExpiry() { + return mPduHeaders.getLongInteger(PduHeaders.EXPIRY); + } + + /** + * Set X-Mms-Expiry value. + * + * @param value the value + * @throws RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setExpiry(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY); + } + + /** + * Get From value. + * From-value = Value-length + * (Address-present-token Encoded-string-value | Insert-address-token) + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getFrom() { + return mPduHeaders.getEncodedStringValue(PduHeaders.FROM); + } + + /** + * Set From value. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setFrom(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM); + } + + /** + * Get X-Mms-Message-Class value. + * Message-class-value = Class-identifier | Token-text + * Class-identifier = Personal | Advertisement | Informational | Auto + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageClass() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS); + } + + /** + * Set X-Mms-Message-Class value. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setMessageClass(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS); + } + + /** + * Get X-Mms-Message-Size value. + * Message-size-value = Long-integer + * + * @return the value + */ + @UnsupportedAppUsage + public long getMessageSize() { + return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE); + } + + /** + * Set X-Mms-Message-Size value. + * + * @param value the value + * @throws RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setMessageSize(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE); + } + + /** + * Get subject. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getSubject() { + return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT); + } + + /** + * Set subject. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setSubject(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT); + } + + /** + * Get X-Mms-Transaction-Id. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } + + /** + * Get X-Mms-Delivery-Report Value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getDeliveryReport() { + return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT); + } + + /** + * Set X-Mms-Delivery-Report Value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setDeliveryReport(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte getDrmContent() {return 0x00;} + * public void setDrmContent(byte value) {} + * + * public byte getDistributionIndicator() {return 0x00;} + * public void setDistributionIndicator(byte value) {} + * + * public ElementDescriptorValue getElementDescriptor() {return null;} + * public void getElementDescriptor(ElementDescriptorValue value) {} + * + * public byte getPriority() {return 0x00;} + * public void setPriority(byte value) {} + * + * public byte getRecommendedRetrievalMode() {return 0x00;} + * public void setRecommendedRetrievalMode(byte value) {} + * + * public byte getRecommendedRetrievalModeText() {return 0x00;} + * public void setRecommendedRetrievalModeText(byte value) {} + * + * public byte[] getReplaceId() {return 0x00;} + * public void setReplaceId(byte[] value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + * + * public byte getReplyCharging() {return 0x00;} + * public void setReplyCharging(byte value) {} + * + * public byte getReplyChargingDeadline() {return 0x00;} + * public void setReplyChargingDeadline(byte value) {} + * + * public byte[] getReplyChargingId() {return 0x00;} + * public void setReplyChargingId(byte[] value) {} + * + * public long getReplyChargingSize() {return 0;} + * public void setReplyChargingSize(long value) {} + * + * public byte getStored() {return 0x00;} + * public void setStored(byte value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java new file mode 100644 index 000000000000..3c70f86a0890 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * M-NofifyResp.ind PDU. + */ +public class NotifyRespInd extends GenericPdu { + /** + * Constructor, used when composing a M-NotifyResp.ind pdu. + * + * @param mmsVersion current version of mms + * @param transactionId the transaction-id value + * @param status the status value + * @throws InvalidHeaderValueException if parameters are invalid. + * NullPointerException if transactionId is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public NotifyRespInd(int mmsVersion, + byte[] transactionId, + int status) throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND); + setMmsVersion(mmsVersion); + setTransactionId(transactionId); + setStatus(status); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + NotifyRespInd(PduHeaders headers) { + super(headers); + } + + /** + * Get X-Mms-Report-Allowed field value. + * + * @return the X-Mms-Report-Allowed value + */ + public int getReportAllowed() { + return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED); + } + + /** + * Set X-Mms-Report-Allowed field value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setReportAllowed(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED); + } + + /** + * Set X-Mms-Status field value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.STATUS); + } + + /** + * GetX-Mms-Status field value. + * + * @return the X-Mms-Status value + */ + public int getStatus() { + return mPduHeaders.getOctet(PduHeaders.STATUS); + } + + /** + * Get X-Mms-Transaction-Id field value. + * + * @return the X-Mms-Report-Allowed value + */ + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id field value. + * + * @param value the value + * @throws NullPointerException if the value is null. + * RuntimeException if an undeclared error occurs. + */ + @UnsupportedAppUsage + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduBody.java b/telephony/common/com/google/android/mms/pdu/PduBody.java new file mode 100644 index 000000000000..51914e4110b0 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduBody.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +public class PduBody { + private Vector<PduPart> mParts = null; + + private Map<String, PduPart> mPartMapByContentId = null; + private Map<String, PduPart> mPartMapByContentLocation = null; + private Map<String, PduPart> mPartMapByName = null; + private Map<String, PduPart> mPartMapByFileName = null; + + /** + * Constructor. + */ + @UnsupportedAppUsage + public PduBody() { + mParts = new Vector<PduPart>(); + + mPartMapByContentId = new HashMap<String, PduPart>(); + mPartMapByContentLocation = new HashMap<String, PduPart>(); + mPartMapByName = new HashMap<String, PduPart>(); + mPartMapByFileName = new HashMap<String, PduPart>(); + } + + private void putPartToMaps(PduPart part) { + // Put part to mPartMapByContentId. + byte[] contentId = part.getContentId(); + if(null != contentId) { + mPartMapByContentId.put(new String(contentId), part); + } + + // Put part to mPartMapByContentLocation. + byte[] contentLocation = part.getContentLocation(); + if(null != contentLocation) { + String clc = new String(contentLocation); + mPartMapByContentLocation.put(clc, part); + } + + // Put part to mPartMapByName. + byte[] name = part.getName(); + if(null != name) { + String clc = new String(name); + mPartMapByName.put(clc, part); + } + + // Put part to mPartMapByFileName. + byte[] fileName = part.getFilename(); + if(null != fileName) { + String clc = new String(fileName); + mPartMapByFileName.put(clc, part); + } + } + + /** + * Appends the specified part to the end of this body. + * + * @param part part to be appended + * @return true when success, false when fail + * @throws NullPointerException when part is null + */ + @UnsupportedAppUsage + public boolean addPart(PduPart part) { + if(null == part) { + throw new NullPointerException(); + } + + putPartToMaps(part); + return mParts.add(part); + } + + /** + * Inserts the specified part at the specified position. + * + * @param index index at which the specified part is to be inserted + * @param part part to be inserted + * @throws NullPointerException when part is null + */ + @UnsupportedAppUsage + public void addPart(int index, PduPart part) { + if(null == part) { + throw new NullPointerException(); + } + + putPartToMaps(part); + mParts.add(index, part); + } + + /** + * Removes the part at the specified position. + * + * @param index index of the part to return + * @return part at the specified index + */ + @UnsupportedAppUsage + public PduPart removePart(int index) { + return mParts.remove(index); + } + + /** + * Remove all of the parts. + */ + public void removeAll() { + mParts.clear(); + } + + /** + * Get the part at the specified position. + * + * @param index index of the part to return + * @return part at the specified index + */ + @UnsupportedAppUsage + public PduPart getPart(int index) { + return mParts.get(index); + } + + /** + * Get the index of the specified part. + * + * @param part the part object + * @return index the index of the first occurrence of the part in this body + */ + @UnsupportedAppUsage + public int getPartIndex(PduPart part) { + return mParts.indexOf(part); + } + + /** + * Get the number of parts. + * + * @return the number of parts + */ + @UnsupportedAppUsage + public int getPartsNum() { + return mParts.size(); + } + + /** + * Get pdu part by content id. + * + * @param cid the value of content id. + * @return the pdu part. + */ + @UnsupportedAppUsage + public PduPart getPartByContentId(String cid) { + return mPartMapByContentId.get(cid); + } + + /** + * Get pdu part by Content-Location. Content-Location of part is + * the same as filename and name(param of content-type). + * + * @param fileName the value of filename. + * @return the pdu part. + */ + @UnsupportedAppUsage + public PduPart getPartByContentLocation(String contentLocation) { + return mPartMapByContentLocation.get(contentLocation); + } + + /** + * Get pdu part by name. + * + * @param fileName the value of filename. + * @return the pdu part. + */ + @UnsupportedAppUsage + public PduPart getPartByName(String name) { + return mPartMapByName.get(name); + } + + /** + * Get pdu part by filename. + * + * @param fileName the value of filename. + * @return the pdu part. + */ + @UnsupportedAppUsage + public PduPart getPartByFileName(String filename) { + return mPartMapByFileName.get(filename); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduComposer.java b/telephony/common/com/google/android/mms/pdu/PduComposer.java new file mode 100644 index 000000000000..e24bf21a11b5 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduComposer.java @@ -0,0 +1,1229 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.content.ContentResolver; +import android.content.Context; +import android.text.TextUtils; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; + +public class PduComposer { + /** + * Address type. + */ + static private final int PDU_PHONE_NUMBER_ADDRESS_TYPE = 1; + static private final int PDU_EMAIL_ADDRESS_TYPE = 2; + static private final int PDU_IPV4_ADDRESS_TYPE = 3; + static private final int PDU_IPV6_ADDRESS_TYPE = 4; + static private final int PDU_UNKNOWN_ADDRESS_TYPE = 5; + + /** + * Address regular expression string. + */ + static final String REGEXP_PHONE_NUMBER_ADDRESS_TYPE = "\\+?[0-9|\\.|\\-]+"; + static final String REGEXP_EMAIL_ADDRESS_TYPE = "[a-zA-Z| ]*\\<{0,1}[a-zA-Z| ]+@{1}" + + "[a-zA-Z| ]+\\.{1}[a-zA-Z| ]+\\>{0,1}"; + static final String REGEXP_IPV6_ADDRESS_TYPE = + "[a-fA-F]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" + + "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" + + "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}"; + static final String REGEXP_IPV4_ADDRESS_TYPE = "[0-9]{1,3}\\.{1}[0-9]{1,3}\\.{1}" + + "[0-9]{1,3}\\.{1}[0-9]{1,3}"; + + /** + * The postfix strings of address. + */ + static final String STRING_PHONE_NUMBER_ADDRESS_TYPE = "/TYPE=PLMN"; + static final String STRING_IPV4_ADDRESS_TYPE = "/TYPE=IPV4"; + static final String STRING_IPV6_ADDRESS_TYPE = "/TYPE=IPV6"; + + /** + * Error values. + */ + static private final int PDU_COMPOSE_SUCCESS = 0; + static private final int PDU_COMPOSE_CONTENT_ERROR = 1; + static private final int PDU_COMPOSE_FIELD_NOT_SET = 2; + static private final int PDU_COMPOSE_FIELD_NOT_SUPPORTED = 3; + + /** + * WAP values defined in WSP spec. + */ + static private final int QUOTED_STRING_FLAG = 34; + static private final int END_STRING_FLAG = 0; + static private final int LENGTH_QUOTE = 31; + static private final int TEXT_MAX = 127; + static private final int SHORT_INTEGER_MAX = 127; + static private final int LONG_INTEGER_LENGTH_MAX = 8; + + /** + * Block size when read data from InputStream. + */ + static private final int PDU_COMPOSER_BLOCK_SIZE = 1024; + + /** + * The output message. + */ + @UnsupportedAppUsage + protected ByteArrayOutputStream mMessage = null; + + /** + * The PDU. + */ + @UnsupportedAppUsage + private GenericPdu mPdu = null; + + /** + * Current visiting position of the mMessage. + */ + @UnsupportedAppUsage + protected int mPosition = 0; + + /** + * Message compose buffer stack. + */ + @UnsupportedAppUsage + private BufferStack mStack = null; + + /** + * Content resolver. + */ + @UnsupportedAppUsage + private final ContentResolver mResolver; + + /** + * Header of this pdu. + */ + @UnsupportedAppUsage + private PduHeaders mPduHeader = null; + + /** + * Map of all content type + */ + @UnsupportedAppUsage + private static HashMap<String, Integer> mContentTypeMap = null; + + static { + mContentTypeMap = new HashMap<String, Integer>(); + + int i; + for (i = 0; i < PduContentTypes.contentTypes.length; i++) { + mContentTypeMap.put(PduContentTypes.contentTypes[i], i); + } + } + + /** + * Constructor. + * + * @param context the context + * @param pdu the pdu to be composed + */ + @UnsupportedAppUsage + public PduComposer(Context context, GenericPdu pdu) { + mPdu = pdu; + mResolver = context.getContentResolver(); + mPduHeader = pdu.getPduHeaders(); + mStack = new BufferStack(); + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + /** + * Make the message. No need to check whether mandatory fields are set, + * because the constructors of outgoing pdus are taking care of this. + * + * @return OutputStream of maked message. Return null if + * the PDU is invalid. + */ + @UnsupportedAppUsage + public byte[] make() { + // Get Message-type. + int type = mPdu.getMessageType(); + + /* make the message */ + switch (type) { + case PduHeaders.MESSAGE_TYPE_SEND_REQ: + case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: + if (makeSendRetrievePdu(type) != PDU_COMPOSE_SUCCESS) { + return null; + } + break; + case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND: + if (makeNotifyResp() != PDU_COMPOSE_SUCCESS) { + return null; + } + break; + case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND: + if (makeAckInd() != PDU_COMPOSE_SUCCESS) { + return null; + } + break; + case PduHeaders.MESSAGE_TYPE_READ_REC_IND: + if (makeReadRecInd() != PDU_COMPOSE_SUCCESS) { + return null; + } + break; + default: + return null; + } + + return mMessage.toByteArray(); + } + + /** + * Copy buf to mMessage. + */ + @UnsupportedAppUsage + protected void arraycopy(byte[] buf, int pos, int length) { + mMessage.write(buf, pos, length); + mPosition = mPosition + length; + } + + /** + * Append a byte to mMessage. + */ + protected void append(int value) { + mMessage.write(value); + mPosition ++; + } + + /** + * Append short integer value to mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendShortInteger(int value) { + /* + * From WAP-230-WSP-20010705-a: + * Short-integer = OCTET + * ; Integers in range 0-127 shall be encoded as a one octet value + * ; with the most significant bit set to one (1xxx xxxx) and with + * ; the value in the remaining least significant bits. + * In our implementation, only low 7 bits are stored and otherwise + * bits are ignored. + */ + append((value | 0x80) & 0xff); + } + + /** + * Append an octet number between 128 and 255 into mMessage. + * NOTE: + * A value between 0 and 127 should be appended by using appendShortInteger. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendOctet(int number) { + append(number); + } + + /** + * Append a short length into mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + protected void appendShortLength(int value) { + /* + * From WAP-230-WSP-20010705-a: + * Short-length = <Any octet 0-30> + */ + append(value); + } + + /** + * Append long integer into mMessage. it's used for really long integers. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendLongInteger(long longInt) { + /* + * From WAP-230-WSP-20010705-a: + * Long-integer = Short-length Multi-octet-integer + * ; The Short-length indicates the length of the Multi-octet-integer + * Multi-octet-integer = 1*30 OCTET + * ; The content octets shall be an unsigned integer value with the + * ; most significant octet encoded first (big-endian representation). + * ; The minimum number of octets must be used to encode the value. + */ + int size; + long temp = longInt; + + // Count the length of the long integer. + for(size = 0; (temp != 0) && (size < LONG_INTEGER_LENGTH_MAX); size++) { + temp = (temp >>> 8); + } + + // Set Length. + appendShortLength(size); + + // Count and set the long integer. + int i; + int shift = (size -1) * 8; + + for (i = 0; i < size; i++) { + append((int)((longInt >>> shift) & 0xff)); + shift = shift - 8; + } + } + + /** + * Append text string into mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendTextString(byte[] text) { + /* + * From WAP-230-WSP-20010705-a: + * Text-string = [Quote] *TEXT End-of-string + * ; If the first character in the TEXT is in the range of 128-255, + * ; a Quote character must precede it. Otherwise the Quote character + * ;must be omitted. The Quote is not part of the contents. + */ + if (((text[0])&0xff) > TEXT_MAX) { // No need to check for <= 255 + append(TEXT_MAX); + } + + arraycopy(text, 0, text.length); + append(0); + } + + /** + * Append text string into mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendTextString(String str) { + /* + * From WAP-230-WSP-20010705-a: + * Text-string = [Quote] *TEXT End-of-string + * ; If the first character in the TEXT is in the range of 128-255, + * ; a Quote character must precede it. Otherwise the Quote character + * ;must be omitted. The Quote is not part of the contents. + */ + appendTextString(str.getBytes()); + } + + /** + * Append encoded string value to mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendEncodedString(EncodedStringValue enStr) { + /* + * From OMA-TS-MMS-ENC-V1_3-20050927-C: + * Encoded-string-value = Text-string | Value-length Char-set Text-string + */ + assert(enStr != null); + + int charset = enStr.getCharacterSet(); + byte[] textString = enStr.getTextString(); + if (null == textString) { + return; + } + + /* + * In the implementation of EncodedStringValue, the charset field will + * never be 0. It will always be composed as + * Encoded-string-value = Value-length Char-set Text-string + */ + mStack.newbuf(); + PositionMarker start = mStack.mark(); + + appendShortInteger(charset); + appendTextString(textString); + + int len = start.getLength(); + mStack.pop(); + appendValueLength(len); + mStack.copy(); + } + + /** + * Append uintvar integer into mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendUintvarInteger(long value) { + /* + * From WAP-230-WSP-20010705-a: + * To encode a large unsigned integer, split it into 7-bit fragments + * and place them in the payloads of multiple octets. The most significant + * bits are placed in the first octets with the least significant bits + * ending up in the last octet. All octets MUST set the Continue bit to 1 + * except the last octet, which MUST set the Continue bit to 0. + */ + int i; + long max = SHORT_INTEGER_MAX; + + for (i = 0; i < 5; i++) { + if (value < max) { + break; + } + + max = (max << 7) | 0x7fl; + } + + while(i > 0) { + long temp = value >>> (i * 7); + temp = temp & 0x7f; + + append((int)((temp | 0x80) & 0xff)); + + i--; + } + + append((int)(value & 0x7f)); + } + + /** + * Append date value into mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + protected void appendDateValue(long date) { + /* + * From OMA-TS-MMS-ENC-V1_3-20050927-C: + * Date-value = Long-integer + */ + appendLongInteger(date); + } + + /** + * Append value length to mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendValueLength(long value) { + /* + * From WAP-230-WSP-20010705-a: + * Value-length = Short-length | (Length-quote Length) + * ; Value length is used to indicate the length of the value to follow + * Short-length = <Any octet 0-30> + * Length-quote = <Octet 31> + * Length = Uintvar-integer + */ + if (value < LENGTH_QUOTE) { + appendShortLength((int) value); + return; + } + + append(LENGTH_QUOTE); + appendUintvarInteger(value); + } + + /** + * Append quoted string to mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendQuotedString(byte[] text) { + /* + * From WAP-230-WSP-20010705-a: + * Quoted-string = <Octet 34> *TEXT End-of-string + * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing + * ;quotation-marks <"> removed. + */ + append(QUOTED_STRING_FLAG); + arraycopy(text, 0, text.length); + append(END_STRING_FLAG); + } + + /** + * Append quoted string to mMessage. + * This implementation doesn't check the validity of parameter, since it + * assumes that the values are validated in the GenericPdu setter methods. + */ + @UnsupportedAppUsage + protected void appendQuotedString(String str) { + /* + * From WAP-230-WSP-20010705-a: + * Quoted-string = <Octet 34> *TEXT End-of-string + * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing + * ;quotation-marks <"> removed. + */ + appendQuotedString(str.getBytes()); + } + + private EncodedStringValue appendAddressType(EncodedStringValue address) { + EncodedStringValue temp = null; + + try { + int addressType = checkAddressType(address.getString()); + temp = EncodedStringValue.copy(address); + if (PDU_PHONE_NUMBER_ADDRESS_TYPE == addressType) { + // Phone number. + temp.appendTextString(STRING_PHONE_NUMBER_ADDRESS_TYPE.getBytes()); + } else if (PDU_IPV4_ADDRESS_TYPE == addressType) { + // Ipv4 address. + temp.appendTextString(STRING_IPV4_ADDRESS_TYPE.getBytes()); + } else if (PDU_IPV6_ADDRESS_TYPE == addressType) { + // Ipv6 address. + temp.appendTextString(STRING_IPV6_ADDRESS_TYPE.getBytes()); + } + } catch (NullPointerException e) { + return null; + } + + return temp; + } + + /** + * Append header to mMessage. + */ + @UnsupportedAppUsage + private int appendHeader(int field) { + switch (field) { + case PduHeaders.MMS_VERSION: + appendOctet(field); + + int version = mPduHeader.getOctet(field); + if (0 == version) { + appendShortInteger(PduHeaders.CURRENT_MMS_VERSION); + } else { + appendShortInteger(version); + } + + break; + + case PduHeaders.MESSAGE_ID: + case PduHeaders.TRANSACTION_ID: + byte[] textString = mPduHeader.getTextString(field); + if (null == textString) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + appendTextString(textString); + break; + + case PduHeaders.TO: + case PduHeaders.BCC: + case PduHeaders.CC: + EncodedStringValue[] addr = mPduHeader.getEncodedStringValues(field); + + if (null == addr) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + EncodedStringValue temp; + for (int i = 0; i < addr.length; i++) { + temp = appendAddressType(addr[i]); + if (temp == null) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + appendOctet(field); + appendEncodedString(temp); + } + break; + + case PduHeaders.FROM: + // Value-length (Address-present-token Encoded-string-value | Insert-address-token) + appendOctet(field); + + EncodedStringValue from = mPduHeader.getEncodedStringValue(field); + if ((from == null) + || TextUtils.isEmpty(from.getString()) + || new String(from.getTextString()).equals( + PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) { + // Length of from = 1 + append(1); + // Insert-address-token = <Octet 129> + append(PduHeaders.FROM_INSERT_ADDRESS_TOKEN); + } else { + mStack.newbuf(); + PositionMarker fstart = mStack.mark(); + + // Address-present-token = <Octet 128> + append(PduHeaders.FROM_ADDRESS_PRESENT_TOKEN); + + temp = appendAddressType(from); + if (temp == null) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + appendEncodedString(temp); + + int flen = fstart.getLength(); + mStack.pop(); + appendValueLength(flen); + mStack.copy(); + } + break; + + case PduHeaders.READ_STATUS: + case PduHeaders.STATUS: + case PduHeaders.REPORT_ALLOWED: + case PduHeaders.PRIORITY: + case PduHeaders.DELIVERY_REPORT: + case PduHeaders.READ_REPORT: + case PduHeaders.RETRIEVE_STATUS: + int octet = mPduHeader.getOctet(field); + if (0 == octet) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + appendOctet(octet); + break; + + case PduHeaders.DATE: + long date = mPduHeader.getLongInteger(field); + if (-1 == date) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + appendDateValue(date); + break; + + case PduHeaders.SUBJECT: + case PduHeaders.RETRIEVE_TEXT: + EncodedStringValue enString = + mPduHeader.getEncodedStringValue(field); + if (null == enString) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + appendEncodedString(enString); + break; + + case PduHeaders.MESSAGE_CLASS: + byte[] messageClass = mPduHeader.getTextString(field); + if (null == messageClass) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + if (Arrays.equals(messageClass, + PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes())) { + appendOctet(PduHeaders.MESSAGE_CLASS_ADVERTISEMENT); + } else if (Arrays.equals(messageClass, + PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes())) { + appendOctet(PduHeaders.MESSAGE_CLASS_AUTO); + } else if (Arrays.equals(messageClass, + PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes())) { + appendOctet(PduHeaders.MESSAGE_CLASS_PERSONAL); + } else if (Arrays.equals(messageClass, + PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes())) { + appendOctet(PduHeaders.MESSAGE_CLASS_INFORMATIONAL); + } else { + appendTextString(messageClass); + } + break; + + case PduHeaders.EXPIRY: + long expiry = mPduHeader.getLongInteger(field); + if (-1 == expiry) { + return PDU_COMPOSE_FIELD_NOT_SET; + } + + appendOctet(field); + + mStack.newbuf(); + PositionMarker expiryStart = mStack.mark(); + + append(PduHeaders.VALUE_RELATIVE_TOKEN); + appendLongInteger(expiry); + + int expiryLength = expiryStart.getLength(); + mStack.pop(); + appendValueLength(expiryLength); + mStack.copy(); + break; + + default: + return PDU_COMPOSE_FIELD_NOT_SUPPORTED; + } + + return PDU_COMPOSE_SUCCESS; + } + + /** + * Make ReadRec.Ind. + */ + private int makeReadRecInd() { + if (mMessage == null) { + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + // X-Mms-Message-Type + appendOctet(PduHeaders.MESSAGE_TYPE); + appendOctet(PduHeaders.MESSAGE_TYPE_READ_REC_IND); + + // X-Mms-MMS-Version + if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // Message-ID + if (appendHeader(PduHeaders.MESSAGE_ID) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // To + if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // From + if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // Date Optional + appendHeader(PduHeaders.DATE); + + // X-Mms-Read-Status + if (appendHeader(PduHeaders.READ_STATUS) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-Applic-ID Optional(not support) + // X-Mms-Reply-Applic-ID Optional(not support) + // X-Mms-Aux-Applic-Info Optional(not support) + + return PDU_COMPOSE_SUCCESS; + } + + /** + * Make NotifyResp.Ind. + */ + private int makeNotifyResp() { + if (mMessage == null) { + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + // X-Mms-Message-Type + appendOctet(PduHeaders.MESSAGE_TYPE); + appendOctet(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND); + + // X-Mms-Transaction-ID + if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-MMS-Version + if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-Status + if (appendHeader(PduHeaders.STATUS) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-Report-Allowed Optional (not support) + return PDU_COMPOSE_SUCCESS; + } + + /** + * Make Acknowledge.Ind. + */ + private int makeAckInd() { + if (mMessage == null) { + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + // X-Mms-Message-Type + appendOctet(PduHeaders.MESSAGE_TYPE); + appendOctet(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND); + + // X-Mms-Transaction-ID + if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-MMS-Version + if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // X-Mms-Report-Allowed Optional + appendHeader(PduHeaders.REPORT_ALLOWED); + + return PDU_COMPOSE_SUCCESS; + } + + /** + * Make Send.req. + */ + private int makeSendRetrievePdu(int type) { + if (mMessage == null) { + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + // X-Mms-Message-Type + appendOctet(PduHeaders.MESSAGE_TYPE); + appendOctet(type); + + // X-Mms-Transaction-ID + appendOctet(PduHeaders.TRANSACTION_ID); + + byte[] trid = mPduHeader.getTextString(PduHeaders.TRANSACTION_ID); + if (trid == null) { + // Transaction-ID should be set(by Transaction) before make(). + throw new IllegalArgumentException("Transaction-ID is null."); + } + appendTextString(trid); + + // X-Mms-MMS-Version + if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // Date Date-value Optional. + appendHeader(PduHeaders.DATE); + + // From + if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + boolean recipient = false; + + // To + if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_CONTENT_ERROR) { + recipient = true; + } + + // Cc + if (appendHeader(PduHeaders.CC) != PDU_COMPOSE_CONTENT_ERROR) { + recipient = true; + } + + // Bcc + if (appendHeader(PduHeaders.BCC) != PDU_COMPOSE_CONTENT_ERROR) { + recipient = true; + } + + // Need at least one of "cc", "bcc" and "to". + if (false == recipient) { + return PDU_COMPOSE_CONTENT_ERROR; + } + + // Subject Optional + appendHeader(PduHeaders.SUBJECT); + + // X-Mms-Message-Class Optional + // Message-class-value = Class-identifier | Token-text + appendHeader(PduHeaders.MESSAGE_CLASS); + + // X-Mms-Expiry Optional + appendHeader(PduHeaders.EXPIRY); + + // X-Mms-Priority Optional + appendHeader(PduHeaders.PRIORITY); + + // X-Mms-Delivery-Report Optional + appendHeader(PduHeaders.DELIVERY_REPORT); + + // X-Mms-Read-Report Optional + appendHeader(PduHeaders.READ_REPORT); + + if (type == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) { + // X-Mms-Retrieve-Status Optional + appendHeader(PduHeaders.RETRIEVE_STATUS); + // X-Mms-Retrieve-Text Optional + appendHeader(PduHeaders.RETRIEVE_TEXT); + } + + + // Content-Type + appendOctet(PduHeaders.CONTENT_TYPE); + + // Message body + return makeMessageBody(type); + } + + /** + * Make message body. + */ + private int makeMessageBody(int type) { + // 1. add body informations + mStack.newbuf(); // Switching buffer because we need to + + PositionMarker ctStart = mStack.mark(); + + // This contentTypeIdentifier should be used for type of attachment... + String contentType = new String(mPduHeader.getTextString(PduHeaders.CONTENT_TYPE)); + Integer contentTypeIdentifier = mContentTypeMap.get(contentType); + if (contentTypeIdentifier == null) { + // content type is mandatory + return PDU_COMPOSE_CONTENT_ERROR; + } + + appendShortInteger(contentTypeIdentifier.intValue()); + + // content-type parameter: start + PduBody body; + if (type == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) { + body = ((RetrieveConf) mPdu).getBody(); + } else { + body = ((SendReq) mPdu).getBody(); + } + if (null == body || body.getPartsNum() == 0) { + // empty message + appendUintvarInteger(0); + mStack.pop(); + mStack.copy(); + return PDU_COMPOSE_SUCCESS; + } + + PduPart part; + try { + part = body.getPart(0); + + byte[] start = part.getContentId(); + if (start != null) { + appendOctet(PduPart.P_DEP_START); + if (('<' == start[0]) && ('>' == start[start.length - 1])) { + appendTextString(start); + } else { + appendTextString("<" + new String(start) + ">"); + } + } + + // content-type parameter: type + appendOctet(PduPart.P_CT_MR_TYPE); + appendTextString(part.getContentType()); + } + catch (ArrayIndexOutOfBoundsException e){ + e.printStackTrace(); + } + + int ctLength = ctStart.getLength(); + mStack.pop(); + appendValueLength(ctLength); + mStack.copy(); + + // 3. add content + int partNum = body.getPartsNum(); + appendUintvarInteger(partNum); + for (int i = 0; i < partNum; i++) { + part = body.getPart(i); + mStack.newbuf(); // Leaving space for header lengh and data length + PositionMarker attachment = mStack.mark(); + + mStack.newbuf(); // Leaving space for Content-Type length + PositionMarker contentTypeBegin = mStack.mark(); + + byte[] partContentType = part.getContentType(); + + if (partContentType == null) { + // content type is mandatory + return PDU_COMPOSE_CONTENT_ERROR; + } + + // content-type value + Integer partContentTypeIdentifier = + mContentTypeMap.get(new String(partContentType)); + if (partContentTypeIdentifier == null) { + appendTextString(partContentType); + } else { + appendShortInteger(partContentTypeIdentifier.intValue()); + } + + /* Content-type parameter : name. + * The value of name, filename, content-location is the same. + * Just one of them is enough for this PDU. + */ + byte[] name = part.getName(); + + if (null == name) { + name = part.getFilename(); + + if (null == name) { + name = part.getContentLocation(); + + if (null == name) { + /* at lease one of name, filename, Content-location + * should be available. + */ + return PDU_COMPOSE_CONTENT_ERROR; + } + } + } + appendOctet(PduPart.P_DEP_NAME); + appendTextString(name); + + // content-type parameter : charset + int charset = part.getCharset(); + if (charset != 0) { + appendOctet(PduPart.P_CHARSET); + appendShortInteger(charset); + } + + int contentTypeLength = contentTypeBegin.getLength(); + mStack.pop(); + appendValueLength(contentTypeLength); + mStack.copy(); + + // content id + byte[] contentId = part.getContentId(); + + if (null != contentId) { + appendOctet(PduPart.P_CONTENT_ID); + if (('<' == contentId[0]) && ('>' == contentId[contentId.length - 1])) { + appendQuotedString(contentId); + } else { + appendQuotedString("<" + new String(contentId) + ">"); + } + } + + // content-location + byte[] contentLocation = part.getContentLocation(); + if (null != contentLocation) { + appendOctet(PduPart.P_CONTENT_LOCATION); + appendTextString(contentLocation); + } + + // content + int headerLength = attachment.getLength(); + + int dataLength = 0; // Just for safety... + byte[] partData = part.getData(); + + if (partData != null) { + arraycopy(partData, 0, partData.length); + dataLength = partData.length; + } else { + InputStream cr = null; + try { + byte[] buffer = new byte[PDU_COMPOSER_BLOCK_SIZE]; + cr = mResolver.openInputStream(part.getDataUri()); + int len = 0; + while ((len = cr.read(buffer)) != -1) { + mMessage.write(buffer, 0, len); + mPosition += len; + dataLength += len; + } + } catch (FileNotFoundException e) { + return PDU_COMPOSE_CONTENT_ERROR; + } catch (IOException e) { + return PDU_COMPOSE_CONTENT_ERROR; + } catch (RuntimeException e) { + return PDU_COMPOSE_CONTENT_ERROR; + } finally { + if (cr != null) { + try { + cr.close(); + } catch (IOException e) { + } + } + } + } + + if (dataLength != (attachment.getLength() - headerLength)) { + throw new RuntimeException("BUG: Length sanity check failed"); + } + + mStack.pop(); + appendUintvarInteger(headerLength); + appendUintvarInteger(dataLength); + mStack.copy(); + } + + return PDU_COMPOSE_SUCCESS; + } + + /** + * Record current message informations. + */ + static private class LengthRecordNode { + ByteArrayOutputStream currentMessage = null; + public int currentPosition = 0; + + public LengthRecordNode next = null; + } + + /** + * Mark current message position and stact size. + */ + private class PositionMarker { + private int c_pos; // Current position + private int currentStackSize; // Current stack size + + @UnsupportedAppUsage + int getLength() { + // If these assert fails, likely that you are finding the + // size of buffer that is deep in BufferStack you can only + // find the length of the buffer that is on top + if (currentStackSize != mStack.stackSize) { + throw new RuntimeException("BUG: Invalid call to getLength()"); + } + + return mPosition - c_pos; + } + } + + /** + * This implementation can be OPTIMIZED to use only + * 2 buffers. This optimization involves changing BufferStack + * only... Its usage (interface) will not change. + */ + private class BufferStack { + private LengthRecordNode stack = null; + private LengthRecordNode toCopy = null; + + int stackSize = 0; + + /** + * Create a new message buffer and push it into the stack. + */ + @UnsupportedAppUsage + void newbuf() { + // You can't create a new buff when toCopy != null + // That is after calling pop() and before calling copy() + // If you do, it is a bug + if (toCopy != null) { + throw new RuntimeException("BUG: Invalid newbuf() before copy()"); + } + + LengthRecordNode temp = new LengthRecordNode(); + + temp.currentMessage = mMessage; + temp.currentPosition = mPosition; + + temp.next = stack; + stack = temp; + + stackSize = stackSize + 1; + + mMessage = new ByteArrayOutputStream(); + mPosition = 0; + } + + /** + * Pop the message before and record current message in the stack. + */ + @UnsupportedAppUsage + void pop() { + ByteArrayOutputStream currentMessage = mMessage; + int currentPosition = mPosition; + + mMessage = stack.currentMessage; + mPosition = stack.currentPosition; + + toCopy = stack; + // Re using the top element of the stack to avoid memory allocation + + stack = stack.next; + stackSize = stackSize - 1; + + toCopy.currentMessage = currentMessage; + toCopy.currentPosition = currentPosition; + } + + /** + * Append current message to the message before. + */ + @UnsupportedAppUsage + void copy() { + arraycopy(toCopy.currentMessage.toByteArray(), 0, + toCopy.currentPosition); + + toCopy = null; + } + + /** + * Mark current message position + */ + @UnsupportedAppUsage + PositionMarker mark() { + PositionMarker m = new PositionMarker(); + + m.c_pos = mPosition; + m.currentStackSize = stackSize; + + return m; + } + } + + /** + * Check address type. + * + * @param address address string without the postfix stinng type, + * such as "/TYPE=PLMN", "/TYPE=IPv6" and "/TYPE=IPv4" + * @return PDU_PHONE_NUMBER_ADDRESS_TYPE if it is phone number, + * PDU_EMAIL_ADDRESS_TYPE if it is email address, + * PDU_IPV4_ADDRESS_TYPE if it is ipv4 address, + * PDU_IPV6_ADDRESS_TYPE if it is ipv6 address, + * PDU_UNKNOWN_ADDRESS_TYPE if it is unknown. + */ + protected static int checkAddressType(String address) { + /** + * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf, section 8. + * address = ( e-mail / device-address / alphanum-shortcode / num-shortcode) + * e-mail = mailbox; to the definition of mailbox as described in + * section 3.4 of [RFC2822], but excluding the + * obsolete definitions as indicated by the "obs-" prefix. + * device-address = ( global-phone-number "/TYPE=PLMN" ) + * / ( ipv4 "/TYPE=IPv4" ) / ( ipv6 "/TYPE=IPv6" ) + * / ( escaped-value "/TYPE=" address-type ) + * + * global-phone-number = ["+"] 1*( DIGIT / written-sep ) + * written-sep =("-"/".") + * + * ipv4 = 1*3DIGIT 3( "." 1*3DIGIT ) ; IPv4 address value + * + * ipv6 = 4HEXDIG 7( ":" 4HEXDIG ) ; IPv6 address per RFC 2373 + */ + + if (null == address) { + return PDU_UNKNOWN_ADDRESS_TYPE; + } + + if (address.matches(REGEXP_IPV4_ADDRESS_TYPE)) { + // Ipv4 address. + return PDU_IPV4_ADDRESS_TYPE; + }else if (address.matches(REGEXP_PHONE_NUMBER_ADDRESS_TYPE)) { + // Phone number. + return PDU_PHONE_NUMBER_ADDRESS_TYPE; + } else if (address.matches(REGEXP_EMAIL_ADDRESS_TYPE)) { + // Email address. + return PDU_EMAIL_ADDRESS_TYPE; + } else if (address.matches(REGEXP_IPV6_ADDRESS_TYPE)) { + // Ipv6 address. + return PDU_IPV6_ADDRESS_TYPE; + } else { + // Unknown address. + return PDU_UNKNOWN_ADDRESS_TYPE; + } + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduContentTypes.java b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java new file mode 100644 index 000000000000..8551b2f9b693 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +public class PduContentTypes { + /** + * All content types. From: + * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.htm + */ + @UnsupportedAppUsage + static final String[] contentTypes = { + "*/*", /* 0x00 */ + "text/*", /* 0x01 */ + "text/html", /* 0x02 */ + "text/plain", /* 0x03 */ + "text/x-hdml", /* 0x04 */ + "text/x-ttml", /* 0x05 */ + "text/x-vCalendar", /* 0x06 */ + "text/x-vCard", /* 0x07 */ + "text/vnd.wap.wml", /* 0x08 */ + "text/vnd.wap.wmlscript", /* 0x09 */ + "text/vnd.wap.wta-event", /* 0x0A */ + "multipart/*", /* 0x0B */ + "multipart/mixed", /* 0x0C */ + "multipart/form-data", /* 0x0D */ + "multipart/byterantes", /* 0x0E */ + "multipart/alternative", /* 0x0F */ + "application/*", /* 0x10 */ + "application/java-vm", /* 0x11 */ + "application/x-www-form-urlencoded", /* 0x12 */ + "application/x-hdmlc", /* 0x13 */ + "application/vnd.wap.wmlc", /* 0x14 */ + "application/vnd.wap.wmlscriptc", /* 0x15 */ + "application/vnd.wap.wta-eventc", /* 0x16 */ + "application/vnd.wap.uaprof", /* 0x17 */ + "application/vnd.wap.wtls-ca-certificate", /* 0x18 */ + "application/vnd.wap.wtls-user-certificate", /* 0x19 */ + "application/x-x509-ca-cert", /* 0x1A */ + "application/x-x509-user-cert", /* 0x1B */ + "image/*", /* 0x1C */ + "image/gif", /* 0x1D */ + "image/jpeg", /* 0x1E */ + "image/tiff", /* 0x1F */ + "image/png", /* 0x20 */ + "image/vnd.wap.wbmp", /* 0x21 */ + "application/vnd.wap.multipart.*", /* 0x22 */ + "application/vnd.wap.multipart.mixed", /* 0x23 */ + "application/vnd.wap.multipart.form-data", /* 0x24 */ + "application/vnd.wap.multipart.byteranges", /* 0x25 */ + "application/vnd.wap.multipart.alternative", /* 0x26 */ + "application/xml", /* 0x27 */ + "text/xml", /* 0x28 */ + "application/vnd.wap.wbxml", /* 0x29 */ + "application/x-x968-cross-cert", /* 0x2A */ + "application/x-x968-ca-cert", /* 0x2B */ + "application/x-x968-user-cert", /* 0x2C */ + "text/vnd.wap.si", /* 0x2D */ + "application/vnd.wap.sic", /* 0x2E */ + "text/vnd.wap.sl", /* 0x2F */ + "application/vnd.wap.slc", /* 0x30 */ + "text/vnd.wap.co", /* 0x31 */ + "application/vnd.wap.coc", /* 0x32 */ + "application/vnd.wap.multipart.related", /* 0x33 */ + "application/vnd.wap.sia", /* 0x34 */ + "text/vnd.wap.connectivity-xml", /* 0x35 */ + "application/vnd.wap.connectivity-wbxml", /* 0x36 */ + "application/pkcs7-mime", /* 0x37 */ + "application/vnd.wap.hashed-certificate", /* 0x38 */ + "application/vnd.wap.signed-certificate", /* 0x39 */ + "application/vnd.wap.cert-response", /* 0x3A */ + "application/xhtml+xml", /* 0x3B */ + "application/wml+xml", /* 0x3C */ + "text/css", /* 0x3D */ + "application/vnd.wap.mms-message", /* 0x3E */ + "application/vnd.wap.rollover-certificate", /* 0x3F */ + "application/vnd.wap.locc+wbxml", /* 0x40 */ + "application/vnd.wap.loc+xml", /* 0x41 */ + "application/vnd.syncml.dm+wbxml", /* 0x42 */ + "application/vnd.syncml.dm+xml", /* 0x43 */ + "application/vnd.syncml.notification", /* 0x44 */ + "application/vnd.wap.xhtml+xml", /* 0x45 */ + "application/vnd.wv.csp.cir", /* 0x46 */ + "application/vnd.oma.dd+xml", /* 0x47 */ + "application/vnd.oma.drm.message", /* 0x48 */ + "application/vnd.oma.drm.content", /* 0x49 */ + "application/vnd.oma.drm.rights+xml", /* 0x4A */ + "application/vnd.oma.drm.rights+wbxml", /* 0x4B */ + "application/vnd.wv.csp+xml", /* 0x4C */ + "application/vnd.wv.csp+wbxml", /* 0x4D */ + "application/vnd.syncml.ds.notification", /* 0x4E */ + "audio/*", /* 0x4F */ + "video/*", /* 0x50 */ + "application/vnd.oma.dd2+xml", /* 0x51 */ + "application/mikey" /* 0x52 */ + }; +} diff --git a/telephony/common/com/google/android/mms/pdu/PduHeaders.java b/telephony/common/com/google/android/mms/pdu/PduHeaders.java new file mode 100644 index 000000000000..b5244645fda1 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduHeaders.java @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +import java.util.ArrayList; +import java.util.HashMap; + +public class PduHeaders { + /** + * All pdu header fields. + */ + public static final int BCC = 0x81; + public static final int CC = 0x82; + public static final int CONTENT_LOCATION = 0x83; + public static final int CONTENT_TYPE = 0x84; + public static final int DATE = 0x85; + public static final int DELIVERY_REPORT = 0x86; + public static final int DELIVERY_TIME = 0x87; + public static final int EXPIRY = 0x88; + public static final int FROM = 0x89; + public static final int MESSAGE_CLASS = 0x8A; + public static final int MESSAGE_ID = 0x8B; + public static final int MESSAGE_TYPE = 0x8C; + public static final int MMS_VERSION = 0x8D; + public static final int MESSAGE_SIZE = 0x8E; + public static final int PRIORITY = 0x8F; + + public static final int READ_REPLY = 0x90; + public static final int READ_REPORT = 0x90; + public static final int REPORT_ALLOWED = 0x91; + public static final int RESPONSE_STATUS = 0x92; + public static final int RESPONSE_TEXT = 0x93; + public static final int SENDER_VISIBILITY = 0x94; + public static final int STATUS = 0x95; + public static final int SUBJECT = 0x96; + public static final int TO = 0x97; + public static final int TRANSACTION_ID = 0x98; + public static final int RETRIEVE_STATUS = 0x99; + public static final int RETRIEVE_TEXT = 0x9A; + public static final int READ_STATUS = 0x9B; + public static final int REPLY_CHARGING = 0x9C; + public static final int REPLY_CHARGING_DEADLINE = 0x9D; + public static final int REPLY_CHARGING_ID = 0x9E; + public static final int REPLY_CHARGING_SIZE = 0x9F; + + public static final int PREVIOUSLY_SENT_BY = 0xA0; + public static final int PREVIOUSLY_SENT_DATE = 0xA1; + public static final int STORE = 0xA2; + public static final int MM_STATE = 0xA3; + public static final int MM_FLAGS = 0xA4; + public static final int STORE_STATUS = 0xA5; + public static final int STORE_STATUS_TEXT = 0xA6; + public static final int STORED = 0xA7; + public static final int ATTRIBUTES = 0xA8; + public static final int TOTALS = 0xA9; + public static final int MBOX_TOTALS = 0xAA; + public static final int QUOTAS = 0xAB; + public static final int MBOX_QUOTAS = 0xAC; + public static final int MESSAGE_COUNT = 0xAD; + public static final int CONTENT = 0xAE; + public static final int START = 0xAF; + + public static final int ADDITIONAL_HEADERS = 0xB0; + public static final int DISTRIBUTION_INDICATOR = 0xB1; + public static final int ELEMENT_DESCRIPTOR = 0xB2; + public static final int LIMIT = 0xB3; + public static final int RECOMMENDED_RETRIEVAL_MODE = 0xB4; + public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5; + public static final int STATUS_TEXT = 0xB6; + public static final int APPLIC_ID = 0xB7; + public static final int REPLY_APPLIC_ID = 0xB8; + public static final int AUX_APPLIC_ID = 0xB9; + public static final int CONTENT_CLASS = 0xBA; + public static final int DRM_CONTENT = 0xBB; + public static final int ADAPTATION_ALLOWED = 0xBC; + public static final int REPLACE_ID = 0xBD; + public static final int CANCEL_ID = 0xBE; + public static final int CANCEL_STATUS = 0xBF; + + /** + * X-Mms-Message-Type field types. + */ + public static final int MESSAGE_TYPE_SEND_REQ = 0x80; + public static final int MESSAGE_TYPE_SEND_CONF = 0x81; + public static final int MESSAGE_TYPE_NOTIFICATION_IND = 0x82; + public static final int MESSAGE_TYPE_NOTIFYRESP_IND = 0x83; + public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84; + public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND = 0x85; + public static final int MESSAGE_TYPE_DELIVERY_IND = 0x86; + public static final int MESSAGE_TYPE_READ_REC_IND = 0x87; + public static final int MESSAGE_TYPE_READ_ORIG_IND = 0x88; + public static final int MESSAGE_TYPE_FORWARD_REQ = 0x89; + public static final int MESSAGE_TYPE_FORWARD_CONF = 0x8A; + public static final int MESSAGE_TYPE_MBOX_STORE_REQ = 0x8B; + public static final int MESSAGE_TYPE_MBOX_STORE_CONF = 0x8C; + public static final int MESSAGE_TYPE_MBOX_VIEW_REQ = 0x8D; + public static final int MESSAGE_TYPE_MBOX_VIEW_CONF = 0x8E; + public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ = 0x8F; + public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF = 0x90; + public static final int MESSAGE_TYPE_MBOX_DELETE_REQ = 0x91; + public static final int MESSAGE_TYPE_MBOX_DELETE_CONF = 0x92; + public static final int MESSAGE_TYPE_MBOX_DESCR = 0x93; + public static final int MESSAGE_TYPE_DELETE_REQ = 0x94; + public static final int MESSAGE_TYPE_DELETE_CONF = 0x95; + public static final int MESSAGE_TYPE_CANCEL_REQ = 0x96; + public static final int MESSAGE_TYPE_CANCEL_CONF = 0x97; + + /** + * X-Mms-Delivery-Report | + * X-Mms-Read-Report | + * X-Mms-Report-Allowed | + * X-Mms-Sender-Visibility | + * X-Mms-Store | + * X-Mms-Stored | + * X-Mms-Totals | + * X-Mms-Quotas | + * X-Mms-Distribution-Indicator | + * X-Mms-DRM-Content | + * X-Mms-Adaptation-Allowed | + * field types. + */ + public static final int VALUE_YES = 0x80; + public static final int VALUE_NO = 0x81; + + /** + * Delivery-Time | + * Expiry and Reply-Charging-Deadline | + * field type components. + */ + public static final int VALUE_ABSOLUTE_TOKEN = 0x80; + public static final int VALUE_RELATIVE_TOKEN = 0x81; + + /** + * X-Mms-MMS-Version field types. + */ + public static final int MMS_VERSION_1_3 = ((1 << 4) | 3); + public static final int MMS_VERSION_1_2 = ((1 << 4) | 2); + public static final int MMS_VERSION_1_1 = ((1 << 4) | 1); + public static final int MMS_VERSION_1_0 = ((1 << 4) | 0); + + // Current version is 1.2. + public static final int CURRENT_MMS_VERSION = MMS_VERSION_1_2; + + /** + * From field type components. + */ + public static final int FROM_ADDRESS_PRESENT_TOKEN = 0x80; + public static final int FROM_INSERT_ADDRESS_TOKEN = 0x81; + + public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token"; + public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token"; + + /** + * X-Mms-Status Field. + */ + public static final int STATUS_EXPIRED = 0x80; + public static final int STATUS_RETRIEVED = 0x81; + public static final int STATUS_REJECTED = 0x82; + public static final int STATUS_DEFERRED = 0x83; + public static final int STATUS_UNRECOGNIZED = 0x84; + public static final int STATUS_INDETERMINATE = 0x85; + public static final int STATUS_FORWARDED = 0x86; + public static final int STATUS_UNREACHABLE = 0x87; + + /** + * MM-Flags field type components. + */ + public static final int MM_FLAGS_ADD_TOKEN = 0x80; + public static final int MM_FLAGS_REMOVE_TOKEN = 0x81; + public static final int MM_FLAGS_FILTER_TOKEN = 0x82; + + /** + * X-Mms-Message-Class field types. + */ + public static final int MESSAGE_CLASS_PERSONAL = 0x80; + public static final int MESSAGE_CLASS_ADVERTISEMENT = 0x81; + public static final int MESSAGE_CLASS_INFORMATIONAL = 0x82; + public static final int MESSAGE_CLASS_AUTO = 0x83; + + public static final String MESSAGE_CLASS_PERSONAL_STR = "personal"; + public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement"; + public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational"; + public static final String MESSAGE_CLASS_AUTO_STR = "auto"; + + /** + * X-Mms-Priority field types. + */ + public static final int PRIORITY_LOW = 0x80; + public static final int PRIORITY_NORMAL = 0x81; + public static final int PRIORITY_HIGH = 0x82; + + /** + * X-Mms-Response-Status field types. + */ + public static final int RESPONSE_STATUS_OK = 0x80; + public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED = 0x81; + public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82; + + public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT = 0x83; + public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84; + + public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND = 0x85; + public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM = 0x86; + public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87; + public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE = 0x88; + public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0; + + public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1; + public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC2; + public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC3; + public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS = 0xC4; + + public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED = 0xE3; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE4; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED = 0xE5; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET = 0xE6; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED = 0xE6; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED = 0xE8; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED = 0xE9; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED = 0xEA; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID = 0xEB; + public static final int RESPONSE_STATUS_ERROR_PERMANENT_END = 0xFF; + + /** + * X-Mms-Retrieve-Status field types. + */ + public static final int RETRIEVE_STATUS_OK = 0x80; + public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0; + public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC1; + public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC2; + public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0; + public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1; + public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE2; + public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3; + public static final int RETRIEVE_STATUS_ERROR_END = 0xFF; + + /** + * X-Mms-Sender-Visibility field types. + */ + public static final int SENDER_VISIBILITY_HIDE = 0x80; + public static final int SENDER_VISIBILITY_SHOW = 0x81; + + /** + * X-Mms-Read-Status field types. + */ + public static final int READ_STATUS_READ = 0x80; + public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81; + + /** + * X-Mms-Cancel-Status field types. + */ + public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80; + public static final int CANCEL_STATUS_REQUEST_CORRUPTED = 0x81; + + /** + * X-Mms-Reply-Charging field types. + */ + public static final int REPLY_CHARGING_REQUESTED = 0x80; + public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81; + public static final int REPLY_CHARGING_ACCEPTED = 0x82; + public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY = 0x83; + + /** + * X-Mms-MM-State field types. + */ + public static final int MM_STATE_DRAFT = 0x80; + public static final int MM_STATE_SENT = 0x81; + public static final int MM_STATE_NEW = 0x82; + public static final int MM_STATE_RETRIEVED = 0x83; + public static final int MM_STATE_FORWARDED = 0x84; + + /** + * X-Mms-Recommended-Retrieval-Mode field types. + */ + public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80; + + /** + * X-Mms-Content-Class field types. + */ + public static final int CONTENT_CLASS_TEXT = 0x80; + public static final int CONTENT_CLASS_IMAGE_BASIC = 0x81; + public static final int CONTENT_CLASS_IMAGE_RICH = 0x82; + public static final int CONTENT_CLASS_VIDEO_BASIC = 0x83; + public static final int CONTENT_CLASS_VIDEO_RICH = 0x84; + public static final int CONTENT_CLASS_MEGAPIXEL = 0x85; + public static final int CONTENT_CLASS_CONTENT_BASIC = 0x86; + public static final int CONTENT_CLASS_CONTENT_RICH = 0x87; + + /** + * X-Mms-Store-Status field types. + */ + public static final int STORE_STATUS_SUCCESS = 0x80; + public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0; + public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC1; + public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0; + public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1; + public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2; + public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE3; + public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL = 0xE4; + public static final int STORE_STATUS_ERROR_END = 0xFF; + + /** + * The map contains the value of all headers. + */ + private HashMap<Integer, Object> mHeaderMap = null; + + /** + * Constructor of PduHeaders. + */ + @UnsupportedAppUsage + public PduHeaders() { + mHeaderMap = new HashMap<Integer, Object>(); + } + + /** + * Get octet value by header field. + * + * @param field the field + * @return the octet value of the pdu header + * with specified header field. Return 0 if + * the value is not set. + */ + @UnsupportedAppUsage + protected int getOctet(int field) { + Integer octet = (Integer) mHeaderMap.get(field); + if (null == octet) { + return 0; + } + + return octet; + } + + /** + * Set octet value to pdu header by header field. + * + * @param value the value + * @param field the field + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + protected void setOctet(int value, int field) + throws InvalidHeaderValueException{ + /** + * Check whether this field can be set for specific + * header and check validity of the field. + */ + switch (field) { + case REPORT_ALLOWED: + case ADAPTATION_ALLOWED: + case DELIVERY_REPORT: + case DRM_CONTENT: + case DISTRIBUTION_INDICATOR: + case QUOTAS: + case READ_REPORT: + case STORE: + case STORED: + case TOTALS: + case SENDER_VISIBILITY: + if ((VALUE_YES != value) && (VALUE_NO != value)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case READ_STATUS: + if ((READ_STATUS_READ != value) && + (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case CANCEL_STATUS: + if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) && + (CANCEL_STATUS_REQUEST_CORRUPTED != value)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case PRIORITY: + if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case STATUS: + if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case REPLY_CHARGING: + if ((value < REPLY_CHARGING_REQUESTED) + || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case MM_STATE: + if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case RECOMMENDED_RETRIEVAL_MODE: + if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case CONTENT_CLASS: + if ((value < CONTENT_CLASS_TEXT) + || (value > CONTENT_CLASS_CONTENT_RICH)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + case RETRIEVE_STATUS: + // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value. + if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) && + (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) { + value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE; + } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) && + (value <= RETRIEVE_STATUS_ERROR_END)) { + value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE; + } else if ((value < RETRIEVE_STATUS_OK) || + ((value > RETRIEVE_STATUS_OK) && + (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) || + (value > RETRIEVE_STATUS_ERROR_END)) { + value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE; + } + break; + case STORE_STATUS: + // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value. + if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) && + (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) { + value = STORE_STATUS_ERROR_TRANSIENT_FAILURE; + } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) && + (value <= STORE_STATUS_ERROR_END)) { + value = STORE_STATUS_ERROR_PERMANENT_FAILURE; + } else if ((value < STORE_STATUS_SUCCESS) || + ((value > STORE_STATUS_SUCCESS) && + (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) || + (value > STORE_STATUS_ERROR_END)) { + value = STORE_STATUS_ERROR_PERMANENT_FAILURE; + } + break; + case RESPONSE_STATUS: + // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value. + if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) && + (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) { + value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE; + } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) && + (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) || + (value < RESPONSE_STATUS_OK) || + ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) && + (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) || + (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) { + value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE; + } + break; + case MMS_VERSION: + if ((value < MMS_VERSION_1_0)|| (value > MMS_VERSION_1_3)) { + value = CURRENT_MMS_VERSION; // Current version is the default value. + } + break; + case MESSAGE_TYPE: + if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) { + // Invalid value. + throw new InvalidHeaderValueException("Invalid Octet value!"); + } + break; + default: + // This header value should not be Octect. + throw new RuntimeException("Invalid header field!"); + } + mHeaderMap.put(field, value); + } + + /** + * Get TextString value by header field. + * + * @param field the field + * @return the TextString value of the pdu header + * with specified header field + */ + @UnsupportedAppUsage + protected byte[] getTextString(int field) { + return (byte[]) mHeaderMap.get(field); + } + + /** + * Set TextString value to pdu header by header field. + * + * @param value the value + * @param field the field + * @return the TextString value of the pdu header + * with specified header field + * @throws NullPointerException if the value is null. + */ + protected void setTextString(byte[] value, int field) { + /** + * Check whether this field can be set for specific + * header and check validity of the field. + */ + if (null == value) { + throw new NullPointerException(); + } + + switch (field) { + case TRANSACTION_ID: + case REPLY_CHARGING_ID: + case AUX_APPLIC_ID: + case APPLIC_ID: + case REPLY_APPLIC_ID: + case MESSAGE_ID: + case REPLACE_ID: + case CANCEL_ID: + case CONTENT_LOCATION: + case MESSAGE_CLASS: + case CONTENT_TYPE: + break; + default: + // This header value should not be Text-String. + throw new RuntimeException("Invalid header field!"); + } + mHeaderMap.put(field, value); + } + + /** + * Get EncodedStringValue value by header field. + * + * @param field the field + * @return the EncodedStringValue value of the pdu header + * with specified header field + */ + @UnsupportedAppUsage + protected EncodedStringValue getEncodedStringValue(int field) { + return (EncodedStringValue) mHeaderMap.get(field); + } + + /** + * Get TO, CC or BCC header value. + * + * @param field the field + * @return the EncodeStringValue array of the pdu header + * with specified header field + */ + @UnsupportedAppUsage + protected EncodedStringValue[] getEncodedStringValues(int field) { + ArrayList<EncodedStringValue> list = + (ArrayList<EncodedStringValue>) mHeaderMap.get(field); + if (null == list) { + return null; + } + EncodedStringValue[] values = new EncodedStringValue[list.size()]; + return list.toArray(values); + } + + /** + * Set EncodedStringValue value to pdu header by header field. + * + * @param value the value + * @param field the field + * @return the EncodedStringValue value of the pdu header + * with specified header field + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + protected void setEncodedStringValue(EncodedStringValue value, int field) { + /** + * Check whether this field can be set for specific + * header and check validity of the field. + */ + if (null == value) { + throw new NullPointerException(); + } + + switch (field) { + case SUBJECT: + case RECOMMENDED_RETRIEVAL_MODE_TEXT: + case RETRIEVE_TEXT: + case STATUS_TEXT: + case STORE_STATUS_TEXT: + case RESPONSE_TEXT: + case FROM: + case PREVIOUSLY_SENT_BY: + case MM_FLAGS: + break; + default: + // This header value should not be Encoded-String-Value. + throw new RuntimeException("Invalid header field!"); + } + + mHeaderMap.put(field, value); + } + + /** + * Set TO, CC or BCC header value. + * + * @param value the value + * @param field the field + * @return the EncodedStringValue value array of the pdu header + * with specified header field + * @throws NullPointerException if the value is null. + */ + protected void setEncodedStringValues(EncodedStringValue[] value, int field) { + /** + * Check whether this field can be set for specific + * header and check validity of the field. + */ + if (null == value) { + throw new NullPointerException(); + } + + switch (field) { + case BCC: + case CC: + case TO: + break; + default: + // This header value should not be Encoded-String-Value. + throw new RuntimeException("Invalid header field!"); + } + + ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>(); + for (int i = 0; i < value.length; i++) { + list.add(value[i]); + } + mHeaderMap.put(field, list); + } + + /** + * Append one EncodedStringValue to another. + * + * @param value the EncodedStringValue to append + * @param field the field + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + protected void appendEncodedStringValue(EncodedStringValue value, + int field) { + if (null == value) { + throw new NullPointerException(); + } + + switch (field) { + case BCC: + case CC: + case TO: + break; + default: + throw new RuntimeException("Invalid header field!"); + } + + ArrayList<EncodedStringValue> list = + (ArrayList<EncodedStringValue>) mHeaderMap.get(field); + if (null == list) { + list = new ArrayList<EncodedStringValue>(); + } + list.add(value); + mHeaderMap.put(field, list); + } + + /** + * Get LongInteger value by header field. + * + * @param field the field + * @return the LongInteger value of the pdu header + * with specified header field. if return -1, the + * field is not existed in pdu header. + */ + @UnsupportedAppUsage + protected long getLongInteger(int field) { + Long longInteger = (Long) mHeaderMap.get(field); + if (null == longInteger) { + return -1; + } + + return longInteger.longValue(); + } + + /** + * Set LongInteger value to pdu header by header field. + * + * @param value the value + * @param field the field + */ + @UnsupportedAppUsage + protected void setLongInteger(long value, int field) { + /** + * Check whether this field can be set for specific + * header and check validity of the field. + */ + switch (field) { + case DATE: + case REPLY_CHARGING_SIZE: + case MESSAGE_SIZE: + case MESSAGE_COUNT: + case START: + case LIMIT: + case DELIVERY_TIME: + case EXPIRY: + case REPLY_CHARGING_DEADLINE: + case PREVIOUSLY_SENT_DATE: + break; + default: + // This header value should not be LongInteger. + throw new RuntimeException("Invalid header field!"); + } + mHeaderMap.put(field, value); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java new file mode 100755 index 000000000000..f48399410723 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduParser.java @@ -0,0 +1,2023 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.ContentType; +import com.google.android.mms.InvalidHeaderValueException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.HashMap; + +public class PduParser { + /** + * The next are WAP values defined in WSP specification. + */ + private static final int QUOTE = 127; + private static final int LENGTH_QUOTE = 31; + private static final int TEXT_MIN = 32; + private static final int TEXT_MAX = 127; + private static final int SHORT_INTEGER_MAX = 127; + private static final int SHORT_LENGTH_MAX = 30; + private static final int LONG_INTEGER_LENGTH_MAX = 8; + private static final int QUOTED_STRING_FLAG = 34; + private static final int END_STRING_FLAG = 0x00; + //The next two are used by the interface "parseWapString" to + //distinguish Text-String and Quoted-String. + private static final int TYPE_TEXT_STRING = 0; + private static final int TYPE_QUOTED_STRING = 1; + private static final int TYPE_TOKEN_STRING = 2; + + /** + * Specify the part position. + */ + private static final int THE_FIRST_PART = 0; + private static final int THE_LAST_PART = 1; + + /** + * The pdu data. + */ + private ByteArrayInputStream mPduDataStream = null; + + /** + * Store pdu headers + */ + private PduHeaders mHeaders = null; + + /** + * Store pdu parts. + */ + private PduBody mBody = null; + + /** + * Store the "type" parameter in "Content-Type" header field. + */ + private static byte[] mTypeParam = null; + + /** + * Store the "start" parameter in "Content-Type" header field. + */ + private static byte[] mStartParam = null; + + /** + * The log tag. + */ + private static final String LOG_TAG = "PduParser"; + private static final boolean DEBUG = false; + private static final boolean LOCAL_LOGV = false; + + /** + * Whether to parse content-disposition part header + */ + private final boolean mParseContentDisposition; + + /** + * Constructor. + * + * @param pduDataStream pdu data to be parsed + * @param parseContentDisposition whether to parse the Content-Disposition part header + */ + @UnsupportedAppUsage + public PduParser(byte[] pduDataStream, boolean parseContentDisposition) { + mPduDataStream = new ByteArrayInputStream(pduDataStream); + mParseContentDisposition = parseContentDisposition; + } + + /** + * Parse the pdu. + * + * @return the pdu structure if parsing successfully. + * null if parsing error happened or mandatory fields are not set. + */ + @UnsupportedAppUsage + public GenericPdu parse(){ + if (mPduDataStream == null) { + return null; + } + + /* parse headers */ + mHeaders = parseHeaders(mPduDataStream); + if (null == mHeaders) { + // Parse headers failed. + return null; + } + + /* get the message type */ + int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE); + + /* check mandatory header fields */ + if (false == checkMandatoryHeader(mHeaders)) { + log("check mandatory headers failed!"); + return null; + } + + if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) || + (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) { + /* need to parse the parts */ + mBody = parseParts(mPduDataStream); + if (null == mBody) { + // Parse parts failed. + return null; + } + } + + switch (messageType) { + case PduHeaders.MESSAGE_TYPE_SEND_REQ: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_REQ"); + } + SendReq sendReq = new SendReq(mHeaders, mBody); + return sendReq; + case PduHeaders.MESSAGE_TYPE_SEND_CONF: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_CONF"); + } + SendConf sendConf = new SendConf(mHeaders); + return sendConf; + case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFICATION_IND"); + } + NotificationInd notificationInd = + new NotificationInd(mHeaders); + return notificationInd; + case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFYRESP_IND"); + } + NotifyRespInd notifyRespInd = + new NotifyRespInd(mHeaders); + return notifyRespInd; + case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF"); + } + RetrieveConf retrieveConf = + new RetrieveConf(mHeaders, mBody); + + byte[] contentType = retrieveConf.getContentType(); + if (null == contentType) { + return null; + } + String ctTypeStr = new String(contentType); + if (ctTypeStr.equals(ContentType.MULTIPART_MIXED) + || ctTypeStr.equals(ContentType.MULTIPART_RELATED) + || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) { + // The MMS content type must be "application/vnd.wap.multipart.mixed" + // or "application/vnd.wap.multipart.related" + // or "application/vnd.wap.multipart.alternative" + return retrieveConf; + } else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) { + // "application/vnd.wap.multipart.alternative" + // should take only the first part. + PduPart firstPart = mBody.getPart(0); + mBody.removeAll(); + mBody.addPart(0, firstPart); + return retrieveConf; + } + return null; + case PduHeaders.MESSAGE_TYPE_DELIVERY_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_DELIVERY_IND"); + } + DeliveryInd deliveryInd = + new DeliveryInd(mHeaders); + return deliveryInd; + case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_ACKNOWLEDGE_IND"); + } + AcknowledgeInd acknowledgeInd = + new AcknowledgeInd(mHeaders); + return acknowledgeInd; + case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_ORIG_IND"); + } + ReadOrigInd readOrigInd = + new ReadOrigInd(mHeaders); + return readOrigInd; + case PduHeaders.MESSAGE_TYPE_READ_REC_IND: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_REC_IND"); + } + ReadRecInd readRecInd = + new ReadRecInd(mHeaders); + return readRecInd; + default: + log("Parser doesn't support this message type in this version!"); + return null; + } + } + + /** + * Parse pdu headers. + * + * @param pduDataStream pdu data input stream + * @return headers in PduHeaders structure, null when parse fail + */ + protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream){ + if (pduDataStream == null) { + return null; + } + boolean keepParsing = true; + PduHeaders headers = new PduHeaders(); + + while (keepParsing && (pduDataStream.available() > 0)) { + pduDataStream.mark(1); + int headerField = extractByteValue(pduDataStream); + /* parse custom text header */ + if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) { + pduDataStream.reset(); + byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "TextHeader: " + new String(bVal)); + } + /* we should ignore it at the moment */ + continue; + } + switch (headerField) { + case PduHeaders.MESSAGE_TYPE: + { + int messageType = extractByteValue(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: messageType: " + messageType); + } + switch (messageType) { + // We don't support these kind of messages now. + case PduHeaders.MESSAGE_TYPE_FORWARD_REQ: + case PduHeaders.MESSAGE_TYPE_FORWARD_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_DESCR: + case PduHeaders.MESSAGE_TYPE_DELETE_REQ: + case PduHeaders.MESSAGE_TYPE_DELETE_CONF: + case PduHeaders.MESSAGE_TYPE_CANCEL_REQ: + case PduHeaders.MESSAGE_TYPE_CANCEL_CONF: + return null; + } + try { + headers.setOctet(messageType, headerField); + } catch(InvalidHeaderValueException e) { + log("Set invalid Octet value: " + messageType + + " into the header filed: " + headerField); + return null; + } catch(RuntimeException e) { + log(headerField + "is not Octet header field!"); + return null; + } + break; + } + /* Octect value */ + case PduHeaders.REPORT_ALLOWED: + case PduHeaders.ADAPTATION_ALLOWED: + case PduHeaders.DELIVERY_REPORT: + case PduHeaders.DRM_CONTENT: + case PduHeaders.DISTRIBUTION_INDICATOR: + case PduHeaders.QUOTAS: + case PduHeaders.READ_REPORT: + case PduHeaders.STORE: + case PduHeaders.STORED: + case PduHeaders.TOTALS: + case PduHeaders.SENDER_VISIBILITY: + case PduHeaders.READ_STATUS: + case PduHeaders.CANCEL_STATUS: + case PduHeaders.PRIORITY: + case PduHeaders.STATUS: + case PduHeaders.REPLY_CHARGING: + case PduHeaders.MM_STATE: + case PduHeaders.RECOMMENDED_RETRIEVAL_MODE: + case PduHeaders.CONTENT_CLASS: + case PduHeaders.RETRIEVE_STATUS: + case PduHeaders.STORE_STATUS: + /** + * The following field has a different value when + * used in the M-Mbox-Delete.conf and M-Delete.conf PDU. + * For now we ignore this fact, since we do not support these PDUs + */ + case PduHeaders.RESPONSE_STATUS: + { + int value = extractByteValue(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: byte: " + headerField + " value: " + + value); + } + + try { + headers.setOctet(value, headerField); + } catch(InvalidHeaderValueException e) { + log("Set invalid Octet value: " + value + + " into the header filed: " + headerField); + return null; + } catch(RuntimeException e) { + log(headerField + "is not Octet header field!"); + return null; + } + break; + } + + /* Long-Integer */ + case PduHeaders.DATE: + case PduHeaders.REPLY_CHARGING_SIZE: + case PduHeaders.MESSAGE_SIZE: + { + try { + long value = parseLongInteger(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: longint: " + headerField + " value: " + + value); + } + headers.setLongInteger(value, headerField); + } catch(RuntimeException e) { + log(headerField + "is not Long-Integer header field!"); + return null; + } + break; + } + + /* Integer-Value */ + case PduHeaders.MESSAGE_COUNT: + case PduHeaders.START: + case PduHeaders.LIMIT: + { + try { + long value = parseIntegerValue(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: int: " + headerField + " value: " + + value); + } + headers.setLongInteger(value, headerField); + } catch(RuntimeException e) { + log(headerField + "is not Long-Integer header field!"); + return null; + } + break; + } + + /* Text-String */ + case PduHeaders.TRANSACTION_ID: + case PduHeaders.REPLY_CHARGING_ID: + case PduHeaders.AUX_APPLIC_ID: + case PduHeaders.APPLIC_ID: + case PduHeaders.REPLY_APPLIC_ID: + /** + * The next three header fields are email addresses + * as defined in RFC2822, + * not including the characters "<" and ">" + */ + case PduHeaders.MESSAGE_ID: + case PduHeaders.REPLACE_ID: + case PduHeaders.CANCEL_ID: + /** + * The following field has a different value when + * used in the M-Mbox-Delete.conf and M-Delete.conf PDU. + * For now we ignore this fact, since we do not support these PDUs + */ + case PduHeaders.CONTENT_LOCATION: + { + byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if (null != value) { + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: string: " + headerField + " value: " + + new String(value)); + } + headers.setTextString(value, headerField); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Text-String header field!"); + return null; + } + } + break; + } + + /* Encoded-string-value */ + case PduHeaders.SUBJECT: + case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT: + case PduHeaders.RETRIEVE_TEXT: + case PduHeaders.STATUS_TEXT: + case PduHeaders.STORE_STATUS_TEXT: + /* the next one is not support + * M-Mbox-Delete.conf and M-Delete.conf now */ + case PduHeaders.RESPONSE_TEXT: + { + EncodedStringValue value = + parseEncodedStringValue(pduDataStream); + if (null != value) { + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: encoded string: " + headerField + + " value: " + value.getString()); + } + headers.setEncodedStringValue(value, headerField); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch (RuntimeException e) { + log(headerField + "is not Encoded-String-Value header field!"); + return null; + } + } + break; + } + + /* Addressing model */ + case PduHeaders.BCC: + case PduHeaders.CC: + case PduHeaders.TO: + { + EncodedStringValue value = + parseEncodedStringValue(pduDataStream); + if (null != value) { + byte[] address = value.getTextString(); + if (null != address) { + String str = new String(address); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: (to/cc/bcc) address: " + headerField + + " value: " + str); + } + int endIndex = str.indexOf("/"); + if (endIndex > 0) { + str = str.substring(0, endIndex); + } + try { + value.setTextString(str.getBytes()); + } catch(NullPointerException e) { + log("null pointer error!"); + return null; + } + } + + try { + headers.appendEncodedStringValue(value, headerField); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Encoded-String-Value header field!"); + return null; + } + } + break; + } + + /* Value-length + * (Absolute-token Date-value | Relative-token Delta-seconds-value) */ + case PduHeaders.DELIVERY_TIME: + case PduHeaders.EXPIRY: + case PduHeaders.REPLY_CHARGING_DEADLINE: + { + /* parse Value-length */ + parseValueLength(pduDataStream); + + /* Absolute-token or Relative-token */ + int token = extractByteValue(pduDataStream); + + /* Date-value or Delta-seconds-value */ + long timeValue; + try { + timeValue = parseLongInteger(pduDataStream); + } catch(RuntimeException e) { + log(headerField + "is not Long-Integer header field!"); + return null; + } + if (PduHeaders.VALUE_RELATIVE_TOKEN == token) { + /* need to convert the Delta-seconds-value + * into Date-value */ + timeValue = System.currentTimeMillis()/1000 + timeValue; + } + + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: time value: " + headerField + + " value: " + timeValue); + } + headers.setLongInteger(timeValue, headerField); + } catch(RuntimeException e) { + log(headerField + "is not Long-Integer header field!"); + return null; + } + break; + } + + case PduHeaders.FROM: { + /* From-value = + * Value-length + * (Address-present-token Encoded-string-value | Insert-address-token) + */ + EncodedStringValue from = null; + parseValueLength(pduDataStream); /* parse value-length */ + + /* Address-present-token or Insert-address-token */ + int fromToken = extractByteValue(pduDataStream); + + /* Address-present-token or Insert-address-token */ + if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) { + /* Encoded-string-value */ + from = parseEncodedStringValue(pduDataStream); + if (null != from) { + byte[] address = from.getTextString(); + if (null != address) { + String str = new String(address); + int endIndex = str.indexOf("/"); + if (endIndex > 0) { + str = str.substring(0, endIndex); + } + try { + from.setTextString(str.getBytes()); + } catch(NullPointerException e) { + log("null pointer error!"); + return null; + } + } + } + } else { + try { + from = new EncodedStringValue( + PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()); + } catch(NullPointerException e) { + log(headerField + "is not Encoded-String-Value header field!"); + return null; + } + } + + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: from address: " + headerField + + " value: " + from.getString()); + } + headers.setEncodedStringValue(from, PduHeaders.FROM); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Encoded-String-Value header field!"); + return null; + } + break; + } + + case PduHeaders.MESSAGE_CLASS: { + /* Message-class-value = Class-identifier | Token-text */ + pduDataStream.mark(1); + int messageClass = extractByteValue(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: MESSAGE_CLASS: " + headerField + + " value: " + messageClass); + } + + if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) { + /* Class-identifier */ + try { + if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) { + headers.setTextString( + PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(), + PduHeaders.MESSAGE_CLASS); + } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) { + headers.setTextString( + PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(), + PduHeaders.MESSAGE_CLASS); + } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) { + headers.setTextString( + PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(), + PduHeaders.MESSAGE_CLASS); + } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) { + headers.setTextString( + PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(), + PduHeaders.MESSAGE_CLASS); + } + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Text-String header field!"); + return null; + } + } else { + /* Token-text */ + pduDataStream.reset(); + byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if (null != messageClassString) { + try { + headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Text-String header field!"); + return null; + } + } + } + break; + } + + case PduHeaders.MMS_VERSION: { + int version = parseShortInteger(pduDataStream); + + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: MMS_VERSION: " + headerField + + " value: " + version); + } + headers.setOctet(version, PduHeaders.MMS_VERSION); + } catch(InvalidHeaderValueException e) { + log("Set invalid Octet value: " + version + + " into the header filed: " + headerField); + return null; + } catch(RuntimeException e) { + log(headerField + "is not Octet header field!"); + return null; + } + break; + } + + case PduHeaders.PREVIOUSLY_SENT_BY: { + /* Previously-sent-by-value = + * Value-length Forwarded-count-value Encoded-string-value */ + /* parse value-length */ + parseValueLength(pduDataStream); + + /* parse Forwarded-count-value */ + try { + parseIntegerValue(pduDataStream); + } catch(RuntimeException e) { + log(headerField + " is not Integer-Value"); + return null; + } + + /* parse Encoded-string-value */ + EncodedStringValue previouslySentBy = + parseEncodedStringValue(pduDataStream); + if (null != previouslySentBy) { + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_BY: " + headerField + + " value: " + previouslySentBy.getString()); + } + headers.setEncodedStringValue(previouslySentBy, + PduHeaders.PREVIOUSLY_SENT_BY); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Encoded-String-Value header field!"); + return null; + } + } + break; + } + + case PduHeaders.PREVIOUSLY_SENT_DATE: { + /* Previously-sent-date-value = + * Value-length Forwarded-count-value Date-value */ + /* parse value-length */ + parseValueLength(pduDataStream); + + /* parse Forwarded-count-value */ + try { + parseIntegerValue(pduDataStream); + } catch(RuntimeException e) { + log(headerField + " is not Integer-Value"); + return null; + } + + /* Date-value */ + try { + long perviouslySentDate = parseLongInteger(pduDataStream); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_DATE: " + headerField + + " value: " + perviouslySentDate); + } + headers.setLongInteger(perviouslySentDate, + PduHeaders.PREVIOUSLY_SENT_DATE); + } catch(RuntimeException e) { + log(headerField + "is not Long-Integer header field!"); + return null; + } + break; + } + + case PduHeaders.MM_FLAGS: { + /* MM-flags-value = + * Value-length + * ( Add-token | Remove-token | Filter-token ) + * Encoded-string-value + */ + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: MM_FLAGS: " + headerField + + " NOT REALLY SUPPORTED"); + } + + /* parse Value-length */ + parseValueLength(pduDataStream); + + /* Add-token | Remove-token | Filter-token */ + extractByteValue(pduDataStream); + + /* Encoded-string-value */ + parseEncodedStringValue(pduDataStream); + + /* not store this header filed in "headers", + * because now PduHeaders doesn't support it */ + break; + } + + /* Value-length + * (Message-total-token | Size-total-token) Integer-Value */ + case PduHeaders.MBOX_TOTALS: + case PduHeaders.MBOX_QUOTAS: + { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: MBOX_TOTALS: " + headerField); + } + /* Value-length */ + parseValueLength(pduDataStream); + + /* Message-total-token | Size-total-token */ + extractByteValue(pduDataStream); + + /*Integer-Value*/ + try { + parseIntegerValue(pduDataStream); + } catch(RuntimeException e) { + log(headerField + " is not Integer-Value"); + return null; + } + + /* not store these headers filed in "headers", + because now PduHeaders doesn't support them */ + break; + } + + case PduHeaders.ELEMENT_DESCRIPTOR: { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: ELEMENT_DESCRIPTOR: " + headerField); + } + parseContentType(pduDataStream, null); + + /* not store this header filed in "headers", + because now PduHeaders doesn't support it */ + break; + } + + case PduHeaders.CONTENT_TYPE: { + HashMap<Integer, Object> map = + new HashMap<Integer, Object>(); + byte[] contentType = + parseContentType(pduDataStream, map); + + if (null != contentType) { + try { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: CONTENT_TYPE: " + headerField + + contentType.toString()); + } + headers.setTextString(contentType, PduHeaders.CONTENT_TYPE); + } catch(NullPointerException e) { + log("null pointer error!"); + } catch(RuntimeException e) { + log(headerField + "is not Text-String header field!"); + return null; + } + } + + /* get start parameter */ + mStartParam = (byte[]) map.get(PduPart.P_START); + + /* get charset parameter */ + mTypeParam= (byte[]) map.get(PduPart.P_TYPE); + + keepParsing = false; + break; + } + + case PduHeaders.CONTENT: + case PduHeaders.ADDITIONAL_HEADERS: + case PduHeaders.ATTRIBUTES: + default: { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "parseHeaders: Unknown header: " + headerField); + } + log("Unknown header"); + } + } + } + + return headers; + } + + /** + * Parse pdu parts. + * + * @param pduDataStream pdu data input stream + * @return parts in PduBody structure + */ + protected PduBody parseParts(ByteArrayInputStream pduDataStream) { + if (pduDataStream == null) { + return null; + } + + int count = parseUnsignedInt(pduDataStream); // get the number of parts + PduBody body = new PduBody(); + + for (int i = 0 ; i < count ; i++) { + int headerLength = parseUnsignedInt(pduDataStream); + int dataLength = parseUnsignedInt(pduDataStream); + PduPart part = new PduPart(); + int startPos = pduDataStream.available(); + if (startPos <= 0) { + // Invalid part. + return null; + } + + /* parse part's content-type */ + HashMap<Integer, Object> map = new HashMap<Integer, Object>(); + byte[] contentType = parseContentType(pduDataStream, map); + if (null != contentType) { + part.setContentType(contentType); + } else { + part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*" + } + + /* get name parameter */ + byte[] name = (byte[]) map.get(PduPart.P_NAME); + if (null != name) { + part.setName(name); + } + + /* get charset parameter */ + Integer charset = (Integer) map.get(PduPart.P_CHARSET); + if (null != charset) { + part.setCharset(charset); + } + + /* parse part's headers */ + int endPos = pduDataStream.available(); + int partHeaderLen = headerLength - (startPos - endPos); + if (partHeaderLen > 0) { + if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) { + // Parse part header faild. + return null; + } + } else if (partHeaderLen < 0) { + // Invalid length of content-type. + return null; + } + + /* FIXME: check content-id, name, filename and content location, + * if not set anyone of them, generate a default content-location + */ + if ((null == part.getContentLocation()) + && (null == part.getName()) + && (null == part.getFilename()) + && (null == part.getContentId())) { + part.setContentLocation(Long.toOctalString( + System.currentTimeMillis()).getBytes()); + } + + /* get part's data */ + if (dataLength > 0) { + byte[] partData = new byte[dataLength]; + String partContentType = new String(part.getContentType()); + pduDataStream.read(partData, 0, dataLength); + if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) { + // parse "multipart/vnd.wap.multipart.alternative". + PduBody childBody = parseParts(new ByteArrayInputStream(partData)); + // take the first part of children. + part = childBody.getPart(0); + } else { + // Check Content-Transfer-Encoding. + byte[] partDataEncoding = part.getContentTransferEncoding(); + if (null != partDataEncoding) { + String encoding = new String(partDataEncoding); + if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) { + // Decode "base64" into "binary". + partData = Base64.decodeBase64(partData); + } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) { + // Decode "quoted-printable" into "binary". + partData = QuotedPrintable.decodeQuotedPrintable(partData); + } else { + // "binary" is the default encoding. + } + } + if (null == partData) { + log("Decode part data error!"); + return null; + } + part.setData(partData); + } + } + + /* add this part to body */ + if (THE_FIRST_PART == checkPartPosition(part)) { + /* this is the first part */ + body.addPart(0, part); + } else { + /* add the part to the end */ + body.addPart(part); + } + } + + return body; + } + + /** + * Log status. + * + * @param text log information + */ + @UnsupportedAppUsage + private static void log(String text) { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, text); + } + } + + /** + * Parse unsigned integer. + * + * @param pduDataStream pdu data input stream + * @return the integer, -1 when failed + */ + @UnsupportedAppUsage + protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) { + /** + * From wap-230-wsp-20010705-a.pdf + * The maximum size of a uintvar is 32 bits. + * So it will be encoded in no more than 5 octets. + */ + assert(null != pduDataStream); + int result = 0; + int temp = pduDataStream.read(); + if (temp == -1) { + return temp; + } + + while((temp & 0x80) != 0) { + result = result << 7; + result |= temp & 0x7F; + temp = pduDataStream.read(); + if (temp == -1) { + return temp; + } + } + + result = result << 7; + result |= temp & 0x7F; + + return result; + } + + /** + * Parse value length. + * + * @param pduDataStream pdu data input stream + * @return the integer + */ + @UnsupportedAppUsage + protected static int parseValueLength(ByteArrayInputStream pduDataStream) { + /** + * From wap-230-wsp-20010705-a.pdf + * Value-length = Short-length | (Length-quote Length) + * Short-length = <Any octet 0-30> + * Length-quote = <Octet 31> + * Length = Uintvar-integer + * Uintvar-integer = 1*5 OCTET + */ + assert(null != pduDataStream); + int temp = pduDataStream.read(); + assert(-1 != temp); + int first = temp & 0xFF; + + if (first <= SHORT_LENGTH_MAX) { + return first; + } else if (first == LENGTH_QUOTE) { + return parseUnsignedInt(pduDataStream); + } + + throw new RuntimeException ("Value length > LENGTH_QUOTE!"); + } + + /** + * Parse encoded string value. + * + * @param pduDataStream pdu data input stream + * @return the EncodedStringValue + */ + protected static EncodedStringValue parseEncodedStringValue(ByteArrayInputStream pduDataStream){ + /** + * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf + * Encoded-string-value = Text-string | Value-length Char-set Text-string + */ + assert(null != pduDataStream); + pduDataStream.mark(1); + EncodedStringValue returnValue = null; + int charset = 0; + int temp = pduDataStream.read(); + assert(-1 != temp); + int first = temp & 0xFF; + if (first == 0) { + return new EncodedStringValue(""); + } + + pduDataStream.reset(); + if (first < TEXT_MIN) { + parseValueLength(pduDataStream); + + charset = parseShortInteger(pduDataStream); //get the "Charset" + } + + byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING); + + try { + if (0 != charset) { + returnValue = new EncodedStringValue(charset, textString); + } else { + returnValue = new EncodedStringValue(textString); + } + } catch(Exception e) { + return null; + } + + return returnValue; + } + + /** + * Parse Text-String or Quoted-String. + * + * @param pduDataStream pdu data input stream + * @param stringType TYPE_TEXT_STRING or TYPE_QUOTED_STRING + * @return the string without End-of-string in byte array + */ + @UnsupportedAppUsage + protected static byte[] parseWapString(ByteArrayInputStream pduDataStream, + int stringType) { + assert(null != pduDataStream); + /** + * From wap-230-wsp-20010705-a.pdf + * Text-string = [Quote] *TEXT End-of-string + * If the first character in the TEXT is in the range of 128-255, + * a Quote character must precede it. + * Otherwise the Quote character must be omitted. + * The Quote is not part of the contents. + * Quote = <Octet 127> + * End-of-string = <Octet 0> + * + * Quoted-string = <Octet 34> *TEXT End-of-string + * + * Token-text = Token End-of-string + */ + + // Mark supposed beginning of Text-string + // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG + pduDataStream.mark(1); + + // Check first char + int temp = pduDataStream.read(); + assert(-1 != temp); + if ((TYPE_QUOTED_STRING == stringType) && + (QUOTED_STRING_FLAG == temp)) { + // Mark again if QUOTED_STRING_FLAG and ignore it + pduDataStream.mark(1); + } else if ((TYPE_TEXT_STRING == stringType) && + (QUOTE == temp)) { + // Mark again if QUOTE and ignore it + pduDataStream.mark(1); + } else { + // Otherwise go back to origin + pduDataStream.reset(); + } + + // We are now definitely at the beginning of string + /** + * Return *TOKEN or *TEXT (Text-String without QUOTE, + * Quoted-String without QUOTED_STRING_FLAG and without End-of-string) + */ + return getWapString(pduDataStream, stringType); + } + + /** + * Check TOKEN data defined in RFC2616. + * @param ch checking data + * @return true when ch is TOKEN, false when ch is not TOKEN + */ + protected static boolean isTokenCharacter(int ch) { + /** + * Token = 1*<any CHAR except CTLs or separators> + * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64) + * | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34) + * | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61) + * | "{"(123) | "}"(125) | SP(32) | HT(9) + * CHAR = <any US-ASCII character (octets 0 - 127)> + * CTL = <any US-ASCII control character + * (octets 0 - 31) and DEL (127)> + * SP = <US-ASCII SP, space (32)> + * HT = <US-ASCII HT, horizontal-tab (9)> + */ + if((ch < 33) || (ch > 126)) { + return false; + } + + switch(ch) { + case '"': /* '"' */ + case '(': /* '(' */ + case ')': /* ')' */ + case ',': /* ',' */ + case '/': /* '/' */ + case ':': /* ':' */ + case ';': /* ';' */ + case '<': /* '<' */ + case '=': /* '=' */ + case '>': /* '>' */ + case '?': /* '?' */ + case '@': /* '@' */ + case '[': /* '[' */ + case '\\': /* '\' */ + case ']': /* ']' */ + case '{': /* '{' */ + case '}': /* '}' */ + return false; + } + + return true; + } + + /** + * Check TEXT data defined in RFC2616. + * @param ch checking data + * @return true when ch is TEXT, false when ch is not TEXT + */ + protected static boolean isText(int ch) { + /** + * TEXT = <any OCTET except CTLs, + * but including LWS> + * CTL = <any US-ASCII control character + * (octets 0 - 31) and DEL (127)> + * LWS = [CRLF] 1*( SP | HT ) + * CRLF = CR LF + * CR = <US-ASCII CR, carriage return (13)> + * LF = <US-ASCII LF, linefeed (10)> + */ + if(((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) { + return true; + } + + switch(ch) { + case '\t': /* '\t' */ + case '\n': /* '\n' */ + case '\r': /* '\r' */ + return true; + } + + return false; + } + + protected static byte[] getWapString(ByteArrayInputStream pduDataStream, + int stringType) { + assert(null != pduDataStream); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int temp = pduDataStream.read(); + assert(-1 != temp); + while((-1 != temp) && ('\0' != temp)) { + // check each of the character + if (stringType == TYPE_TOKEN_STRING) { + if (isTokenCharacter(temp)) { + out.write(temp); + } + } else { + if (isText(temp)) { + out.write(temp); + } + } + + temp = pduDataStream.read(); + assert(-1 != temp); + } + + if (out.size() > 0) { + return out.toByteArray(); + } + + return null; + } + + /** + * Extract a byte value from the input stream. + * + * @param pduDataStream pdu data input stream + * @return the byte + */ + protected static int extractByteValue(ByteArrayInputStream pduDataStream) { + assert(null != pduDataStream); + int temp = pduDataStream.read(); + assert(-1 != temp); + return temp & 0xFF; + } + + /** + * Parse Short-Integer. + * + * @param pduDataStream pdu data input stream + * @return the byte + */ + @UnsupportedAppUsage + protected static int parseShortInteger(ByteArrayInputStream pduDataStream) { + /** + * From wap-230-wsp-20010705-a.pdf + * Short-integer = OCTET + * Integers in range 0-127 shall be encoded as a one + * octet value with the most significant bit set to one (1xxx xxxx) + * and with the value in the remaining least significant bits. + */ + assert(null != pduDataStream); + int temp = pduDataStream.read(); + assert(-1 != temp); + return temp & 0x7F; + } + + /** + * Parse Long-Integer. + * + * @param pduDataStream pdu data input stream + * @return long integer + */ + protected static long parseLongInteger(ByteArrayInputStream pduDataStream) { + /** + * From wap-230-wsp-20010705-a.pdf + * Long-integer = Short-length Multi-octet-integer + * The Short-length indicates the length of the Multi-octet-integer + * Multi-octet-integer = 1*30 OCTET + * The content octets shall be an unsigned integer value + * with the most significant octet encoded first (big-endian representation). + * The minimum number of octets must be used to encode the value. + * Short-length = <Any octet 0-30> + */ + assert(null != pduDataStream); + int temp = pduDataStream.read(); + assert(-1 != temp); + int count = temp & 0xFF; + + if (count > LONG_INTEGER_LENGTH_MAX) { + throw new RuntimeException("Octet count greater than 8 and I can't represent that!"); + } + + long result = 0; + + for (int i = 0 ; i < count ; i++) { + temp = pduDataStream.read(); + assert(-1 != temp); + result <<= 8; + result += (temp & 0xFF); + } + + return result; + } + + /** + * Parse Integer-Value. + * + * @param pduDataStream pdu data input stream + * @return long integer + */ + protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) { + /** + * From wap-230-wsp-20010705-a.pdf + * Integer-Value = Short-integer | Long-integer + */ + assert(null != pduDataStream); + pduDataStream.mark(1); + int temp = pduDataStream.read(); + assert(-1 != temp); + pduDataStream.reset(); + if (temp > SHORT_INTEGER_MAX) { + return parseShortInteger(pduDataStream); + } else { + return parseLongInteger(pduDataStream); + } + } + + /** + * To skip length of the wap value. + * + * @param pduDataStream pdu data input stream + * @param length area size + * @return the values in this area + */ + protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) { + assert(null != pduDataStream); + byte[] area = new byte[length]; + int readLen = pduDataStream.read(area, 0, length); + if (readLen < length) { //The actually read length is lower than the length + return -1; + } else { + return readLen; + } + } + + /** + * Parse content type parameters. For now we just support + * four parameters used in mms: "type", "start", "name", "charset". + * + * @param pduDataStream pdu data input stream + * @param map to store parameters of Content-Type field + * @param length length of all the parameters + */ + protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream, + HashMap<Integer, Object> map, Integer length) { + /** + * From wap-230-wsp-20010705-a.pdf + * Parameter = Typed-parameter | Untyped-parameter + * Typed-parameter = Well-known-parameter-token Typed-value + * the actual expected type of the value is implied by the well-known parameter + * Well-known-parameter-token = Integer-value + * the code values used for parameters are specified in the Assigned Numbers appendix + * Typed-value = Compact-value | Text-value + * In addition to the expected type, there may be no value. + * If the value cannot be encoded using the expected type, it shall be encoded as text. + * Compact-value = Integer-value | + * Date-value | Delta-seconds-value | Q-value | Version-value | + * Uri-value + * Untyped-parameter = Token-text Untyped-value + * the type of the value is unknown, but it shall be encoded as an integer, + * if that is possible. + * Untyped-value = Integer-value | Text-value + */ + assert(null != pduDataStream); + assert(length > 0); + + int startPos = pduDataStream.available(); + int tempPos = 0; + int lastLen = length; + while(0 < lastLen) { + int param = pduDataStream.read(); + assert(-1 != param); + lastLen--; + + switch (param) { + /** + * From rfc2387, chapter 3.1 + * The type parameter must be specified and its value is the MIME media + * type of the "root" body part. It permits a MIME user agent to + * determine the content-type without reference to the enclosed body + * part. If the value of the type parameter and the root body part's + * content-type differ then the User Agent's behavior is undefined. + * + * From wap-230-wsp-20010705-a.pdf + * type = Constrained-encoding + * Constrained-encoding = Extension-Media | Short-integer + * Extension-media = *TEXT End-of-string + */ + case PduPart.P_TYPE: + case PduPart.P_CT_MR_TYPE: + pduDataStream.mark(1); + int first = extractByteValue(pduDataStream); + pduDataStream.reset(); + if (first > TEXT_MAX) { + // Short-integer (well-known type) + int index = parseShortInteger(pduDataStream); + + if (index < PduContentTypes.contentTypes.length) { + byte[] type = (PduContentTypes.contentTypes[index]).getBytes(); + map.put(PduPart.P_TYPE, type); + } else { + //not support this type, ignore it. + } + } else { + // Text-String (extension-media) + byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if ((null != type) && (null != map)) { + map.put(PduPart.P_TYPE, type); + } + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + + /** + * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3. + * Start Parameter Referring to Presentation + * + * From rfc2387, chapter 3.2 + * The start parameter, if given, is the content-ID of the compound + * object's "root". If not present the "root" is the first body part in + * the Multipart/Related entity. The "root" is the element the + * applications processes first. + * + * From wap-230-wsp-20010705-a.pdf + * start = Text-String + */ + case PduPart.P_START: + case PduPart.P_DEP_START: + byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if ((null != start) && (null != map)) { + map.put(PduPart.P_START, start); + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + + /** + * From oma-ts-mms-conf-v1_3.pdf + * In creation, the character set SHALL be either us-ascii + * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode]. + * In retrieval, both us-ascii and utf-8 SHALL be supported. + * + * From wap-230-wsp-20010705-a.pdf + * charset = Well-known-charset|Text-String + * Well-known-charset = Any-charset | Integer-value + * Both are encoded using values from Character Set + * Assignments table in Assigned Numbers + * Any-charset = <Octet 128> + * Equivalent to the special RFC2616 charset value "*" + */ + case PduPart.P_CHARSET: + pduDataStream.mark(1); + int firstValue = extractByteValue(pduDataStream); + pduDataStream.reset(); + //Check first char + if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) || + (END_STRING_FLAG == firstValue)) { + //Text-String (extension-charset) + byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING); + try { + int charsetInt = CharacterSets.getMibEnumValue( + new String(charsetStr)); + map.put(PduPart.P_CHARSET, charsetInt); + } catch (UnsupportedEncodingException e) { + // Not a well-known charset, use "*". + Log.e(LOG_TAG, Arrays.toString(charsetStr), e); + map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET); + } + } else { + //Well-known-charset + int charset = (int) parseIntegerValue(pduDataStream); + if (map != null) { + map.put(PduPart.P_CHARSET, charset); + } + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + + /** + * From oma-ts-mms-conf-v1_3.pdf + * A name for multipart object SHALL be encoded using name-parameter + * for Content-Type header in WSP multipart headers. + * + * From wap-230-wsp-20010705-a.pdf + * name = Text-String + */ + case PduPart.P_DEP_NAME: + case PduPart.P_NAME: + byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if ((null != name) && (null != map)) { + map.put(PduPart.P_NAME, name); + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + default: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "Not supported Content-Type parameter"); + } + if (-1 == skipWapValue(pduDataStream, lastLen)) { + Log.e(LOG_TAG, "Corrupt Content-Type"); + } else { + lastLen = 0; + } + break; + } + } + + if (0 != lastLen) { + Log.e(LOG_TAG, "Corrupt Content-Type"); + } + } + + /** + * Parse content type. + * + * @param pduDataStream pdu data input stream + * @param map to store parameters in Content-Type header field + * @return Content-Type value + */ + @UnsupportedAppUsage + protected static byte[] parseContentType(ByteArrayInputStream pduDataStream, + HashMap<Integer, Object> map) { + /** + * From wap-230-wsp-20010705-a.pdf + * Content-type-value = Constrained-media | Content-general-form + * Content-general-form = Value-length Media-type + * Media-type = (Well-known-media | Extension-Media) *(Parameter) + */ + assert(null != pduDataStream); + + byte[] contentType = null; + pduDataStream.mark(1); + int temp = pduDataStream.read(); + assert(-1 != temp); + pduDataStream.reset(); + + int cur = (temp & 0xFF); + + if (cur < TEXT_MIN) { + int length = parseValueLength(pduDataStream); + int startPos = pduDataStream.available(); + pduDataStream.mark(1); + temp = pduDataStream.read(); + assert(-1 != temp); + pduDataStream.reset(); + int first = (temp & 0xFF); + + if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) { + contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING); + } else if (first > TEXT_MAX) { + int index = parseShortInteger(pduDataStream); + + if (index < PduContentTypes.contentTypes.length) { //well-known type + contentType = (PduContentTypes.contentTypes[index]).getBytes(); + } else { + pduDataStream.reset(); + contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING); + } + } else { + Log.e(LOG_TAG, "Corrupt content-type"); + return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*" + } + + int endPos = pduDataStream.available(); + int parameterLen = length - (startPos - endPos); + if (parameterLen > 0) {//have parameters + parseContentTypeParams(pduDataStream, map, parameterLen); + } + + if (parameterLen < 0) { + Log.e(LOG_TAG, "Corrupt MMS message"); + return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*" + } + } else if (cur <= TEXT_MAX) { + contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING); + } else { + contentType = + (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes(); + } + + return contentType; + } + + /** + * Parse part's headers. + * + * @param pduDataStream pdu data input stream + * @param part to store the header informations of the part + * @param length length of the headers + * @return true if parse successfully, false otherwise + */ + @UnsupportedAppUsage + protected boolean parsePartHeaders(ByteArrayInputStream pduDataStream, + PduPart part, int length) { + assert(null != pduDataStream); + assert(null != part); + assert(length > 0); + + /** + * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2. + * A name for multipart object SHALL be encoded using name-parameter + * for Content-Type header in WSP multipart headers. + * In decoding, name-parameter of Content-Type SHALL be used if available. + * If name-parameter of Content-Type is not available, + * filename parameter of Content-Disposition header SHALL be used if available. + * If neither name-parameter of Content-Type header nor filename parameter + * of Content-Disposition header is available, + * Content-Location header SHALL be used if available. + * + * Within SMIL part the reference to the media object parts SHALL use + * either Content-ID or Content-Location mechanism [RFC2557] + * and the corresponding WSP part headers in media object parts + * contain the corresponding definitions. + */ + int startPos = pduDataStream.available(); + int tempPos = 0; + int lastLen = length; + while(0 < lastLen) { + int header = pduDataStream.read(); + assert(-1 != header); + lastLen--; + + if (header > TEXT_MAX) { + // Number assigned headers. + switch (header) { + case PduPart.P_CONTENT_LOCATION: + /** + * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21 + * Content-location-value = Uri-value + */ + byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if (null != contentLocation) { + part.setContentLocation(contentLocation); + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + case PduPart.P_CONTENT_ID: + /** + * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21 + * Content-ID-value = Quoted-string + */ + byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING); + if (null != contentId) { + part.setContentId(contentId); + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + break; + case PduPart.P_DEP_CONTENT_DISPOSITION: + case PduPart.P_CONTENT_DISPOSITION: + /** + * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21 + * Content-disposition-value = Value-length Disposition *(Parameter) + * Disposition = Form-data | Attachment | Inline | Token-text + * Form-data = <Octet 128> + * Attachment = <Octet 129> + * Inline = <Octet 130> + */ + + /* + * some carrier mmsc servers do not support content_disposition + * field correctly + */ + if (mParseContentDisposition) { + int len = parseValueLength(pduDataStream); + pduDataStream.mark(1); + int thisStartPos = pduDataStream.available(); + int thisEndPos = 0; + int value = pduDataStream.read(); + + if (value == PduPart.P_DISPOSITION_FROM_DATA ) { + part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA); + } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) { + part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT); + } else if (value == PduPart.P_DISPOSITION_INLINE) { + part.setContentDisposition(PduPart.DISPOSITION_INLINE); + } else { + pduDataStream.reset(); + /* Token-text */ + part.setContentDisposition(parseWapString(pduDataStream + , TYPE_TEXT_STRING)); + } + + /* get filename parameter and skip other parameters */ + thisEndPos = pduDataStream.available(); + if (thisStartPos - thisEndPos < len) { + value = pduDataStream.read(); + if (value == PduPart.P_FILENAME) { //filename is text-string + part.setFilename(parseWapString(pduDataStream + , TYPE_TEXT_STRING)); + } + + /* skip other parameters */ + thisEndPos = pduDataStream.available(); + if (thisStartPos - thisEndPos < len) { + int last = len - (thisStartPos - thisEndPos); + byte[] temp = new byte[last]; + pduDataStream.read(temp, 0, last); + } + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + } + break; + default: + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "Not supported Part headers: " + header); + } + if (-1 == skipWapValue(pduDataStream, lastLen)) { + Log.e(LOG_TAG, "Corrupt Part headers"); + return false; + } + lastLen = 0; + break; + } + } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) { + // Not assigned header. + byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING); + byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING); + + // Check the header whether it is "Content-Transfer-Encoding". + if (true == + PduPart.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(new String(tempHeader))) { + part.setContentTransferEncoding(tempValue); + } + + tempPos = pduDataStream.available(); + lastLen = length - (startPos - tempPos); + } else { + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "Not supported Part headers: " + header); + } + // Skip all headers of this part. + if (-1 == skipWapValue(pduDataStream, lastLen)) { + Log.e(LOG_TAG, "Corrupt Part headers"); + return false; + } + lastLen = 0; + } + } + + if (0 != lastLen) { + Log.e(LOG_TAG, "Corrupt Part headers"); + return false; + } + + return true; + } + + /** + * Check the position of a specified part. + * + * @param part the part to be checked + * @return part position, THE_FIRST_PART when it's the + * first one, THE_LAST_PART when it's the last one. + */ + @UnsupportedAppUsage + private static int checkPartPosition(PduPart part) { + assert(null != part); + if ((null == mTypeParam) && + (null == mStartParam)) { + return THE_LAST_PART; + } + + /* check part's content-id */ + if (null != mStartParam) { + byte[] contentId = part.getContentId(); + if (null != contentId) { + if (true == Arrays.equals(mStartParam, contentId)) { + return THE_FIRST_PART; + } + } + // This is not the first part, so append to end (keeping the original order) + // Check b/19607294 for details of this change + return THE_LAST_PART; + } + + /* check part's content-type */ + if (null != mTypeParam) { + byte[] contentType = part.getContentType(); + if (null != contentType) { + if (true == Arrays.equals(mTypeParam, contentType)) { + return THE_FIRST_PART; + } + } + } + + return THE_LAST_PART; + } + + /** + * Check mandatory headers of a pdu. + * + * @param headers pdu headers + * @return true if the pdu has all of the mandatory headers, false otherwise. + */ + protected static boolean checkMandatoryHeader(PduHeaders headers) { + if (null == headers) { + return false; + } + + /* get message type */ + int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE); + + /* check Mms-Version field */ + int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION); + if (0 == mmsVersion) { + // Every message should have Mms-Version field. + return false; + } + + /* check mandatory header fields */ + switch (messageType) { + case PduHeaders.MESSAGE_TYPE_SEND_REQ: + // Content-Type field. + byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE); + if (null == srContentType) { + return false; + } + + // From field. + EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM); + if (null == srFrom) { + return false; + } + + // Transaction-Id field. + byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID); + if (null == srTransactionId) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_SEND_CONF: + // Response-Status field. + int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS); + if (0 == scResponseStatus) { + return false; + } + + // Transaction-Id field. + byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID); + if (null == scTransactionId) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: + // Content-Location field. + byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION); + if (null == niContentLocation) { + return false; + } + + // Expiry field. + long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY); + if (-1 == niExpiry) { + return false; + } + + // Message-Class field. + byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS); + if (null == niMessageClass) { + return false; + } + + // Message-Size field. + long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE); + if (-1 == niMessageSize) { + return false; + } + + // Transaction-Id field. + byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID); + if (null == niTransactionId) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND: + // Status field. + int nriStatus = headers.getOctet(PduHeaders.STATUS); + if (0 == nriStatus) { + return false; + } + + // Transaction-Id field. + byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID); + if (null == nriTransactionId) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: + // Content-Type field. + byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE); + if (null == rcContentType) { + return false; + } + + // Date field. + long rcDate = headers.getLongInteger(PduHeaders.DATE); + if (-1 == rcDate) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_DELIVERY_IND: + // Date field. + long diDate = headers.getLongInteger(PduHeaders.DATE); + if (-1 == diDate) { + return false; + } + + // Message-Id field. + byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID); + if (null == diMessageId) { + return false; + } + + // Status field. + int diStatus = headers.getOctet(PduHeaders.STATUS); + if (0 == diStatus) { + return false; + } + + // To field. + EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO); + if (null == diTo) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND: + // Transaction-Id field. + byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID); + if (null == aiTransactionId) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND: + // Date field. + long roDate = headers.getLongInteger(PduHeaders.DATE); + if (-1 == roDate) { + return false; + } + + // From field. + EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM); + if (null == roFrom) { + return false; + } + + // Message-Id field. + byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID); + if (null == roMessageId) { + return false; + } + + // Read-Status field. + int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS); + if (0 == roReadStatus) { + return false; + } + + // To field. + EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO); + if (null == roTo) { + return false; + } + + break; + case PduHeaders.MESSAGE_TYPE_READ_REC_IND: + // From field. + EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM); + if (null == rrFrom) { + return false; + } + + // Message-Id field. + byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID); + if (null == rrMessageId) { + return false; + } + + // Read-Status field. + int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS); + if (0 == rrReadStatus) { + return false; + } + + // To field. + EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO); + if (null == rrTo) { + return false; + } + + break; + default: + // Parser doesn't support this message type in this version. + return false; + } + + return true; + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduPart.java b/telephony/common/com/google/android/mms/pdu/PduPart.java new file mode 100644 index 000000000000..09b775118dc3 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduPart.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.net.Uri; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.util.HashMap; +import java.util.Map; + +/** + * The pdu part. + */ +public class PduPart { + /** + * Well-Known Parameters. + */ + public static final int P_Q = 0x80; + public static final int P_CHARSET = 0x81; + public static final int P_LEVEL = 0x82; + public static final int P_TYPE = 0x83; + public static final int P_DEP_NAME = 0x85; + public static final int P_DEP_FILENAME = 0x86; + public static final int P_DIFFERENCES = 0x87; + public static final int P_PADDING = 0x88; + // This value of "TYPE" s used with Content-Type: multipart/related + public static final int P_CT_MR_TYPE = 0x89; + public static final int P_DEP_START = 0x8A; + public static final int P_DEP_START_INFO = 0x8B; + public static final int P_DEP_COMMENT = 0x8C; + public static final int P_DEP_DOMAIN = 0x8D; + public static final int P_MAX_AGE = 0x8E; + public static final int P_DEP_PATH = 0x8F; + public static final int P_SECURE = 0x90; + public static final int P_SEC = 0x91; + public static final int P_MAC = 0x92; + public static final int P_CREATION_DATE = 0x93; + public static final int P_MODIFICATION_DATE = 0x94; + public static final int P_READ_DATE = 0x95; + public static final int P_SIZE = 0x96; + public static final int P_NAME = 0x97; + public static final int P_FILENAME = 0x98; + public static final int P_START = 0x99; + public static final int P_START_INFO = 0x9A; + public static final int P_COMMENT = 0x9B; + public static final int P_DOMAIN = 0x9C; + public static final int P_PATH = 0x9D; + + /** + * Header field names. + */ + public static final int P_CONTENT_TYPE = 0x91; + public static final int P_CONTENT_LOCATION = 0x8E; + public static final int P_CONTENT_ID = 0xC0; + public static final int P_DEP_CONTENT_DISPOSITION = 0xAE; + public static final int P_CONTENT_DISPOSITION = 0xC5; + // The next header is unassigned header, use reserved header(0x48) value. + public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8; + + /** + * Content=Transfer-Encoding string. + */ + public static final String CONTENT_TRANSFER_ENCODING = + "Content-Transfer-Encoding"; + + /** + * Value of Content-Transfer-Encoding. + */ + public static final String P_BINARY = "binary"; + public static final String P_7BIT = "7bit"; + public static final String P_8BIT = "8bit"; + public static final String P_BASE64 = "base64"; + public static final String P_QUOTED_PRINTABLE = "quoted-printable"; + + /** + * Value of disposition can be set to PduPart when the value is octet in + * the PDU. + * "from-data" instead of Form-data<Octet 128>. + * "attachment" instead of Attachment<Octet 129>. + * "inline" instead of Inline<Octet 130>. + */ + static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes(); + static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes(); + static final byte[] DISPOSITION_INLINE = "inline".getBytes(); + + /** + * Content-Disposition value. + */ + public static final int P_DISPOSITION_FROM_DATA = 0x80; + public static final int P_DISPOSITION_ATTACHMENT = 0x81; + public static final int P_DISPOSITION_INLINE = 0x82; + + /** + * Header of part. + */ + private Map<Integer, Object> mPartHeader = null; + + /** + * Data uri. + */ + private Uri mUri = null; + + /** + * Part data. + */ + private byte[] mPartData = null; + + private static final String TAG = "PduPart"; + + /** + * Empty Constructor. + */ + @UnsupportedAppUsage + public PduPart() { + mPartHeader = new HashMap<Integer, Object>(); + } + + /** + * Set part data. The data are stored as byte array. + * + * @param data the data + */ + @UnsupportedAppUsage + public void setData(byte[] data) { + if(data == null) { + return; + } + + mPartData = new byte[data.length]; + System.arraycopy(data, 0, mPartData, 0, data.length); + } + + /** + * @return A copy of the part data or null if the data wasn't set or + * the data is stored as Uri. + * @see #getDataUri + */ + @UnsupportedAppUsage + public byte[] getData() { + if(mPartData == null) { + return null; + } + + byte[] byteArray = new byte[mPartData.length]; + System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length); + return byteArray; + } + + /** + * @return The length of the data, if this object have data, else 0. + */ + @UnsupportedAppUsage + public int getDataLength() { + if(mPartData != null){ + return mPartData.length; + } else { + return 0; + } + } + + + /** + * Set data uri. The data are stored as Uri. + * + * @param uri the uri + */ + @UnsupportedAppUsage + public void setDataUri(Uri uri) { + mUri = uri; + } + + /** + * @return The Uri of the part data or null if the data wasn't set or + * the data is stored as byte array. + * @see #getData + */ + @UnsupportedAppUsage + public Uri getDataUri() { + return mUri; + } + + /** + * Set Content-id value + * + * @param contentId the content-id value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentId(byte[] contentId) { + if((contentId == null) || (contentId.length == 0)) { + throw new IllegalArgumentException( + "Content-Id may not be null or empty."); + } + + if ((contentId.length > 1) + && ((char) contentId[0] == '<') + && ((char) contentId[contentId.length - 1] == '>')) { + mPartHeader.put(P_CONTENT_ID, contentId); + return; + } + + // Insert beginning '<' and trailing '>' for Content-Id. + byte[] buffer = new byte[contentId.length + 2]; + buffer[0] = (byte) (0xff & '<'); + buffer[buffer.length - 1] = (byte) (0xff & '>'); + System.arraycopy(contentId, 0, buffer, 1, contentId.length); + mPartHeader.put(P_CONTENT_ID, buffer); + } + + /** + * Get Content-id value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentId() { + return (byte[]) mPartHeader.get(P_CONTENT_ID); + } + + /** + * Set Char-set value. + * + * @param charset the value + */ + @UnsupportedAppUsage + public void setCharset(int charset) { + mPartHeader.put(P_CHARSET, charset); + } + + /** + * Get Char-set value + * + * @return the charset value. Return 0 if charset was not set. + */ + @UnsupportedAppUsage + public int getCharset() { + Integer charset = (Integer) mPartHeader.get(P_CHARSET); + if(charset == null) { + return 0; + } else { + return charset.intValue(); + } + } + + /** + * Set Content-Location value. + * + * @param contentLocation the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentLocation(byte[] contentLocation) { + if(contentLocation == null) { + throw new NullPointerException("null content-location"); + } + + mPartHeader.put(P_CONTENT_LOCATION, contentLocation); + } + + /** + * Get Content-Location value. + * + * @return the value + * return PduPart.disposition[0] instead of <Octet 128> (Form-data). + * return PduPart.disposition[1] instead of <Octet 129> (Attachment). + * return PduPart.disposition[2] instead of <Octet 130> (Inline). + */ + @UnsupportedAppUsage + public byte[] getContentLocation() { + return (byte[]) mPartHeader.get(P_CONTENT_LOCATION); + } + + /** + * Set Content-Disposition value. + * Use PduPart.disposition[0] instead of <Octet 128> (Form-data). + * Use PduPart.disposition[1] instead of <Octet 129> (Attachment). + * Use PduPart.disposition[2] instead of <Octet 130> (Inline). + * + * @param contentDisposition the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentDisposition(byte[] contentDisposition) { + if(contentDisposition == null) { + throw new NullPointerException("null content-disposition"); + } + + mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition); + } + + /** + * Get Content-Disposition value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentDisposition() { + return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION); + } + + /** + * Set Content-Type value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentType(byte[] contentType) { + if(contentType == null) { + throw new NullPointerException("null content-type"); + } + + mPartHeader.put(P_CONTENT_TYPE, contentType); + } + + /** + * Get Content-Type value of part. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentType() { + return (byte[]) mPartHeader.get(P_CONTENT_TYPE); + } + + /** + * Set Content-Transfer-Encoding value + * + * @param contentId the content-id value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentTransferEncoding(byte[] contentTransferEncoding) { + if(contentTransferEncoding == null) { + throw new NullPointerException("null content-transfer-encoding"); + } + + mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding); + } + + /** + * Get Content-Transfer-Encoding value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentTransferEncoding() { + return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING); + } + + /** + * Set Content-type parameter: name. + * + * @param name the name value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setName(byte[] name) { + if(null == name) { + throw new NullPointerException("null content-id"); + } + + mPartHeader.put(P_NAME, name); + } + + /** + * Get content-type parameter: name. + * + * @return the name + */ + @UnsupportedAppUsage + public byte[] getName() { + return (byte[]) mPartHeader.get(P_NAME); + } + + /** + * Get Content-disposition parameter: filename + * + * @param fileName the filename value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setFilename(byte[] fileName) { + if(null == fileName) { + throw new NullPointerException("null content-id"); + } + + mPartHeader.put(P_FILENAME, fileName); + } + + /** + * Set Content-disposition parameter: filename + * + * @return the filename + */ + @UnsupportedAppUsage + public byte[] getFilename() { + return (byte[]) mPartHeader.get(P_FILENAME); + } + + @UnsupportedAppUsage + public String generateLocation() { + // Assumption: At least one of the content-location / name / filename + // or content-id should be set. This is guaranteed by the PduParser + // for incoming messages and by MM composer for outgoing messages. + byte[] location = (byte[]) mPartHeader.get(P_NAME); + if(null == location) { + location = (byte[]) mPartHeader.get(P_FILENAME); + + if (null == location) { + location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION); + } + } + + if (null == location) { + byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID); + return "cid:" + new String(contentId); + } else { + return new String(location); + } + } +} + diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java new file mode 100755 index 000000000000..95ae4096ed86 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java @@ -0,0 +1,1574 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.drm.DrmManagerClient; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.provider.Telephony; +import android.provider.Telephony.Mms; +import android.provider.Telephony.Mms.Addr; +import android.provider.Telephony.Mms.Part; +import android.provider.Telephony.MmsSms; +import android.provider.Telephony.MmsSms.PendingMessages; +import android.provider.Telephony.Threads; +import android.telephony.PhoneNumberUtils; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.ContentType; +import com.google.android.mms.InvalidHeaderValueException; +import com.google.android.mms.MmsException; +import com.google.android.mms.util.DownloadDrmHelper; +import com.google.android.mms.util.DrmConvertSession; +import com.google.android.mms.util.PduCache; +import com.google.android.mms.util.PduCacheEntry; +import com.google.android.mms.util.SqliteWrapper; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * This class is the high-level manager of PDU storage. + */ +public class PduPersister { + private static final String TAG = "PduPersister"; + private static final boolean DEBUG = false; + private static final boolean LOCAL_LOGV = false; + + private static final long DUMMY_THREAD_ID = Long.MAX_VALUE; + + /** + * The uri of temporary drm objects. + */ + public static final String TEMPORARY_DRM_OBJECT_URI = + "content://mms/" + Long.MAX_VALUE + "/part"; + /** + * Indicate that we transiently failed to process a MM. + */ + public static final int PROC_STATUS_TRANSIENT_FAILURE = 1; + /** + * Indicate that we permanently failed to process a MM. + */ + public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2; + /** + * Indicate that we have successfully processed a MM. + */ + public static final int PROC_STATUS_COMPLETED = 3; + + private static PduPersister sPersister; + @UnsupportedAppUsage + private static final PduCache PDU_CACHE_INSTANCE; + + @UnsupportedAppUsage + private static final int[] ADDRESS_FIELDS = new int[] { + PduHeaders.BCC, + PduHeaders.CC, + PduHeaders.FROM, + PduHeaders.TO + }; + + private static final String[] PDU_PROJECTION = new String[] { + Mms._ID, + Mms.MESSAGE_BOX, + Mms.THREAD_ID, + Mms.RETRIEVE_TEXT, + Mms.SUBJECT, + Mms.CONTENT_LOCATION, + Mms.CONTENT_TYPE, + Mms.MESSAGE_CLASS, + Mms.MESSAGE_ID, + Mms.RESPONSE_TEXT, + Mms.TRANSACTION_ID, + Mms.CONTENT_CLASS, + Mms.DELIVERY_REPORT, + Mms.MESSAGE_TYPE, + Mms.MMS_VERSION, + Mms.PRIORITY, + Mms.READ_REPORT, + Mms.READ_STATUS, + Mms.REPORT_ALLOWED, + Mms.RETRIEVE_STATUS, + Mms.STATUS, + Mms.DATE, + Mms.DELIVERY_TIME, + Mms.EXPIRY, + Mms.MESSAGE_SIZE, + Mms.SUBJECT_CHARSET, + Mms.RETRIEVE_TEXT_CHARSET, + }; + + private static final int PDU_COLUMN_ID = 0; + private static final int PDU_COLUMN_MESSAGE_BOX = 1; + private static final int PDU_COLUMN_THREAD_ID = 2; + private static final int PDU_COLUMN_RETRIEVE_TEXT = 3; + private static final int PDU_COLUMN_SUBJECT = 4; + private static final int PDU_COLUMN_CONTENT_LOCATION = 5; + private static final int PDU_COLUMN_CONTENT_TYPE = 6; + private static final int PDU_COLUMN_MESSAGE_CLASS = 7; + private static final int PDU_COLUMN_MESSAGE_ID = 8; + private static final int PDU_COLUMN_RESPONSE_TEXT = 9; + private static final int PDU_COLUMN_TRANSACTION_ID = 10; + private static final int PDU_COLUMN_CONTENT_CLASS = 11; + private static final int PDU_COLUMN_DELIVERY_REPORT = 12; + private static final int PDU_COLUMN_MESSAGE_TYPE = 13; + private static final int PDU_COLUMN_MMS_VERSION = 14; + private static final int PDU_COLUMN_PRIORITY = 15; + private static final int PDU_COLUMN_READ_REPORT = 16; + private static final int PDU_COLUMN_READ_STATUS = 17; + private static final int PDU_COLUMN_REPORT_ALLOWED = 18; + private static final int PDU_COLUMN_RETRIEVE_STATUS = 19; + private static final int PDU_COLUMN_STATUS = 20; + private static final int PDU_COLUMN_DATE = 21; + private static final int PDU_COLUMN_DELIVERY_TIME = 22; + private static final int PDU_COLUMN_EXPIRY = 23; + private static final int PDU_COLUMN_MESSAGE_SIZE = 24; + private static final int PDU_COLUMN_SUBJECT_CHARSET = 25; + private static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26; + + @UnsupportedAppUsage + private static final String[] PART_PROJECTION = new String[] { + Part._ID, + Part.CHARSET, + Part.CONTENT_DISPOSITION, + Part.CONTENT_ID, + Part.CONTENT_LOCATION, + Part.CONTENT_TYPE, + Part.FILENAME, + Part.NAME, + Part.TEXT + }; + + private static final int PART_COLUMN_ID = 0; + private static final int PART_COLUMN_CHARSET = 1; + private static final int PART_COLUMN_CONTENT_DISPOSITION = 2; + private static final int PART_COLUMN_CONTENT_ID = 3; + private static final int PART_COLUMN_CONTENT_LOCATION = 4; + private static final int PART_COLUMN_CONTENT_TYPE = 5; + private static final int PART_COLUMN_FILENAME = 6; + private static final int PART_COLUMN_NAME = 7; + private static final int PART_COLUMN_TEXT = 8; + + @UnsupportedAppUsage + private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP; + // These map are used for convenience in persist() and load(). + private static final HashMap<Integer, Integer> CHARSET_COLUMN_INDEX_MAP; + private static final HashMap<Integer, Integer> ENCODED_STRING_COLUMN_INDEX_MAP; + private static final HashMap<Integer, Integer> TEXT_STRING_COLUMN_INDEX_MAP; + private static final HashMap<Integer, Integer> OCTET_COLUMN_INDEX_MAP; + private static final HashMap<Integer, Integer> LONG_COLUMN_INDEX_MAP; + @UnsupportedAppUsage + private static final HashMap<Integer, String> CHARSET_COLUMN_NAME_MAP; + @UnsupportedAppUsage + private static final HashMap<Integer, String> ENCODED_STRING_COLUMN_NAME_MAP; + @UnsupportedAppUsage + private static final HashMap<Integer, String> TEXT_STRING_COLUMN_NAME_MAP; + @UnsupportedAppUsage + private static final HashMap<Integer, String> OCTET_COLUMN_NAME_MAP; + @UnsupportedAppUsage + private static final HashMap<Integer, String> LONG_COLUMN_NAME_MAP; + + static { + MESSAGE_BOX_MAP = new HashMap<Uri, Integer>(); + MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI, Mms.MESSAGE_BOX_INBOX); + MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI, Mms.MESSAGE_BOX_SENT); + MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI, Mms.MESSAGE_BOX_DRAFTS); + MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX); + + CHARSET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>(); + CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET); + CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET); + + CHARSET_COLUMN_NAME_MAP = new HashMap<Integer, String>(); + CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET); + CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET); + + // Encoded string field code -> column index/name map. + ENCODED_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>(); + ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT); + ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT); + + ENCODED_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>(); + ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT); + ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT); + + // Text string field code -> column index/name map. + TEXT_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>(); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT); + TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID); + + TEXT_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>(); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT); + TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID); + + // Octet field code -> column index/name map. + OCTET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>(); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS); + OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS); + + OCTET_COLUMN_NAME_MAP = new HashMap<Integer, String>(); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS); + OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS); + + // Long field code -> column index/name map. + LONG_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>(); + LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE); + LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME); + LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY); + LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE); + + LONG_COLUMN_NAME_MAP = new HashMap<Integer, String>(); + LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE); + LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME); + LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY); + LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE); + + PDU_CACHE_INSTANCE = PduCache.getInstance(); + } + + @UnsupportedAppUsage + private final Context mContext; + @UnsupportedAppUsage + private final ContentResolver mContentResolver; + private final DrmManagerClient mDrmManagerClient; + @UnsupportedAppUsage + private final TelephonyManager mTelephonyManager; + + private PduPersister(Context context) { + mContext = context; + mContentResolver = context.getContentResolver(); + mDrmManagerClient = new DrmManagerClient(context); + mTelephonyManager = (TelephonyManager)context + .getSystemService(Context.TELEPHONY_SERVICE); + } + + /** Get(or create if not exist) an instance of PduPersister */ + @UnsupportedAppUsage + public static PduPersister getPduPersister(Context context) { + if ((sPersister == null)) { + sPersister = new PduPersister(context); + } else if (!context.equals(sPersister.mContext)) { + sPersister.release(); + sPersister = new PduPersister(context); + } + + return sPersister; + } + + private void setEncodedStringValueToHeaders( + Cursor c, int columnIndex, + PduHeaders headers, int mapColumn) { + String s = c.getString(columnIndex); + if ((s != null) && (s.length() > 0)) { + int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn); + int charset = c.getInt(charsetColumnIndex); + EncodedStringValue value = new EncodedStringValue( + charset, getBytes(s)); + headers.setEncodedStringValue(value, mapColumn); + } + } + + private void setTextStringToHeaders( + Cursor c, int columnIndex, + PduHeaders headers, int mapColumn) { + String s = c.getString(columnIndex); + if (s != null) { + headers.setTextString(getBytes(s), mapColumn); + } + } + + private void setOctetToHeaders( + Cursor c, int columnIndex, + PduHeaders headers, int mapColumn) throws InvalidHeaderValueException { + if (!c.isNull(columnIndex)) { + int b = c.getInt(columnIndex); + headers.setOctet(b, mapColumn); + } + } + + private void setLongToHeaders( + Cursor c, int columnIndex, + PduHeaders headers, int mapColumn) { + if (!c.isNull(columnIndex)) { + long l = c.getLong(columnIndex); + headers.setLongInteger(l, mapColumn); + } + } + + @UnsupportedAppUsage + private Integer getIntegerFromPartColumn(Cursor c, int columnIndex) { + if (!c.isNull(columnIndex)) { + return c.getInt(columnIndex); + } + return null; + } + + @UnsupportedAppUsage + private byte[] getByteArrayFromPartColumn(Cursor c, int columnIndex) { + if (!c.isNull(columnIndex)) { + return getBytes(c.getString(columnIndex)); + } + return null; + } + + private PduPart[] loadParts(long msgId) throws MmsException { + Cursor c = SqliteWrapper.query(mContext, mContentResolver, + Uri.parse("content://mms/" + msgId + "/part"), + PART_PROJECTION, null, null, null); + + PduPart[] parts = null; + + try { + if ((c == null) || (c.getCount() == 0)) { + if (LOCAL_LOGV) { + Log.v(TAG, "loadParts(" + msgId + "): no part to load."); + } + return null; + } + + int partCount = c.getCount(); + int partIdx = 0; + parts = new PduPart[partCount]; + while (c.moveToNext()) { + PduPart part = new PduPart(); + Integer charset = getIntegerFromPartColumn( + c, PART_COLUMN_CHARSET); + if (charset != null) { + part.setCharset(charset); + } + + byte[] contentDisposition = getByteArrayFromPartColumn( + c, PART_COLUMN_CONTENT_DISPOSITION); + if (contentDisposition != null) { + part.setContentDisposition(contentDisposition); + } + + byte[] contentId = getByteArrayFromPartColumn( + c, PART_COLUMN_CONTENT_ID); + if (contentId != null) { + part.setContentId(contentId); + } + + byte[] contentLocation = getByteArrayFromPartColumn( + c, PART_COLUMN_CONTENT_LOCATION); + if (contentLocation != null) { + part.setContentLocation(contentLocation); + } + + byte[] contentType = getByteArrayFromPartColumn( + c, PART_COLUMN_CONTENT_TYPE); + if (contentType != null) { + part.setContentType(contentType); + } else { + throw new MmsException("Content-Type must be set."); + } + + byte[] fileName = getByteArrayFromPartColumn( + c, PART_COLUMN_FILENAME); + if (fileName != null) { + part.setFilename(fileName); + } + + byte[] name = getByteArrayFromPartColumn( + c, PART_COLUMN_NAME); + if (name != null) { + part.setName(name); + } + + // Construct a Uri for this part. + long partId = c.getLong(PART_COLUMN_ID); + Uri partURI = Uri.parse("content://mms/part/" + partId); + part.setDataUri(partURI); + + // For images/audio/video, we won't keep their data in Part + // because their renderer accept Uri as source. + String type = toIsoString(contentType); + if (!ContentType.isImageType(type) + && !ContentType.isAudioType(type) + && !ContentType.isVideoType(type)) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream is = null; + + // Store simple string values directly in the database instead of an + // external file. This makes the text searchable and retrieval slightly + // faster. + if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type) + || ContentType.TEXT_HTML.equals(type)) { + String text = c.getString(PART_COLUMN_TEXT); + byte [] blob = new EncodedStringValue(text != null ? text : "") + .getTextString(); + baos.write(blob, 0, blob.length); + } else { + + try { + is = mContentResolver.openInputStream(partURI); + + byte[] buffer = new byte[256]; + int len = is.read(buffer); + while (len >= 0) { + baos.write(buffer, 0, len); + len = is.read(buffer); + } + } catch (IOException e) { + Log.e(TAG, "Failed to load part data", e); + c.close(); + throw new MmsException(e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + Log.e(TAG, "Failed to close stream", e); + } // Ignore + } + } + } + part.setData(baos.toByteArray()); + } + parts[partIdx++] = part; + } + } finally { + if (c != null) { + c.close(); + } + } + + return parts; + } + + private void loadAddress(long msgId, PduHeaders headers) { + Cursor c = SqliteWrapper.query(mContext, mContentResolver, + Uri.parse("content://mms/" + msgId + "/addr"), + new String[] { Addr.ADDRESS, Addr.CHARSET, Addr.TYPE }, + null, null, null); + + if (c != null) { + try { + while (c.moveToNext()) { + String addr = c.getString(0); + if (!TextUtils.isEmpty(addr)) { + int addrType = c.getInt(2); + switch (addrType) { + case PduHeaders.FROM: + headers.setEncodedStringValue( + new EncodedStringValue(c.getInt(1), getBytes(addr)), + addrType); + break; + case PduHeaders.TO: + case PduHeaders.CC: + case PduHeaders.BCC: + headers.appendEncodedStringValue( + new EncodedStringValue(c.getInt(1), getBytes(addr)), + addrType); + break; + default: + Log.e(TAG, "Unknown address type: " + addrType); + break; + } + } + } + } finally { + c.close(); + } + } + } + + /** + * Load a PDU from storage by given Uri. + * + * @param uri The Uri of the PDU to be loaded. + * @return A generic PDU object, it may be cast to dedicated PDU. + * @throws MmsException Failed to load some fields of a PDU. + */ + @UnsupportedAppUsage + public GenericPdu load(Uri uri) throws MmsException { + GenericPdu pdu = null; + PduCacheEntry cacheEntry = null; + int msgBox = 0; + long threadId = -1; + try { + synchronized(PDU_CACHE_INSTANCE) { + if (PDU_CACHE_INSTANCE.isUpdating(uri)) { + if (LOCAL_LOGV) { + Log.v(TAG, "load: " + uri + " blocked by isUpdating()"); + } + try { + PDU_CACHE_INSTANCE.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "load: ", e); + } + cacheEntry = PDU_CACHE_INSTANCE.get(uri); + if (cacheEntry != null) { + return cacheEntry.getPdu(); + } + } + // Tell the cache to indicate to other callers that this item + // is currently being updated. + PDU_CACHE_INSTANCE.setUpdating(uri, true); + } + + Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri, + PDU_PROJECTION, null, null, null); + PduHeaders headers = new PduHeaders(); + Set<Entry<Integer, Integer>> set; + long msgId = ContentUris.parseId(uri); + + try { + if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) { + throw new MmsException("Bad uri: " + uri); + } + + msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX); + threadId = c.getLong(PDU_COLUMN_THREAD_ID); + + set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setEncodedStringValueToHeaders( + c, e.getValue(), headers, e.getKey()); + } + + set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setTextStringToHeaders( + c, e.getValue(), headers, e.getKey()); + } + + set = OCTET_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setOctetToHeaders( + c, e.getValue(), headers, e.getKey()); + } + + set = LONG_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setLongToHeaders( + c, e.getValue(), headers, e.getKey()); + } + } finally { + if (c != null) { + c.close(); + } + } + + // Check whether 'msgId' has been assigned a valid value. + if (msgId == -1L) { + throw new MmsException("Error! ID of the message: -1."); + } + + // Load address information of the MM. + loadAddress(msgId, headers); + + int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE); + PduBody body = new PduBody(); + + // For PDU which type is M_retrieve.conf or Send.req, we should + // load multiparts and put them into the body of the PDU. + if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) + || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { + PduPart[] parts = loadParts(msgId); + if (parts != null) { + int partsNum = parts.length; + for (int i = 0; i < partsNum; i++) { + body.addPart(parts[i]); + } + } + } + + switch (msgType) { + case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: + pdu = new NotificationInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_DELIVERY_IND: + pdu = new DeliveryInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND: + pdu = new ReadOrigInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: + pdu = new RetrieveConf(headers, body); + break; + case PduHeaders.MESSAGE_TYPE_SEND_REQ: + pdu = new SendReq(headers, body); + break; + case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND: + pdu = new AcknowledgeInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND: + pdu = new NotifyRespInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_READ_REC_IND: + pdu = new ReadRecInd(headers); + break; + case PduHeaders.MESSAGE_TYPE_SEND_CONF: + case PduHeaders.MESSAGE_TYPE_FORWARD_REQ: + case PduHeaders.MESSAGE_TYPE_FORWARD_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ: + case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF: + case PduHeaders.MESSAGE_TYPE_MBOX_DESCR: + case PduHeaders.MESSAGE_TYPE_DELETE_REQ: + case PduHeaders.MESSAGE_TYPE_DELETE_CONF: + case PduHeaders.MESSAGE_TYPE_CANCEL_REQ: + case PduHeaders.MESSAGE_TYPE_CANCEL_CONF: + throw new MmsException( + "Unsupported PDU type: " + Integer.toHexString(msgType)); + + default: + throw new MmsException( + "Unrecognized PDU type: " + Integer.toHexString(msgType)); + } + } finally { + synchronized(PDU_CACHE_INSTANCE) { + if (pdu != null) { + assert(PDU_CACHE_INSTANCE.get(uri) == null); + // Update the cache entry with the real info + cacheEntry = new PduCacheEntry(pdu, msgBox, threadId); + PDU_CACHE_INSTANCE.put(uri, cacheEntry); + } + PDU_CACHE_INSTANCE.setUpdating(uri, false); + PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead + } + } + return pdu; + } + + @UnsupportedAppUsage + private void persistAddress( + long msgId, int type, EncodedStringValue[] array) { + ContentValues values = new ContentValues(3); + + for (EncodedStringValue addr : array) { + values.clear(); // Clear all values first. + values.put(Addr.ADDRESS, toIsoString(addr.getTextString())); + values.put(Addr.CHARSET, addr.getCharacterSet()); + values.put(Addr.TYPE, type); + + Uri uri = Uri.parse("content://mms/" + msgId + "/addr"); + SqliteWrapper.insert(mContext, mContentResolver, uri, values); + } + } + + @UnsupportedAppUsage + private static String getPartContentType(PduPart part) { + return part.getContentType() == null ? null : toIsoString(part.getContentType()); + } + + @UnsupportedAppUsage + public Uri persistPart(PduPart part, long msgId, HashMap<Uri, InputStream> preOpenedFiles) + throws MmsException { + Uri uri = Uri.parse("content://mms/" + msgId + "/part"); + ContentValues values = new ContentValues(8); + + int charset = part.getCharset(); + if (charset != 0 ) { + values.put(Part.CHARSET, charset); + } + + String contentType = getPartContentType(part); + if (contentType != null) { + // There is no "image/jpg" in Android (and it's an invalid mimetype). + // Change it to "image/jpeg" + if (ContentType.IMAGE_JPG.equals(contentType)) { + contentType = ContentType.IMAGE_JPEG; + } + + values.put(Part.CONTENT_TYPE, contentType); + // To ensure the SMIL part is always the first part. + if (ContentType.APP_SMIL.equals(contentType)) { + values.put(Part.SEQ, -1); + } + } else { + throw new MmsException("MIME type of the part must be set."); + } + + if (part.getFilename() != null) { + String fileName = new String(part.getFilename()); + values.put(Part.FILENAME, fileName); + } + + if (part.getName() != null) { + String name = new String(part.getName()); + values.put(Part.NAME, name); + } + + Object value = null; + if (part.getContentDisposition() != null) { + value = toIsoString(part.getContentDisposition()); + values.put(Part.CONTENT_DISPOSITION, (String) value); + } + + if (part.getContentId() != null) { + value = toIsoString(part.getContentId()); + values.put(Part.CONTENT_ID, (String) value); + } + + if (part.getContentLocation() != null) { + value = toIsoString(part.getContentLocation()); + values.put(Part.CONTENT_LOCATION, (String) value); + } + + Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values); + if (res == null) { + throw new MmsException("Failed to persist part, return null."); + } + + persistData(part, res, contentType, preOpenedFiles); + // After successfully store the data, we should update + // the dataUri of the part. + part.setDataUri(res); + + return res; + } + + /** + * Save data of the part into storage. The source data may be given + * by a byte[] or a Uri. If it's a byte[], directly save it + * into storage, otherwise load source data from the dataUri and then + * save it. If the data is an image, we may scale down it according + * to user preference. + * + * @param part The PDU part which contains data to be saved. + * @param uri The URI of the part. + * @param contentType The MIME type of the part. + * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. + * @throws MmsException Cannot find source data or error occurred + * while saving the data. + */ + private void persistData(PduPart part, Uri uri, + String contentType, HashMap<Uri, InputStream> preOpenedFiles) + throws MmsException { + OutputStream os = null; + InputStream is = null; + DrmConvertSession drmConvertSession = null; + Uri dataUri = null; + String path = null; + + try { + byte[] data = part.getData(); + if (ContentType.TEXT_PLAIN.equals(contentType) + || ContentType.APP_SMIL.equals(contentType) + || ContentType.TEXT_HTML.equals(contentType)) { + ContentValues cv = new ContentValues(); + if (data == null) { + data = new String("").getBytes(CharacterSets.DEFAULT_CHARSET_NAME); + } + cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString()); + if (mContentResolver.update(uri, cv, null, null) != 1) { + throw new MmsException("unable to update " + uri.toString()); + } + } else { + boolean isDrm = DownloadDrmHelper.isDrmConvertNeeded(contentType); + if (isDrm) { + if (uri != null) { + try (ParcelFileDescriptor pfd = + mContentResolver.openFileDescriptor(uri, "r")) { + if (pfd.getStatSize() > 0) { + // we're not going to re-persist and re-encrypt an already + // converted drm file + return; + } + } catch (Exception e) { + Log.e(TAG, "Can't get file info for: " + part.getDataUri(), e); + } + } + // We haven't converted the file yet, start the conversion + drmConvertSession = DrmConvertSession.open(mContext, contentType); + if (drmConvertSession == null) { + throw new MmsException("Mimetype " + contentType + + " can not be converted."); + } + } + // uri can look like: + // content://mms/part/98 + os = mContentResolver.openOutputStream(uri); + if (data == null) { + dataUri = part.getDataUri(); + if ((dataUri == null) || (dataUri.equals(uri))) { + Log.w(TAG, "Can't find data for this part."); + return; + } + // dataUri can look like: + // content://com.google.android.gallery3d.provider/picasa/item/5720646660183715586 + if (preOpenedFiles != null && preOpenedFiles.containsKey(dataUri)) { + is = preOpenedFiles.get(dataUri); + } + if (is == null) { + is = mContentResolver.openInputStream(dataUri); + } + + if (LOCAL_LOGV) { + Log.v(TAG, "Saving data to: " + uri); + } + + byte[] buffer = new byte[8192]; + for (int len = 0; (len = is.read(buffer)) != -1; ) { + if (!isDrm) { + os.write(buffer, 0, len); + } else { + byte[] convertedData = drmConvertSession.convert(buffer, len); + if (convertedData != null) { + os.write(convertedData, 0, convertedData.length); + } else { + throw new MmsException("Error converting drm data."); + } + } + } + } else { + if (LOCAL_LOGV) { + Log.v(TAG, "Saving data to: " + uri); + } + if (!isDrm) { + os.write(data); + } else { + dataUri = uri; + byte[] convertedData = drmConvertSession.convert(data, data.length); + if (convertedData != null) { + os.write(convertedData, 0, convertedData.length); + } else { + throw new MmsException("Error converting drm data."); + } + } + } + } + } catch (FileNotFoundException e) { + Log.e(TAG, "Failed to open Input/Output stream.", e); + throw new MmsException(e); + } catch (IOException e) { + Log.e(TAG, "Failed to read/write data.", e); + throw new MmsException(e); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + Log.e(TAG, "IOException while closing: " + os, e); + } // Ignore + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + Log.e(TAG, "IOException while closing: " + is, e); + } // Ignore + } + if (drmConvertSession != null) { + drmConvertSession.close(path); + + // Reset the permissions on the encrypted part file so everyone has only read + // permission. + File f = new File(path); + ContentValues values = new ContentValues(0); + SqliteWrapper.update(mContext, mContentResolver, + Uri.parse("content://mms/resetFilePerm/" + f.getName()), + values, null, null); + } + } + } + + @UnsupportedAppUsage + private void updateAddress( + long msgId, int type, EncodedStringValue[] array) { + // Delete old address information and then insert new ones. + SqliteWrapper.delete(mContext, mContentResolver, + Uri.parse("content://mms/" + msgId + "/addr"), + Addr.TYPE + "=" + type, null); + + persistAddress(msgId, type, array); + } + + /** + * Update headers of a SendReq. + * + * @param uri The PDU which need to be updated. + * @param pdu New headers. + * @throws MmsException Bad URI or updating failed. + */ + @UnsupportedAppUsage + public void updateHeaders(Uri uri, SendReq sendReq) { + synchronized(PDU_CACHE_INSTANCE) { + // If the cache item is getting updated, wait until it's done updating before + // purging it. + if (PDU_CACHE_INSTANCE.isUpdating(uri)) { + if (LOCAL_LOGV) { + Log.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()"); + } + try { + PDU_CACHE_INSTANCE.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "updateHeaders: ", e); + } + } + } + PDU_CACHE_INSTANCE.purge(uri); + + ContentValues values = new ContentValues(10); + byte[] contentType = sendReq.getContentType(); + if (contentType != null) { + values.put(Mms.CONTENT_TYPE, toIsoString(contentType)); + } + + long date = sendReq.getDate(); + if (date != -1) { + values.put(Mms.DATE, date); + } + + int deliveryReport = sendReq.getDeliveryReport(); + if (deliveryReport != 0) { + values.put(Mms.DELIVERY_REPORT, deliveryReport); + } + + long expiry = sendReq.getExpiry(); + if (expiry != -1) { + values.put(Mms.EXPIRY, expiry); + } + + byte[] msgClass = sendReq.getMessageClass(); + if (msgClass != null) { + values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass)); + } + + int priority = sendReq.getPriority(); + if (priority != 0) { + values.put(Mms.PRIORITY, priority); + } + + int readReport = sendReq.getReadReport(); + if (readReport != 0) { + values.put(Mms.READ_REPORT, readReport); + } + + byte[] transId = sendReq.getTransactionId(); + if (transId != null) { + values.put(Mms.TRANSACTION_ID, toIsoString(transId)); + } + + EncodedStringValue subject = sendReq.getSubject(); + if (subject != null) { + values.put(Mms.SUBJECT, toIsoString(subject.getTextString())); + values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet()); + } else { + values.put(Mms.SUBJECT, ""); + } + + long messageSize = sendReq.getMessageSize(); + if (messageSize > 0) { + values.put(Mms.MESSAGE_SIZE, messageSize); + } + + PduHeaders headers = sendReq.getPduHeaders(); + HashSet<String> recipients = new HashSet<String>(); + for (int addrType : ADDRESS_FIELDS) { + EncodedStringValue[] array = null; + if (addrType == PduHeaders.FROM) { + EncodedStringValue v = headers.getEncodedStringValue(addrType); + if (v != null) { + array = new EncodedStringValue[1]; + array[0] = v; + } + } else { + array = headers.getEncodedStringValues(addrType); + } + + if (array != null) { + long msgId = ContentUris.parseId(uri); + updateAddress(msgId, addrType, array); + if (addrType == PduHeaders.TO) { + for (EncodedStringValue v : array) { + if (v != null) { + recipients.add(v.getString()); + } + } + } + } + } + if (!recipients.isEmpty()) { + long threadId = Threads.getOrCreateThreadId(mContext, recipients); + values.put(Mms.THREAD_ID, threadId); + } + + SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null); + } + + private void updatePart(Uri uri, PduPart part, HashMap<Uri, InputStream> preOpenedFiles) + throws MmsException { + ContentValues values = new ContentValues(7); + + int charset = part.getCharset(); + if (charset != 0 ) { + values.put(Part.CHARSET, charset); + } + + String contentType = null; + if (part.getContentType() != null) { + contentType = toIsoString(part.getContentType()); + values.put(Part.CONTENT_TYPE, contentType); + } else { + throw new MmsException("MIME type of the part must be set."); + } + + if (part.getFilename() != null) { + String fileName = new String(part.getFilename()); + values.put(Part.FILENAME, fileName); + } + + if (part.getName() != null) { + String name = new String(part.getName()); + values.put(Part.NAME, name); + } + + Object value = null; + if (part.getContentDisposition() != null) { + value = toIsoString(part.getContentDisposition()); + values.put(Part.CONTENT_DISPOSITION, (String) value); + } + + if (part.getContentId() != null) { + value = toIsoString(part.getContentId()); + values.put(Part.CONTENT_ID, (String) value); + } + + if (part.getContentLocation() != null) { + value = toIsoString(part.getContentLocation()); + values.put(Part.CONTENT_LOCATION, (String) value); + } + + SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null); + + // Only update the data when: + // 1. New binary data supplied or + // 2. The Uri of the part is different from the current one. + if ((part.getData() != null) + || (!uri.equals(part.getDataUri()))) { + persistData(part, uri, contentType, preOpenedFiles); + } + } + + /** + * Update all parts of a PDU. + * + * @param uri The PDU which need to be updated. + * @param body New message body of the PDU. + * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. + * @throws MmsException Bad URI or updating failed. + */ + @UnsupportedAppUsage + public void updateParts(Uri uri, PduBody body, HashMap<Uri, InputStream> preOpenedFiles) + throws MmsException { + try { + PduCacheEntry cacheEntry; + synchronized(PDU_CACHE_INSTANCE) { + if (PDU_CACHE_INSTANCE.isUpdating(uri)) { + if (LOCAL_LOGV) { + Log.v(TAG, "updateParts: " + uri + " blocked by isUpdating()"); + } + try { + PDU_CACHE_INSTANCE.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "updateParts: ", e); + } + cacheEntry = PDU_CACHE_INSTANCE.get(uri); + if (cacheEntry != null) { + ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body); + } + } + // Tell the cache to indicate to other callers that this item + // is currently being updated. + PDU_CACHE_INSTANCE.setUpdating(uri, true); + } + + ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>(); + HashMap<Uri, PduPart> toBeUpdated = new HashMap<Uri, PduPart>(); + + int partsNum = body.getPartsNum(); + StringBuilder filter = new StringBuilder().append('('); + for (int i = 0; i < partsNum; i++) { + PduPart part = body.getPart(i); + Uri partUri = part.getDataUri(); + if ((partUri == null) || TextUtils.isEmpty(partUri.getAuthority()) + || !partUri.getAuthority().startsWith("mms")) { + toBeCreated.add(part); + } else { + toBeUpdated.put(partUri, part); + + // Don't use 'i > 0' to determine whether we should append + // 'AND' since 'i = 0' may be skipped in another branch. + if (filter.length() > 1) { + filter.append(" AND "); + } + + filter.append(Part._ID); + filter.append("!="); + DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment()); + } + } + filter.append(')'); + + long msgId = ContentUris.parseId(uri); + + // Remove the parts which doesn't exist anymore. + SqliteWrapper.delete(mContext, mContentResolver, + Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"), + filter.length() > 2 ? filter.toString() : null, null); + + // Create new parts which didn't exist before. + for (PduPart part : toBeCreated) { + persistPart(part, msgId, preOpenedFiles); + } + + // Update the modified parts. + for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) { + updatePart(e.getKey(), e.getValue(), preOpenedFiles); + } + } finally { + synchronized(PDU_CACHE_INSTANCE) { + PDU_CACHE_INSTANCE.setUpdating(uri, false); + PDU_CACHE_INSTANCE.notifyAll(); + } + } + } + + /** + * Persist a PDU object to specific location in the storage. + * + * @param pdu The PDU object to be stored. + * @param uri Where to store the given PDU object. + * @param createThreadId if true, this function may create a thread id for the recipients + * @param groupMmsEnabled if true, all of the recipients addressed in the PDU will be used + * to create the associated thread. When false, only the sender will be used in finding or + * creating the appropriate thread or conversation. + * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. + * @return A Uri which can be used to access the stored PDU. + */ + + @UnsupportedAppUsage + public Uri persist(GenericPdu pdu, Uri uri, boolean createThreadId, boolean groupMmsEnabled, + HashMap<Uri, InputStream> preOpenedFiles) + throws MmsException { + if (uri == null) { + throw new MmsException("Uri may not be null."); + } + long msgId = -1; + try { + msgId = ContentUris.parseId(uri); + } catch (NumberFormatException e) { + // the uri ends with "inbox" or something else like that + } + boolean existingUri = msgId != -1; + + if (!existingUri && MESSAGE_BOX_MAP.get(uri) == null) { + throw new MmsException( + "Bad destination, must be one of " + + "content://mms/inbox, content://mms/sent, " + + "content://mms/drafts, content://mms/outbox, " + + "content://mms/temp."); + } + synchronized(PDU_CACHE_INSTANCE) { + // If the cache item is getting updated, wait until it's done updating before + // purging it. + if (PDU_CACHE_INSTANCE.isUpdating(uri)) { + if (LOCAL_LOGV) { + Log.v(TAG, "persist: " + uri + " blocked by isUpdating()"); + } + try { + PDU_CACHE_INSTANCE.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "persist1: ", e); + } + } + } + PDU_CACHE_INSTANCE.purge(uri); + + PduHeaders header = pdu.getPduHeaders(); + PduBody body = null; + ContentValues values = new ContentValues(); + Set<Entry<Integer, String>> set; + + set = ENCODED_STRING_COLUMN_NAME_MAP.entrySet(); + for (Entry<Integer, String> e : set) { + int field = e.getKey(); + EncodedStringValue encodedString = header.getEncodedStringValue(field); + if (encodedString != null) { + String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field); + values.put(e.getValue(), toIsoString(encodedString.getTextString())); + values.put(charsetColumn, encodedString.getCharacterSet()); + } + } + + set = TEXT_STRING_COLUMN_NAME_MAP.entrySet(); + for (Entry<Integer, String> e : set){ + byte[] text = header.getTextString(e.getKey()); + if (text != null) { + values.put(e.getValue(), toIsoString(text)); + } + } + + set = OCTET_COLUMN_NAME_MAP.entrySet(); + for (Entry<Integer, String> e : set){ + int b = header.getOctet(e.getKey()); + if (b != 0) { + values.put(e.getValue(), b); + } + } + + set = LONG_COLUMN_NAME_MAP.entrySet(); + for (Entry<Integer, String> e : set){ + long l = header.getLongInteger(e.getKey()); + if (l != -1L) { + values.put(e.getValue(), l); + } + } + + HashMap<Integer, EncodedStringValue[]> addressMap = + new HashMap<Integer, EncodedStringValue[]>(ADDRESS_FIELDS.length); + // Save address information. + for (int addrType : ADDRESS_FIELDS) { + EncodedStringValue[] array = null; + if (addrType == PduHeaders.FROM) { + EncodedStringValue v = header.getEncodedStringValue(addrType); + if (v != null) { + array = new EncodedStringValue[1]; + array[0] = v; + } + } else { + array = header.getEncodedStringValues(addrType); + } + addressMap.put(addrType, array); + } + + HashSet<String> recipients = new HashSet<String>(); + int msgType = pdu.getMessageType(); + // Here we only allocate thread ID for M-Notification.ind, + // M-Retrieve.conf and M-Send.req. + // Some of other PDU types may be allocated a thread ID outside + // this scope. + if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) + || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) + || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { + switch (msgType) { + case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: + case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: + loadRecipients(PduHeaders.FROM, recipients, addressMap, false); + + // For received messages when group MMS is enabled, we want to associate this + // message with the thread composed of all the recipients -- all but our own + // number, that is. This includes the person who sent the + // message or the FROM field (above) in addition to the other people the message + // was addressed to or the TO field. Our own number is in that TO field and + // we have to ignore it in loadRecipients. + if (groupMmsEnabled) { + loadRecipients(PduHeaders.TO, recipients, addressMap, true); + + // Also load any numbers in the CC field to address group messaging + // compatibility issues with devices that place numbers in this field + // for group messages. + loadRecipients(PduHeaders.CC, recipients, addressMap, true); + } + break; + case PduHeaders.MESSAGE_TYPE_SEND_REQ: + loadRecipients(PduHeaders.TO, recipients, addressMap, false); + break; + } + long threadId = 0; + if (createThreadId && !recipients.isEmpty()) { + // Given all the recipients associated with this message, find (or create) the + // correct thread. + threadId = Threads.getOrCreateThreadId(mContext, recipients); + } + values.put(Mms.THREAD_ID, threadId); + } + + // Save parts first to avoid inconsistent message is loaded + // while saving the parts. + long dummyId = System.currentTimeMillis(); // Dummy ID of the msg. + + // Figure out if this PDU is a text-only message + boolean textOnly = true; + + // Sum up the total message size + int messageSize = 0; + + // Get body if the PDU is a RetrieveConf or SendReq. + if (pdu instanceof MultimediaMessagePdu) { + body = ((MultimediaMessagePdu) pdu).getBody(); + // Start saving parts if necessary. + if (body != null) { + int partsNum = body.getPartsNum(); + if (partsNum > 2) { + // For a text-only message there will be two parts: 1-the SMIL, 2-the text. + // Down a few lines below we're checking to make sure we've only got SMIL or + // text. We also have to check then we don't have more than two parts. + // Otherwise, a slideshow with two text slides would be marked as textOnly. + textOnly = false; + } + for (int i = 0; i < partsNum; i++) { + PduPart part = body.getPart(i); + messageSize += part.getDataLength(); + persistPart(part, dummyId, preOpenedFiles); + + // If we've got anything besides text/plain or SMIL part, then we've got + // an mms message with some other type of attachment. + String contentType = getPartContentType(part); + if (contentType != null && !ContentType.APP_SMIL.equals(contentType) + && !ContentType.TEXT_PLAIN.equals(contentType)) { + textOnly = false; + } + } + } + } + // Record whether this mms message is a simple plain text or not. This is a hint for the + // UI. + values.put(Mms.TEXT_ONLY, textOnly ? 1 : 0); + // The message-size might already have been inserted when parsing the + // PDU header. If not, then we insert the message size as well. + if (values.getAsInteger(Mms.MESSAGE_SIZE) == null) { + values.put(Mms.MESSAGE_SIZE, messageSize); + } + + Uri res = null; + if (existingUri) { + res = uri; + SqliteWrapper.update(mContext, mContentResolver, res, values, null, null); + } else { + res = SqliteWrapper.insert(mContext, mContentResolver, uri, values); + if (res == null) { + throw new MmsException("persist() failed: return null."); + } + // Get the real ID of the PDU and update all parts which were + // saved with the dummy ID. + msgId = ContentUris.parseId(res); + } + + values = new ContentValues(1); + values.put(Part.MSG_ID, msgId); + SqliteWrapper.update(mContext, mContentResolver, + Uri.parse("content://mms/" + dummyId + "/part"), + values, null, null); + // We should return the longest URI of the persisted PDU, for + // example, if input URI is "content://mms/inbox" and the _ID of + // persisted PDU is '8', we should return "content://mms/inbox/8" + // instead of "content://mms/8". + // FIXME: Should the MmsProvider be responsible for this??? + if (!existingUri) { + res = Uri.parse(uri + "/" + msgId); + } + + // Save address information. + for (int addrType : ADDRESS_FIELDS) { + EncodedStringValue[] array = addressMap.get(addrType); + if (array != null) { + persistAddress(msgId, addrType, array); + } + } + + return res; + } + + /** + * For a given address type, extract the recipients from the headers. + * + * @param addressType can be PduHeaders.FROM, PduHeaders.TO or PduHeaders.CC + * @param recipients a HashSet that is loaded with the recipients from the FROM, TO or CC headers + * @param addressMap a HashMap of the addresses from the ADDRESS_FIELDS header + * @param excludeMyNumber if true, the number of this phone will be excluded from recipients + */ + @UnsupportedAppUsage + private void loadRecipients(int addressType, HashSet<String> recipients, + HashMap<Integer, EncodedStringValue[]> addressMap, boolean excludeMyNumber) { + EncodedStringValue[] array = addressMap.get(addressType); + if (array == null) { + return; + } + // If the TO recipients is only a single address, then we can skip loadRecipients when + // we're excluding our own number because we know that address is our own. + if (excludeMyNumber && array.length == 1) { + return; + } + final SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext); + final Set<String> myPhoneNumbers = new HashSet<String>(); + if (excludeMyNumber) { + // Build a list of my phone numbers from the various sims. + for (int subid : subscriptionManager.getActiveSubscriptionIdList()) { + final String myNumber = mTelephonyManager.getLine1Number(subid); + if (myNumber != null) { + myPhoneNumbers.add(myNumber); + } + } + } + + for (EncodedStringValue v : array) { + if (v != null) { + final String number = v.getString(); + if (excludeMyNumber) { + for (final String myNumber : myPhoneNumbers) { + if (!PhoneNumberUtils.compare(number, myNumber) + && !recipients.contains(number)) { + // Only add numbers which aren't my own number. + recipients.add(number); + break; + } + } + } else if (!recipients.contains(number)){ + recipients.add(number); + } + } + } + } + + /** + * Move a PDU object from one location to another. + * + * @param from Specify the PDU object to be moved. + * @param to The destination location, should be one of the following: + * "content://mms/inbox", "content://mms/sent", + * "content://mms/drafts", "content://mms/outbox", + * "content://mms/trash". + * @return New Uri of the moved PDU. + * @throws MmsException Error occurred while moving the message. + */ + @UnsupportedAppUsage + public Uri move(Uri from, Uri to) throws MmsException { + // Check whether the 'msgId' has been assigned a valid value. + long msgId = ContentUris.parseId(from); + if (msgId == -1L) { + throw new MmsException("Error! ID of the message: -1."); + } + + // Get corresponding int value of destination box. + Integer msgBox = MESSAGE_BOX_MAP.get(to); + if (msgBox == null) { + throw new MmsException( + "Bad destination, must be one of " + + "content://mms/inbox, content://mms/sent, " + + "content://mms/drafts, content://mms/outbox, " + + "content://mms/temp."); + } + + ContentValues values = new ContentValues(1); + values.put(Mms.MESSAGE_BOX, msgBox); + SqliteWrapper.update(mContext, mContentResolver, from, values, null, null); + return ContentUris.withAppendedId(to, msgId); + } + + /** + * Wrap a byte[] into a String. + */ + @UnsupportedAppUsage + public static String toIsoString(byte[] bytes) { + try { + return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1); + } catch (UnsupportedEncodingException e) { + // Impossible to reach here! + Log.e(TAG, "ISO_8859_1 must be supported!", e); + return ""; + } + } + + /** + * Unpack a given String into a byte[]. + */ + @UnsupportedAppUsage + public static byte[] getBytes(String data) { + try { + return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1); + } catch (UnsupportedEncodingException e) { + // Impossible to reach here! + Log.e(TAG, "ISO_8859_1 must be supported!", e); + return new byte[0]; + } + } + + /** + * Remove all objects in the temporary path. + */ + public void release() { + Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI); + SqliteWrapper.delete(mContext, mContentResolver, uri, null, null); + mDrmManagerClient.release(); + } + + /** + * Find all messages to be sent or downloaded before certain time. + */ + @UnsupportedAppUsage + public Cursor getPendingMessages(long dueTime) { + Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon(); + uriBuilder.appendQueryParameter("protocol", "mms"); + + String selection = PendingMessages.ERROR_TYPE + " < ?" + + " AND " + PendingMessages.DUE_TIME + " <= ?"; + + String[] selectionArgs = new String[] { + String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT), + String.valueOf(dueTime) + }; + + return SqliteWrapper.query(mContext, mContentResolver, + uriBuilder.build(), null, selection, selectionArgs, + PendingMessages.DUE_TIME); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java new file mode 100644 index 000000000000..9d6535c72e90 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.io.ByteArrayOutputStream; + +public class QuotedPrintable { + private static byte ESCAPE_CHAR = '='; + + /** + * Decodes an array quoted-printable characters into an array of original bytes. + * Escaped characters are converted back to their original representation. + * + * <p> + * This function implements a subset of + * quoted-printable encoding specification (rule #1 and rule #2) + * as defined in RFC 1521. + * </p> + * + * @param bytes array of quoted-printable characters + * @return array of original bytes, + * null if quoted-printable decoding is unsuccessful. + */ + @UnsupportedAppUsage + public static final byte[] decodeQuotedPrintable(byte[] bytes) { + if (bytes == null) { + return null; + } + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + for (int i = 0; i < bytes.length; i++) { + int b = bytes[i]; + if (b == ESCAPE_CHAR) { + try { + if('\r' == (char)bytes[i + 1] && + '\n' == (char)bytes[i + 2]) { + i += 2; + continue; + } + int u = Character.digit((char) bytes[++i], 16); + int l = Character.digit((char) bytes[++i], 16); + if (u == -1 || l == -1) { + return null; + } + buffer.write((char) ((u << 4) + l)); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } else { + buffer.write(b); + } + } + return buffer.toByteArray(); + } +} diff --git a/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java new file mode 100644 index 000000000000..e38c62dde622 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +public class ReadOrigInd extends GenericPdu { + /** + * Empty constructor. + * Since the Pdu corresponding to this class is constructed + * by the Proxy-Relay server, this class is only instantiated + * by the Pdu Parser. + * + * @throws InvalidHeaderValueException if error occurs. + */ + public ReadOrigInd() throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_READ_ORIG_IND); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + ReadOrigInd(PduHeaders headers) { + super(headers); + } + + /** + * Get Date value. + * + * @return the value + */ + public long getDate() { + return mPduHeaders.getLongInteger(PduHeaders.DATE); + } + + /** + * Set Date value. + * + * @param value the value + */ + public void setDate(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.DATE); + } + + /** + * Get From value. + * From-value = Value-length + * (Address-present-token Encoded-string-value | Insert-address-token) + * + * @return the value + */ + public EncodedStringValue getFrom() { + return mPduHeaders.getEncodedStringValue(PduHeaders.FROM); + } + + /** + * Set From value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setFrom(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM); + } + + /** + * Get Message-ID value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageId() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID); + } + + /** + * Set Message-ID value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setMessageId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID); + } + + /** + * Get X-MMS-Read-status value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getReadStatus() { + return mPduHeaders.getOctet(PduHeaders.READ_STATUS); + } + + /** + * Set X-MMS-Read-status value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + public void setReadStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.READ_STATUS); + } + + /** + * Get To value. + * + * @return the value + */ + public EncodedStringValue[] getTo() { + return mPduHeaders.getEncodedStringValues(PduHeaders.TO); + } + + /** + * Set To value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setTo(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.TO); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/ReadRecInd.java b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java new file mode 100644 index 000000000000..9696bc259d00 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +public class ReadRecInd extends GenericPdu { + /** + * Constructor, used when composing a M-ReadRec.ind pdu. + * + * @param from the from value + * @param messageId the message ID value + * @param mmsVersion current viersion of mms + * @param readStatus the read status value + * @param to the to value + * @throws InvalidHeaderValueException if parameters are invalid. + * NullPointerException if messageId or to is null. + */ + @UnsupportedAppUsage + public ReadRecInd(EncodedStringValue from, + byte[] messageId, + int mmsVersion, + int readStatus, + EncodedStringValue[] to) throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_READ_REC_IND); + setFrom(from); + setMessageId(messageId); + setMmsVersion(mmsVersion); + setTo(to); + setReadStatus(readStatus); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + ReadRecInd(PduHeaders headers) { + super(headers); + } + + /** + * Get Date value. + * + * @return the value + */ + public long getDate() { + return mPduHeaders.getLongInteger(PduHeaders.DATE); + } + + /** + * Set Date value. + * + * @param value the value + */ + @UnsupportedAppUsage + public void setDate(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.DATE); + } + + /** + * Get Message-ID value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageId() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID); + } + + /** + * Set Message-ID value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setMessageId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID); + } + + /** + * Get To value. + * + * @return the value + */ + public EncodedStringValue[] getTo() { + return mPduHeaders.getEncodedStringValues(PduHeaders.TO); + } + + /** + * Set To value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setTo(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.TO); + } + + /** + * Get X-MMS-Read-status value. + * + * @return the value + */ + public int getReadStatus() { + return mPduHeaders.getOctet(PduHeaders.READ_STATUS); + } + + /** + * Set X-MMS-Read-status value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + public void setReadStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.READ_STATUS); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/RetrieveConf.java b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java new file mode 100644 index 000000000000..03755af4189c --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +/** + * M-Retrieve.conf Pdu. + */ +public class RetrieveConf extends MultimediaMessagePdu { + /** + * Empty constructor. + * Since the Pdu corresponding to this class is constructed + * by the Proxy-Relay server, this class is only instantiated + * by the Pdu Parser. + * + * @throws InvalidHeaderValueException if error occurs. + */ + @UnsupportedAppUsage + public RetrieveConf() throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + RetrieveConf(PduHeaders headers) { + super(headers); + } + + /** + * Constructor with given headers and body + * + * @param headers Headers for this PDU. + * @param body Body of this PDu. + */ + @UnsupportedAppUsage + RetrieveConf(PduHeaders headers, PduBody body) { + super(headers, body); + } + + /** + * Get CC value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue[] getCc() { + return mPduHeaders.getEncodedStringValues(PduHeaders.CC); + } + + /** + * Add a "CC" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void addCc(EncodedStringValue value) { + mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC); + } + + /** + * Get Content-type value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentType() { + return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE); + } + + /** + * Set Content-type value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentType(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE); + } + + /** + * Get X-Mms-Delivery-Report value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getDeliveryReport() { + return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT); + } + + /** + * Set X-Mms-Delivery-Report value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setDeliveryReport(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT); + } + + /** + * Get From value. + * From-value = Value-length + * (Address-present-token Encoded-string-value | Insert-address-token) + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getFrom() { + return mPduHeaders.getEncodedStringValue(PduHeaders.FROM); + } + + /** + * Set From value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setFrom(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM); + } + + /** + * Get X-Mms-Message-Class value. + * Message-class-value = Class-identifier | Token-text + * Class-identifier = Personal | Advertisement | Informational | Auto + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageClass() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS); + } + + /** + * Set X-Mms-Message-Class value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setMessageClass(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS); + } + + /** + * Get Message-ID value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageId() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID); + } + + /** + * Set Message-ID value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setMessageId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID); + } + + /** + * Get X-Mms-Read-Report value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getReadReport() { + return mPduHeaders.getOctet(PduHeaders.READ_REPORT); + } + + /** + * Set X-Mms-Read-Report value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setReadReport(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.READ_REPORT); + } + + /** + * Get X-Mms-Retrieve-Status value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getRetrieveStatus() { + return mPduHeaders.getOctet(PduHeaders.RETRIEVE_STATUS); + } + + /** + * Set X-Mms-Retrieve-Status value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setRetrieveStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.RETRIEVE_STATUS); + } + + /** + * Get X-Mms-Retrieve-Text value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue getRetrieveText() { + return mPduHeaders.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT); + } + + /** + * Set X-Mms-Retrieve-Text value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setRetrieveText(EncodedStringValue value) { + mPduHeaders.setEncodedStringValue(value, PduHeaders.RETRIEVE_TEXT); + } + + /** + * Get X-Mms-Transaction-Id. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte getContentClass() {return 0x00;} + * public void setApplicId(byte value) {} + * + * public byte getDrmContent() {return 0x00;} + * public void setDrmContent(byte value) {} + * + * public byte getDistributionIndicator() {return 0x00;} + * public void setDistributionIndicator(byte value) {} + * + * public PreviouslySentByValue getPreviouslySentBy() {return null;} + * public void setPreviouslySentBy(PreviouslySentByValue value) {} + * + * public PreviouslySentDateValue getPreviouslySentDate() {} + * public void setPreviouslySentDate(PreviouslySentDateValue value) {} + * + * public MmFlagsValue getMmFlags() {return null;} + * public void setMmFlags(MmFlagsValue value) {} + * + * public MmStateValue getMmState() {return null;} + * public void getMmState(MmStateValue value) {} + * + * public byte[] getReplaceId() {return 0x00;} + * public void setReplaceId(byte[] value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + * + * public byte getReplyCharging() {return 0x00;} + * public void setReplyCharging(byte value) {} + * + * public byte getReplyChargingDeadline() {return 0x00;} + * public void setReplyChargingDeadline(byte value) {} + * + * public byte[] getReplyChargingId() {return 0x00;} + * public void setReplyChargingId(byte[] value) {} + * + * public long getReplyChargingSize() {return 0;} + * public void setReplyChargingSize(long value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/SendConf.java b/telephony/common/com/google/android/mms/pdu/SendConf.java new file mode 100644 index 000000000000..b85982791ada --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/SendConf.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.mms.pdu; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +public class SendConf extends GenericPdu { + /** + * Empty constructor. + * Since the Pdu corresponding to this class is constructed + * by the Proxy-Relay server, this class is only instantiated + * by the Pdu Parser. + * + * @throws InvalidHeaderValueException if error occurs. + */ + @UnsupportedAppUsage + public SendConf() throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_SEND_CONF); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + @UnsupportedAppUsage + SendConf(PduHeaders headers) { + super(headers); + } + + /** + * Get Message-ID value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageId() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID); + } + + /** + * Set Message-ID value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setMessageId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID); + } + + /** + * Get X-Mms-Response-Status. + * + * @return the value + */ + @UnsupportedAppUsage + public int getResponseStatus() { + return mPduHeaders.getOctet(PduHeaders.RESPONSE_STATUS); + } + + /** + * Set X-Mms-Response-Status. + * + * @param value the values + * @throws InvalidHeaderValueException if the value is invalid. + */ + public void setResponseStatus(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.RESPONSE_STATUS); + } + + /** + * Get X-Mms-Transaction-Id field value. + * + * @return the X-Mms-Report-Allowed value + */ + @UnsupportedAppUsage + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id field value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } + + /* + * Optional, not supported header fields: + * + * public byte[] getContentLocation() {return null;} + * public void setContentLocation(byte[] value) {} + * + * public EncodedStringValue getResponseText() {return null;} + * public void setResponseText(EncodedStringValue value) {} + * + * public byte getStoreStatus() {return 0x00;} + * public void setStoreStatus(byte value) {} + * + * public byte[] getStoreStatusText() {return null;} + * public void setStoreStatusText(byte[] value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/SendReq.java b/telephony/common/com/google/android/mms/pdu/SendReq.java new file mode 100644 index 000000000000..c1b7f934c0f7 --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/SendReq.java @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 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.google.android.mms.pdu; + +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.InvalidHeaderValueException; + +public class SendReq extends MultimediaMessagePdu { + private static final String TAG = "SendReq"; + + @UnsupportedAppUsage + public SendReq() { + super(); + + try { + setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ); + setMmsVersion(PduHeaders.CURRENT_MMS_VERSION); + // FIXME: Content-type must be decided according to whether + // SMIL part present. + setContentType("application/vnd.wap.multipart.related".getBytes()); + setFrom(new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes())); + setTransactionId(generateTransactionId()); + } catch (InvalidHeaderValueException e) { + // Impossible to reach here since all headers we set above are valid. + Log.e(TAG, "Unexpected InvalidHeaderValueException.", e); + throw new RuntimeException(e); + } + } + + private byte[] generateTransactionId() { + String transactionId = "T" + Long.toHexString(System.currentTimeMillis()); + return transactionId.getBytes(); + } + + /** + * Constructor, used when composing a M-Send.req pdu. + * + * @param contentType the content type value + * @param from the from value + * @param mmsVersion current viersion of mms + * @param transactionId the transaction-id value + * @throws InvalidHeaderValueException if parameters are invalid. + * NullPointerException if contentType, form or transactionId is null. + */ + public SendReq(byte[] contentType, + EncodedStringValue from, + int mmsVersion, + byte[] transactionId) throws InvalidHeaderValueException { + super(); + setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ); + setContentType(contentType); + setFrom(from); + setMmsVersion(mmsVersion); + setTransactionId(transactionId); + } + + /** + * Constructor with given headers. + * + * @param headers Headers for this PDU. + */ + SendReq(PduHeaders headers) { + super(headers); + } + + /** + * Constructor with given headers and body + * + * @param headers Headers for this PDU. + * @param body Body of this PDu. + */ + @UnsupportedAppUsage + SendReq(PduHeaders headers, PduBody body) { + super(headers, body); + } + + /** + * Get Bcc value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue[] getBcc() { + return mPduHeaders.getEncodedStringValues(PduHeaders.BCC); + } + + /** + * Add a "BCC" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void addBcc(EncodedStringValue value) { + mPduHeaders.appendEncodedStringValue(value, PduHeaders.BCC); + } + + /** + * Set "BCC" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setBcc(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.BCC); + } + + /** + * Get CC value. + * + * @return the value + */ + @UnsupportedAppUsage + public EncodedStringValue[] getCc() { + return mPduHeaders.getEncodedStringValues(PduHeaders.CC); + } + + /** + * Add a "CC" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void addCc(EncodedStringValue value) { + mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC); + } + + /** + * Set "CC" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setCc(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.CC); + } + + /** + * Get Content-type value. + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getContentType() { + return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE); + } + + /** + * Set Content-type value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setContentType(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE); + } + + /** + * Get X-Mms-Delivery-Report value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getDeliveryReport() { + return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT); + } + + /** + * Set X-Mms-Delivery-Report value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setDeliveryReport(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT); + } + + /** + * Get X-Mms-Expiry value. + * + * Expiry-value = Value-length + * (Absolute-token Date-value | Relative-token Delta-seconds-value) + * + * @return the value + */ + @UnsupportedAppUsage + public long getExpiry() { + return mPduHeaders.getLongInteger(PduHeaders.EXPIRY); + } + + /** + * Set X-Mms-Expiry value. + * + * @param value the value + */ + @UnsupportedAppUsage + public void setExpiry(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY); + } + + /** + * Get X-Mms-MessageSize value. + * + * Expiry-value = size of message + * + * @return the value + */ + @UnsupportedAppUsage + public long getMessageSize() { + return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE); + } + + /** + * Set X-Mms-MessageSize value. + * + * @param value the value + */ + @UnsupportedAppUsage + public void setMessageSize(long value) { + mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE); + } + + /** + * Get X-Mms-Message-Class value. + * Message-class-value = Class-identifier | Token-text + * Class-identifier = Personal | Advertisement | Informational | Auto + * + * @return the value + */ + @UnsupportedAppUsage + public byte[] getMessageClass() { + return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS); + } + + /** + * Set X-Mms-Message-Class value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setMessageClass(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS); + } + + /** + * Get X-Mms-Read-Report value. + * + * @return the value + */ + @UnsupportedAppUsage + public int getReadReport() { + return mPduHeaders.getOctet(PduHeaders.READ_REPORT); + } + + /** + * Set X-Mms-Read-Report value. + * + * @param value the value + * @throws InvalidHeaderValueException if the value is invalid. + */ + @UnsupportedAppUsage + public void setReadReport(int value) throws InvalidHeaderValueException { + mPduHeaders.setOctet(value, PduHeaders.READ_REPORT); + } + + /** + * Set "To" value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setTo(EncodedStringValue[] value) { + mPduHeaders.setEncodedStringValues(value, PduHeaders.TO); + } + + /** + * Get X-Mms-Transaction-Id field value. + * + * @return the X-Mms-Report-Allowed value + */ + @UnsupportedAppUsage + public byte[] getTransactionId() { + return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID); + } + + /** + * Set X-Mms-Transaction-Id field value. + * + * @param value the value + * @throws NullPointerException if the value is null. + */ + @UnsupportedAppUsage + public void setTransactionId(byte[] value) { + mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID); + } + + /* + * Optional, not supported header fields: + * + * public byte getAdaptationAllowed() {return 0}; + * public void setAdaptationAllowed(btye value) {}; + * + * public byte[] getApplicId() {return null;} + * public void setApplicId(byte[] value) {} + * + * public byte[] getAuxApplicId() {return null;} + * public void getAuxApplicId(byte[] value) {} + * + * public byte getContentClass() {return 0x00;} + * public void setApplicId(byte value) {} + * + * public long getDeliveryTime() {return 0}; + * public void setDeliveryTime(long value) {}; + * + * public byte getDrmContent() {return 0x00;} + * public void setDrmContent(byte value) {} + * + * public MmFlagsValue getMmFlags() {return null;} + * public void setMmFlags(MmFlagsValue value) {} + * + * public MmStateValue getMmState() {return null;} + * public void getMmState(MmStateValue value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + * + * public byte getReplyCharging() {return 0x00;} + * public void setReplyCharging(byte value) {} + * + * public byte getReplyChargingDeadline() {return 0x00;} + * public void setReplyChargingDeadline(byte value) {} + * + * public byte[] getReplyChargingId() {return 0x00;} + * public void setReplyChargingId(byte[] value) {} + * + * public long getReplyChargingSize() {return 0;} + * public void setReplyChargingSize(long value) {} + * + * public byte[] getReplyApplicId() {return 0x00;} + * public void setReplyApplicId(byte[] value) {} + * + * public byte getStore() {return 0x00;} + * public void setStore(byte value) {} + */ +} diff --git a/telephony/common/com/google/android/mms/pdu/package.html b/telephony/common/com/google/android/mms/pdu/package.html new file mode 100755 index 000000000000..c9f96a66ab3b --- /dev/null +++ b/telephony/common/com/google/android/mms/pdu/package.html @@ -0,0 +1,5 @@ +<body> + +{@hide} + +</body> diff --git a/telephony/common/com/google/android/mms/util/AbstractCache.java b/telephony/common/com/google/android/mms/util/AbstractCache.java new file mode 100644 index 000000000000..ab5d48a4ce3d --- /dev/null +++ b/telephony/common/com/google/android/mms/util/AbstractCache.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008 Esmertec AG. + * Copyright (C) 2008 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.google.android.mms.util; + +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.util.HashMap; + +public abstract class AbstractCache<K, V> { + private static final String TAG = "AbstractCache"; + private static final boolean DEBUG = false; + private static final boolean LOCAL_LOGV = false; + + private static final int MAX_CACHED_ITEMS = 500; + + private final HashMap<K, CacheEntry<V>> mCacheMap; + + @UnsupportedAppUsage + protected AbstractCache() { + mCacheMap = new HashMap<K, CacheEntry<V>>(); + } + + @UnsupportedAppUsage + public boolean put(K key, V value) { + if (LOCAL_LOGV) { + Log.v(TAG, "Trying to put " + key + " into cache."); + } + + if (mCacheMap.size() >= MAX_CACHED_ITEMS) { + // TODO Should remove the oldest or least hit cached entry + // and then cache the new one. + if (LOCAL_LOGV) { + Log.v(TAG, "Failed! size limitation reached."); + } + return false; + } + + if (key != null) { + CacheEntry<V> cacheEntry = new CacheEntry<V>(); + cacheEntry.value = value; + mCacheMap.put(key, cacheEntry); + + if (LOCAL_LOGV) { + Log.v(TAG, key + " cached, " + mCacheMap.size() + " items total."); + } + return true; + } + return false; + } + + @UnsupportedAppUsage + public V get(K key) { + if (LOCAL_LOGV) { + Log.v(TAG, "Trying to get " + key + " from cache."); + } + + if (key != null) { + CacheEntry<V> cacheEntry = mCacheMap.get(key); + if (cacheEntry != null) { + cacheEntry.hit++; + if (LOCAL_LOGV) { + Log.v(TAG, key + " hit " + cacheEntry.hit + " times."); + } + return cacheEntry.value; + } + } + return null; + } + + @UnsupportedAppUsage + public V purge(K key) { + if (LOCAL_LOGV) { + Log.v(TAG, "Trying to purge " + key); + } + + CacheEntry<V> v = mCacheMap.remove(key); + + if (LOCAL_LOGV) { + Log.v(TAG, mCacheMap.size() + " items cached."); + } + + return v != null ? v.value : null; + } + + @UnsupportedAppUsage + public void purgeAll() { + if (LOCAL_LOGV) { + Log.v(TAG, "Purging cache, " + mCacheMap.size() + + " items dropped."); + } + mCacheMap.clear(); + } + + public int size() { + return mCacheMap.size(); + } + + private static class CacheEntry<V> { + int hit; + V value; + } +} diff --git a/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java new file mode 100644 index 000000000000..118de465a518 --- /dev/null +++ b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012 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.google.android.mms.util; + +import android.content.Context; +import android.drm.DrmManagerClient; +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +public class DownloadDrmHelper { + private static final String TAG = "DownloadDrmHelper"; + + /** The MIME type of special DRM files */ + public static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message"; + + /** The extensions of special DRM files */ + public static final String EXTENSION_DRM_MESSAGE = ".dm"; + + public static final String EXTENSION_INTERNAL_FWDL = ".fl"; + + /** + * Checks if the Media Type is a DRM Media Type + * + * @param drmManagerClient A DrmManagerClient + * @param mimetype Media Type to check + * @return True if the Media Type is DRM else false + */ + public static boolean isDrmMimeType(Context context, String mimetype) { + boolean result = false; + if (context != null) { + try { + DrmManagerClient drmClient = new DrmManagerClient(context); + if (drmClient != null && mimetype != null && mimetype.length() > 0) { + result = drmClient.canHandle("", mimetype); + } + } catch (IllegalArgumentException e) { + Log.w(TAG, + "DrmManagerClient instance could not be created, context is Illegal."); + } catch (IllegalStateException e) { + Log.w(TAG, "DrmManagerClient didn't initialize properly."); + } + } + return result; + } + + /** + * Checks if the Media Type needs to be DRM converted + * + * @param mimetype Media type of the content + * @return True if convert is needed else false + */ + @UnsupportedAppUsage + public static boolean isDrmConvertNeeded(String mimetype) { + return MIMETYPE_DRM_MESSAGE.equals(mimetype); + } + + /** + * Modifies the file extension for a DRM Forward Lock file NOTE: This + * function shouldn't be called if the file shouldn't be DRM converted + */ + @UnsupportedAppUsage + public static String modifyDrmFwLockFileExtension(String filename) { + if (filename != null) { + int extensionIndex; + extensionIndex = filename.lastIndexOf("."); + if (extensionIndex != -1) { + filename = filename.substring(0, extensionIndex); + } + filename = filename.concat(EXTENSION_INTERNAL_FWDL); + } + return filename; + } + + /** + * Gets the original mime type of DRM protected content. + * + * @param context The context + * @param path Path to the file + * @param containingMime The current mime type of the file i.e. the + * containing mime type + * @return The original mime type of the file if DRM protected else the + * currentMime + */ + public static String getOriginalMimeType(Context context, String path, String containingMime) { + String result = containingMime; + DrmManagerClient drmClient = new DrmManagerClient(context); + try { + if (drmClient.canHandle(path, null)) { + result = drmClient.getOriginalMimeType(path); + } + } catch (IllegalArgumentException ex) { + Log.w(TAG, + "Can't get original mime type since path is null or empty string."); + } catch (IllegalStateException ex) { + Log.w(TAG, "DrmManagerClient didn't initialize properly."); + } + return result; + } +} diff --git a/telephony/common/com/google/android/mms/util/DrmConvertSession.java b/telephony/common/com/google/android/mms/util/DrmConvertSession.java new file mode 100644 index 000000000000..0e8ec91f4ef6 --- /dev/null +++ b/telephony/common/com/google/android/mms/util/DrmConvertSession.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2012 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.google.android.mms.util; + +import android.content.Context; +import android.drm.DrmConvertedStatus; +import android.drm.DrmManagerClient; +import android.provider.Downloads; +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + + +public class DrmConvertSession { + private DrmManagerClient mDrmClient; + private int mConvertSessionId; + private static final String TAG = "DrmConvertSession"; + + private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) { + mDrmClient = drmClient; + mConvertSessionId = convertSessionId; + } + + /** + * Start of converting a file. + * + * @param context The context of the application running the convert session. + * @param mimeType Mimetype of content that shall be converted. + * @return A convert session or null in case an error occurs. + */ + @UnsupportedAppUsage + public static DrmConvertSession open(Context context, String mimeType) { + DrmManagerClient drmClient = null; + int convertSessionId = -1; + if (context != null && mimeType != null && !mimeType.equals("")) { + try { + drmClient = new DrmManagerClient(context); + try { + convertSessionId = drmClient.openConvertSession(mimeType); + } catch (IllegalArgumentException e) { + Log.w(TAG, "Conversion of Mimetype: " + mimeType + + " is not supported.", e); + } catch (IllegalStateException e) { + Log.w(TAG, "Could not access Open DrmFramework.", e); + } + } catch (IllegalArgumentException e) { + Log.w(TAG, + "DrmManagerClient instance could not be created, context is Illegal."); + } catch (IllegalStateException e) { + Log.w(TAG, "DrmManagerClient didn't initialize properly."); + } + } + + if (drmClient == null || convertSessionId < 0) { + return null; + } else { + return new DrmConvertSession(drmClient, convertSessionId); + } + } + /** + * Convert a buffer of data to protected format. + * + * @param buffer Buffer filled with data to convert. + * @param size The number of bytes that shall be converted. + * @return A Buffer filled with converted data, if execution is ok, in all + * other case null. + */ + @UnsupportedAppUsage + public byte [] convert(byte[] inBuffer, int size) { + byte[] result = null; + if (inBuffer != null) { + DrmConvertedStatus convertedStatus = null; + try { + if (size != inBuffer.length) { + byte[] buf = new byte[size]; + System.arraycopy(inBuffer, 0, buf, 0, size); + convertedStatus = mDrmClient.convertData(mConvertSessionId, buf); + } else { + convertedStatus = mDrmClient.convertData(mConvertSessionId, inBuffer); + } + + if (convertedStatus != null && + convertedStatus.statusCode == DrmConvertedStatus.STATUS_OK && + convertedStatus.convertedData != null) { + result = convertedStatus.convertedData; + } + } catch (IllegalArgumentException e) { + Log.w(TAG, "Buffer with data to convert is illegal. Convertsession: " + + mConvertSessionId, e); + } catch (IllegalStateException e) { + Log.w(TAG, "Could not convert data. Convertsession: " + + mConvertSessionId, e); + } + } else { + throw new IllegalArgumentException("Parameter inBuffer is null"); + } + return result; + } + + /** + * Ends a conversion session of a file. + * + * @param fileName The filename of the converted file. + * @return Downloads.Impl.STATUS_SUCCESS if execution is ok. + * Downloads.Impl.STATUS_FILE_ERROR in case converted file can not + * be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem + * occurs when accessing drm framework. + * Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred. + */ + @UnsupportedAppUsage + public int close(String filename) { + DrmConvertedStatus convertedStatus = null; + int result = Downloads.Impl.STATUS_UNKNOWN_ERROR; + if (mDrmClient != null && mConvertSessionId >= 0) { + try { + convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId); + if (convertedStatus == null || + convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK || + convertedStatus.convertedData == null) { + result = Downloads.Impl.STATUS_NOT_ACCEPTABLE; + } else { + RandomAccessFile rndAccessFile = null; + try { + rndAccessFile = new RandomAccessFile(filename, "rw"); + rndAccessFile.seek(convertedStatus.offset); + rndAccessFile.write(convertedStatus.convertedData); + result = Downloads.Impl.STATUS_SUCCESS; + } catch (FileNotFoundException e) { + result = Downloads.Impl.STATUS_FILE_ERROR; + Log.w(TAG, "File: " + filename + " could not be found.", e); + } catch (IOException e) { + result = Downloads.Impl.STATUS_FILE_ERROR; + Log.w(TAG, "Could not access File: " + filename + " .", e); + } catch (IllegalArgumentException e) { + result = Downloads.Impl.STATUS_FILE_ERROR; + Log.w(TAG, "Could not open file in mode: rw", e); + } catch (SecurityException e) { + Log.w(TAG, "Access to File: " + filename + + " was denied denied by SecurityManager.", e); + } finally { + if (rndAccessFile != null) { + try { + rndAccessFile.close(); + } catch (IOException e) { + result = Downloads.Impl.STATUS_FILE_ERROR; + Log.w(TAG, "Failed to close File:" + filename + + ".", e); + } + } + } + } + } catch (IllegalStateException e) { + Log.w(TAG, "Could not close convertsession. Convertsession: " + + mConvertSessionId, e); + } + } + return result; + } +} diff --git a/telephony/common/com/google/android/mms/util/PduCache.java b/telephony/common/com/google/android/mms/util/PduCache.java new file mode 100644 index 000000000000..94e38946f632 --- /dev/null +++ b/telephony/common/com/google/android/mms/util/PduCache.java @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2008 Esmertec AG. + * Copyright (C) 2008 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.google.android.mms.util; + +import android.content.ContentUris; +import android.content.UriMatcher; +import android.net.Uri; +import android.provider.Telephony.Mms; +import android.util.Log; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.util.HashMap; +import java.util.HashSet; + +public final class PduCache extends AbstractCache<Uri, PduCacheEntry> { + private static final String TAG = "PduCache"; + private static final boolean DEBUG = false; + private static final boolean LOCAL_LOGV = false; + + private static final int MMS_ALL = 0; + private static final int MMS_ALL_ID = 1; + private static final int MMS_INBOX = 2; + private static final int MMS_INBOX_ID = 3; + private static final int MMS_SENT = 4; + private static final int MMS_SENT_ID = 5; + private static final int MMS_DRAFTS = 6; + private static final int MMS_DRAFTS_ID = 7; + private static final int MMS_OUTBOX = 8; + private static final int MMS_OUTBOX_ID = 9; + private static final int MMS_CONVERSATION = 10; + private static final int MMS_CONVERSATION_ID = 11; + + private static final UriMatcher URI_MATCHER; + private static final HashMap<Integer, Integer> MATCH_TO_MSGBOX_ID_MAP; + + private static PduCache sInstance; + + static { + URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); + URI_MATCHER.addURI("mms", null, MMS_ALL); + URI_MATCHER.addURI("mms", "#", MMS_ALL_ID); + URI_MATCHER.addURI("mms", "inbox", MMS_INBOX); + URI_MATCHER.addURI("mms", "inbox/#", MMS_INBOX_ID); + URI_MATCHER.addURI("mms", "sent", MMS_SENT); + URI_MATCHER.addURI("mms", "sent/#", MMS_SENT_ID); + URI_MATCHER.addURI("mms", "drafts", MMS_DRAFTS); + URI_MATCHER.addURI("mms", "drafts/#", MMS_DRAFTS_ID); + URI_MATCHER.addURI("mms", "outbox", MMS_OUTBOX); + URI_MATCHER.addURI("mms", "outbox/#", MMS_OUTBOX_ID); + URI_MATCHER.addURI("mms-sms", "conversations", MMS_CONVERSATION); + URI_MATCHER.addURI("mms-sms", "conversations/#", MMS_CONVERSATION_ID); + + MATCH_TO_MSGBOX_ID_MAP = new HashMap<Integer, Integer>(); + MATCH_TO_MSGBOX_ID_MAP.put(MMS_INBOX, Mms.MESSAGE_BOX_INBOX); + MATCH_TO_MSGBOX_ID_MAP.put(MMS_SENT, Mms.MESSAGE_BOX_SENT); + MATCH_TO_MSGBOX_ID_MAP.put(MMS_DRAFTS, Mms.MESSAGE_BOX_DRAFTS); + MATCH_TO_MSGBOX_ID_MAP.put(MMS_OUTBOX, Mms.MESSAGE_BOX_OUTBOX); + } + + private final HashMap<Integer, HashSet<Uri>> mMessageBoxes; + private final HashMap<Long, HashSet<Uri>> mThreads; + private final HashSet<Uri> mUpdating; + + @UnsupportedAppUsage + private PduCache() { + mMessageBoxes = new HashMap<Integer, HashSet<Uri>>(); + mThreads = new HashMap<Long, HashSet<Uri>>(); + mUpdating = new HashSet<Uri>(); + } + + @UnsupportedAppUsage + synchronized public static final PduCache getInstance() { + if (sInstance == null) { + if (LOCAL_LOGV) { + Log.v(TAG, "Constructing new PduCache instance."); + } + sInstance = new PduCache(); + } + return sInstance; + } + + @Override + synchronized public boolean put(Uri uri, PduCacheEntry entry) { + int msgBoxId = entry.getMessageBox(); + HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId); + if (msgBox == null) { + msgBox = new HashSet<Uri>(); + mMessageBoxes.put(msgBoxId, msgBox); + } + + long threadId = entry.getThreadId(); + HashSet<Uri> thread = mThreads.get(threadId); + if (thread == null) { + thread = new HashSet<Uri>(); + mThreads.put(threadId, thread); + } + + Uri finalKey = normalizeKey(uri); + boolean result = super.put(finalKey, entry); + if (result) { + msgBox.add(finalKey); + thread.add(finalKey); + } + setUpdating(uri, false); + return result; + } + + synchronized public void setUpdating(Uri uri, boolean updating) { + if (updating) { + mUpdating.add(uri); + } else { + mUpdating.remove(uri); + } + } + + @UnsupportedAppUsage + synchronized public boolean isUpdating(Uri uri) { + return mUpdating.contains(uri); + } + + @Override + @UnsupportedAppUsage + synchronized public PduCacheEntry purge(Uri uri) { + int match = URI_MATCHER.match(uri); + switch (match) { + case MMS_ALL_ID: + return purgeSingleEntry(uri); + case MMS_INBOX_ID: + case MMS_SENT_ID: + case MMS_DRAFTS_ID: + case MMS_OUTBOX_ID: + String msgId = uri.getLastPathSegment(); + return purgeSingleEntry(Uri.withAppendedPath(Mms.CONTENT_URI, msgId)); + // Implicit batch of purge, return null. + case MMS_ALL: + case MMS_CONVERSATION: + purgeAll(); + return null; + case MMS_INBOX: + case MMS_SENT: + case MMS_DRAFTS: + case MMS_OUTBOX: + purgeByMessageBox(MATCH_TO_MSGBOX_ID_MAP.get(match)); + return null; + case MMS_CONVERSATION_ID: + purgeByThreadId(ContentUris.parseId(uri)); + return null; + default: + return null; + } + } + + private PduCacheEntry purgeSingleEntry(Uri key) { + mUpdating.remove(key); + PduCacheEntry entry = super.purge(key); + if (entry != null) { + removeFromThreads(key, entry); + removeFromMessageBoxes(key, entry); + return entry; + } + return null; + } + + @UnsupportedAppUsage + @Override + synchronized public void purgeAll() { + super.purgeAll(); + + mMessageBoxes.clear(); + mThreads.clear(); + mUpdating.clear(); + } + + /** + * @param uri The Uri to be normalized. + * @return Uri The normalized key of cached entry. + */ + private Uri normalizeKey(Uri uri) { + int match = URI_MATCHER.match(uri); + Uri normalizedKey = null; + + switch (match) { + case MMS_ALL_ID: + normalizedKey = uri; + break; + case MMS_INBOX_ID: + case MMS_SENT_ID: + case MMS_DRAFTS_ID: + case MMS_OUTBOX_ID: + String msgId = uri.getLastPathSegment(); + normalizedKey = Uri.withAppendedPath(Mms.CONTENT_URI, msgId); + break; + default: + return null; + } + + if (LOCAL_LOGV) { + Log.v(TAG, uri + " -> " + normalizedKey); + } + return normalizedKey; + } + + private void purgeByMessageBox(Integer msgBoxId) { + if (LOCAL_LOGV) { + Log.v(TAG, "Purge cache in message box: " + msgBoxId); + } + + if (msgBoxId != null) { + HashSet<Uri> msgBox = mMessageBoxes.remove(msgBoxId); + if (msgBox != null) { + for (Uri key : msgBox) { + mUpdating.remove(key); + PduCacheEntry entry = super.purge(key); + if (entry != null) { + removeFromThreads(key, entry); + } + } + } + } + } + + private void removeFromThreads(Uri key, PduCacheEntry entry) { + HashSet<Uri> thread = mThreads.get(entry.getThreadId()); + if (thread != null) { + thread.remove(key); + } + } + + private void purgeByThreadId(long threadId) { + if (LOCAL_LOGV) { + Log.v(TAG, "Purge cache in thread: " + threadId); + } + + HashSet<Uri> thread = mThreads.remove(threadId); + if (thread != null) { + for (Uri key : thread) { + mUpdating.remove(key); + PduCacheEntry entry = super.purge(key); + if (entry != null) { + removeFromMessageBoxes(key, entry); + } + } + } + } + + private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) { + HashSet<Uri> msgBox = mThreads.get(Long.valueOf(entry.getMessageBox())); + if (msgBox != null) { + msgBox.remove(key); + } + } +} diff --git a/telephony/common/com/google/android/mms/util/PduCacheEntry.java b/telephony/common/com/google/android/mms/util/PduCacheEntry.java new file mode 100644 index 000000000000..1ecd1bf93e7f --- /dev/null +++ b/telephony/common/com/google/android/mms/util/PduCacheEntry.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Esmertec AG. + * Copyright (C) 2008 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.google.android.mms.util; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +import com.google.android.mms.pdu.GenericPdu; + +public final class PduCacheEntry { + private final GenericPdu mPdu; + private final int mMessageBox; + private final long mThreadId; + + @UnsupportedAppUsage + public PduCacheEntry(GenericPdu pdu, int msgBox, long threadId) { + mPdu = pdu; + mMessageBox = msgBox; + mThreadId = threadId; + } + + @UnsupportedAppUsage + public GenericPdu getPdu() { + return mPdu; + } + + @UnsupportedAppUsage + public int getMessageBox() { + return mMessageBox; + } + + @UnsupportedAppUsage + public long getThreadId() { + return mThreadId; + } +} diff --git a/telephony/common/com/google/android/mms/util/SqliteWrapper.java b/telephony/common/com/google/android/mms/util/SqliteWrapper.java new file mode 100644 index 000000000000..2dd1dc11c2a9 --- /dev/null +++ b/telephony/common/com/google/android/mms/util/SqliteWrapper.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 Esmertec AG. + * Copyright (C) 2008 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.google.android.mms.util; + +import android.app.ActivityManager; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.net.Uri; +import android.util.Log; +import android.widget.Toast; + +import dalvik.annotation.compat.UnsupportedAppUsage; + +public final class SqliteWrapper { + private static final String TAG = "SqliteWrapper"; + private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE + = "unable to open database file"; + + private SqliteWrapper() { + // Forbidden being instantiated. + } + + // FIXME: It looks like outInfo.lowMemory does not work well as we expected. + // after run command: adb shell fillup -p 100, outInfo.lowMemory is still false. + private static boolean isLowMemory(Context context) { + if (null == context) { + return false; + } + + ActivityManager am = (ActivityManager) + context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo(); + am.getMemoryInfo(outInfo); + + return outInfo.lowMemory; + } + + // FIXME: need to optimize this method. + private static boolean isLowMemory(SQLiteException e) { + return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE); + } + + @UnsupportedAppUsage + public static void checkSQLiteException(Context context, SQLiteException e) { + if (isLowMemory(e)) { + Toast.makeText(context, com.android.internal.R.string.low_memory, + Toast.LENGTH_SHORT).show(); + } else { + throw e; + } + } + + @UnsupportedAppUsage + public static Cursor query(Context context, ContentResolver resolver, Uri uri, + String[] projection, String selection, String[] selectionArgs, String sortOrder) { + try { + return resolver.query(uri, projection, selection, selectionArgs, sortOrder); + } catch (SQLiteException e) { + Log.e(TAG, "Catch a SQLiteException when query: ", e); + checkSQLiteException(context, e); + return null; + } + } + + @UnsupportedAppUsage + public static boolean requery(Context context, Cursor cursor) { + try { + return cursor.requery(); + } catch (SQLiteException e) { + Log.e(TAG, "Catch a SQLiteException when requery: ", e); + checkSQLiteException(context, e); + return false; + } + } + @UnsupportedAppUsage + public static int update(Context context, ContentResolver resolver, Uri uri, + ContentValues values, String where, String[] selectionArgs) { + try { + return resolver.update(uri, values, where, selectionArgs); + } catch (SQLiteException e) { + Log.e(TAG, "Catch a SQLiteException when update: ", e); + checkSQLiteException(context, e); + return -1; + } + } + + @UnsupportedAppUsage + public static int delete(Context context, ContentResolver resolver, Uri uri, + String where, String[] selectionArgs) { + try { + return resolver.delete(uri, where, selectionArgs); + } catch (SQLiteException e) { + Log.e(TAG, "Catch a SQLiteException when delete: ", e); + checkSQLiteException(context, e); + return -1; + } + } + + @UnsupportedAppUsage + public static Uri insert(Context context, ContentResolver resolver, + Uri uri, ContentValues values) { + try { + return resolver.insert(uri, values); + } catch (SQLiteException e) { + Log.e(TAG, "Catch a SQLiteException when insert: ", e); + checkSQLiteException(context, e); + return null; + } + } +} diff --git a/telephony/common/com/google/android/mms/util/package.html b/telephony/common/com/google/android/mms/util/package.html new file mode 100755 index 000000000000..c9f96a66ab3b --- /dev/null +++ b/telephony/common/com/google/android/mms/util/package.html @@ -0,0 +1,5 @@ +<body> + +{@hide} + +</body> diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index d3728a6dd178..087937d5ade2 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -16,6 +16,7 @@ package android.provider; +import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -1126,8 +1127,9 @@ public final class Telephony { * values:</p> * * <ul> - * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message - * data, including ETWS or CMAS warning notification info if present.</li> + * <li><em>"message"</em> - An {@link android.telephony.SmsCbMessage} object + * containing the broadcast message data, including ETWS or CMAS warning notification + * info if present.</li> * </ul> * * <p>The extra values can be extracted using @@ -1138,11 +1140,12 @@ public final class Telephony { * * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST} to * receive.</p> - * @removed + * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION = - "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; + @SystemApi + public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = + "android.provider.action.SMS_EMERGENCY_CB_RECEIVED"; /** * Broadcast Action: A new CDMA SMS has been received containing Service Category @@ -3944,10 +3947,11 @@ public final class Telephony { } /** - * Contains received SMS cell broadcast messages. More details are available in 3GPP TS 23.041. + * Contains received cell broadcast messages. More details are available in 3GPP TS 23.041. * @hide */ @SystemApi + @TestApi public static final class CellBroadcasts implements BaseColumns { /** @@ -3958,11 +3962,44 @@ public final class Telephony { /** * The {@code content://} URI for this table. + * Only privileged framework components running on phone or network stack uid can + * query or modify this table. */ @NonNull public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); /** + * The {@code content://} URI for query cellbroadcast message history. + * query results include following entries + * <ul> + * <li>{@link #_ID}</li> + * <li>{@link #SLOT_INDEX}</li> + * <li>{@link #GEOGRAPHICAL_SCOPE}</li> + * <li>{@link #PLMN}</li> + * <li>{@link #LAC}</li> + * <li>{@link #CID}</li> + * <li>{@link #SERIAL_NUMBER}</li> + * <li>{@link #SERVICE_CATEGORY}</li> + * <li>{@link #LANGUAGE_CODE}</li> + * <li>{@link #MESSAGE_BODY}</li> + * <li>{@link #DELIVERY_TIME}</li> + * <li>{@link #MESSAGE_READ}</li> + * <li>{@link #MESSAGE_FORMAT}</li> + * <li>{@link #MESSAGE_PRIORITY}</li> + * <li>{@link #ETWS_WARNING_TYPE}</li> + * <li>{@link #CMAS_MESSAGE_CLASS}</li> + * <li>{@link #CMAS_CATEGORY}</li> + * <li>{@link #CMAS_RESPONSE_TYPE}</li> + * <li>{@link #CMAS_SEVERITY}</li> + * <li>{@link #CMAS_URGENCY}</li> + * <li>{@link #CMAS_CERTAINTY}</li> + * </ul> + */ + @RequiresPermission(Manifest.permission.READ_CELL_BROADCASTS) + @NonNull + public static final Uri MESSAGE_HISTORY_URI = Uri.parse("content://cellbroadcasts/history"); + + /** * The subscription which received this cell broadcast message. * @deprecated use {@link #SLOT_INDEX} instead. * <P>Type: INTEGER</P> @@ -3973,7 +4010,6 @@ public final class Telephony { /** * The slot which received this cell broadcast message. * <P>Type: INTEGER</P> - * @hide */ public static final String SLOT_INDEX = "slot_index"; @@ -4151,14 +4187,12 @@ public final class Telephony { /** * The timestamp in millisecond of when the device received the message. * <P>Type: BIGINT</P> - * @hide */ public static final String RECEIVED_TIME = "received_time"; /** * Indicates that whether the message has been broadcasted to the application. * <P>Type: BOOLEAN</P> - * @hide */ public static final String MESSAGE_BROADCASTED = "message_broadcasted"; @@ -4194,7 +4228,6 @@ public final class Telephony { * "circle|0,0|100;polygon|0,0|0,1.5|1,1|1,0;circle|100.123,100|200.123" * * <P>Type: TEXT</P> - * @hide */ public static final String GEOMETRIES = "geometries"; @@ -4206,7 +4239,6 @@ public final class Telephony { * for the alert. * * <P>Type: INTEGER</P> - * @hide */ public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index afa35b4d4de3..a0aa60b74ba0 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -45,6 +45,7 @@ public final class AccessNetworkConstants { * @hide */ @SystemApi + @TestApi public static final int TRANSPORT_TYPE_INVALID = -1; /** diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java new file mode 100644 index 000000000000..a884a7039d5b --- /dev/null +++ b/telephony/java/android/telephony/Annotation.java @@ -0,0 +1,472 @@ +package android.telephony; + +import android.annotation.IntDef; +import android.telephony.data.ApnSetting; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Telephony Annotations. + * Telephony sdk is a mainline module and others cannot reference hidden @IntDef. Moving some + * telephony annotations to a separate class to allow others statically link to it. + * + * @hide + */ +public class Annotation { + @IntDef(prefix = {"DATA_"}, value = { + TelephonyManager.DATA_ACTIVITY_NONE, + TelephonyManager.DATA_ACTIVITY_IN, + TelephonyManager.DATA_ACTIVITY_OUT, + TelephonyManager.DATA_ACTIVITY_INOUT, + TelephonyManager.DATA_ACTIVITY_DORMANT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DataActivityType { + } + + @IntDef(prefix = {"DATA_"}, value = { + TelephonyManager.DATA_UNKNOWN, + TelephonyManager.DATA_DISCONNECTED, + TelephonyManager.DATA_CONNECTING, + TelephonyManager.DATA_CONNECTED, + TelephonyManager.DATA_SUSPENDED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DataState { + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"RADIO_POWER_"}, + value = { + TelephonyManager.RADIO_POWER_OFF, + TelephonyManager.RADIO_POWER_ON, + TelephonyManager.RADIO_POWER_UNAVAILABLE, + }) + public @interface RadioPowerState { + } + + @IntDef({ + TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN, + TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATING, + TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATED, + TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED, + TelephonyManager.SIM_ACTIVATION_STATE_RESTRICTED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SimActivationState { + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"SRVCC_STATE_"}, + value = { + TelephonyManager.SRVCC_STATE_HANDOVER_NONE, + TelephonyManager.SRVCC_STATE_HANDOVER_STARTED, + TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED, + TelephonyManager.SRVCC_STATE_HANDOVER_FAILED, + TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED}) + public @interface SrvccState { + } + + @IntDef(prefix = {"CALL_STATE_"}, value = { + TelephonyManager.CALL_STATE_IDLE, + TelephonyManager.CALL_STATE_RINGING, + TelephonyManager.CALL_STATE_OFFHOOK + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CallState { + } + + @IntDef({ + TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyManager.NETWORK_TYPE_GPRS, + TelephonyManager.NETWORK_TYPE_EDGE, + TelephonyManager.NETWORK_TYPE_UMTS, + TelephonyManager.NETWORK_TYPE_CDMA, + TelephonyManager.NETWORK_TYPE_EVDO_0, + TelephonyManager.NETWORK_TYPE_EVDO_A, + TelephonyManager.NETWORK_TYPE_1xRTT, + TelephonyManager.NETWORK_TYPE_HSDPA, + TelephonyManager.NETWORK_TYPE_HSUPA, + TelephonyManager.NETWORK_TYPE_HSPA, + TelephonyManager.NETWORK_TYPE_IDEN, + TelephonyManager.NETWORK_TYPE_EVDO_B, + TelephonyManager.NETWORK_TYPE_LTE, + TelephonyManager.NETWORK_TYPE_EHRPD, + TelephonyManager.NETWORK_TYPE_HSPAP, + TelephonyManager.NETWORK_TYPE_GSM, + TelephonyManager.NETWORK_TYPE_TD_SCDMA, + TelephonyManager.NETWORK_TYPE_IWLAN, + TelephonyManager.NETWORK_TYPE_LTE_CA, + TelephonyManager.NETWORK_TYPE_NR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NetworkType { + } + + @IntDef(flag = true, prefix = {"TYPE_"}, value = { + ApnSetting.TYPE_DEFAULT, + ApnSetting.TYPE_MMS, + ApnSetting.TYPE_SUPL, + ApnSetting.TYPE_DUN, + ApnSetting.TYPE_HIPRI, + ApnSetting.TYPE_FOTA, + ApnSetting.TYPE_IMS, + ApnSetting.TYPE_CBS, + ApnSetting.TYPE_IA, + ApnSetting.TYPE_EMERGENCY, + ApnSetting.TYPE_MCX + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ApnType { + } + + @IntDef(value = { + DataFailCause.NONE, + DataFailCause.OPERATOR_BARRED, + DataFailCause.NAS_SIGNALLING, + DataFailCause.LLC_SNDCP, + DataFailCause.INSUFFICIENT_RESOURCES, + DataFailCause.MISSING_UNKNOWN_APN, + DataFailCause.UNKNOWN_PDP_ADDRESS_TYPE, + DataFailCause.USER_AUTHENTICATION, + DataFailCause.ACTIVATION_REJECT_GGSN, + DataFailCause.ACTIVATION_REJECT_UNSPECIFIED, + DataFailCause.SERVICE_OPTION_NOT_SUPPORTED, + DataFailCause.SERVICE_OPTION_NOT_SUBSCRIBED, + DataFailCause.SERVICE_OPTION_OUT_OF_ORDER, + DataFailCause.NSAPI_IN_USE, + DataFailCause.REGULAR_DEACTIVATION, + DataFailCause.QOS_NOT_ACCEPTED, + DataFailCause.NETWORK_FAILURE, + DataFailCause.UMTS_REACTIVATION_REQ, + DataFailCause.FEATURE_NOT_SUPP, + DataFailCause.TFT_SEMANTIC_ERROR, + DataFailCause.TFT_SYTAX_ERROR, + DataFailCause.UNKNOWN_PDP_CONTEXT, + DataFailCause.FILTER_SEMANTIC_ERROR, + DataFailCause.FILTER_SYTAX_ERROR, + DataFailCause.PDP_WITHOUT_ACTIVE_TFT, + DataFailCause.ACTIVATION_REJECTED_BCM_VIOLATION, + DataFailCause.ONLY_IPV4_ALLOWED, + DataFailCause.ONLY_IPV6_ALLOWED, + DataFailCause.ONLY_SINGLE_BEARER_ALLOWED, + DataFailCause.ESM_INFO_NOT_RECEIVED, + DataFailCause.PDN_CONN_DOES_NOT_EXIST, + DataFailCause.MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED, + DataFailCause.COLLISION_WITH_NETWORK_INITIATED_REQUEST, + DataFailCause.ONLY_IPV4V6_ALLOWED, + DataFailCause.ONLY_NON_IP_ALLOWED, + DataFailCause.UNSUPPORTED_QCI_VALUE, + DataFailCause.BEARER_HANDLING_NOT_SUPPORTED, + DataFailCause.ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED, + DataFailCause.UNSUPPORTED_APN_IN_CURRENT_PLMN, + DataFailCause.INVALID_TRANSACTION_ID, + DataFailCause.MESSAGE_INCORRECT_SEMANTIC, + DataFailCause.INVALID_MANDATORY_INFO, + DataFailCause.MESSAGE_TYPE_UNSUPPORTED, + DataFailCause.MSG_TYPE_NONCOMPATIBLE_STATE, + DataFailCause.UNKNOWN_INFO_ELEMENT, + DataFailCause.CONDITIONAL_IE_ERROR, + DataFailCause.MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE, + DataFailCause.PROTOCOL_ERRORS, + DataFailCause.APN_TYPE_CONFLICT, + DataFailCause.INVALID_PCSCF_ADDR, + DataFailCause.INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN, + DataFailCause.EMM_ACCESS_BARRED, + DataFailCause.EMERGENCY_IFACE_ONLY, + DataFailCause.IFACE_MISMATCH, + DataFailCause.COMPANION_IFACE_IN_USE, + DataFailCause.IP_ADDRESS_MISMATCH, + DataFailCause.IFACE_AND_POL_FAMILY_MISMATCH, + DataFailCause.EMM_ACCESS_BARRED_INFINITE_RETRY, + DataFailCause.AUTH_FAILURE_ON_EMERGENCY_CALL, + DataFailCause.INVALID_DNS_ADDR, + DataFailCause.INVALID_PCSCF_OR_DNS_ADDRESS, + DataFailCause.CALL_PREEMPT_BY_EMERGENCY_APN, + DataFailCause.UE_INITIATED_DETACH_OR_DISCONNECT, + DataFailCause.MIP_FA_REASON_UNSPECIFIED, + DataFailCause.MIP_FA_ADMIN_PROHIBITED, + DataFailCause.MIP_FA_INSUFFICIENT_RESOURCES, + DataFailCause.MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE, + DataFailCause.MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE, + DataFailCause.MIP_FA_REQUESTED_LIFETIME_TOO_LONG, + DataFailCause.MIP_FA_MALFORMED_REQUEST, + DataFailCause.MIP_FA_MALFORMED_REPLY, + DataFailCause.MIP_FA_ENCAPSULATION_UNAVAILABLE, + DataFailCause.MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE, + DataFailCause.MIP_FA_REVERSE_TUNNEL_UNAVAILABLE, + DataFailCause.MIP_FA_REVERSE_TUNNEL_IS_MANDATORY, + DataFailCause.MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED, + DataFailCause.MIP_FA_MISSING_NAI, + DataFailCause.MIP_FA_MISSING_HOME_AGENT, + DataFailCause.MIP_FA_MISSING_HOME_ADDRESS, + DataFailCause.MIP_FA_UNKNOWN_CHALLENGE, + DataFailCause.MIP_FA_MISSING_CHALLENGE, + DataFailCause.MIP_FA_STALE_CHALLENGE, + DataFailCause.MIP_HA_REASON_UNSPECIFIED, + DataFailCause.MIP_HA_ADMIN_PROHIBITED, + DataFailCause.MIP_HA_INSUFFICIENT_RESOURCES, + DataFailCause.MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE, + DataFailCause.MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE, + DataFailCause.MIP_HA_REGISTRATION_ID_MISMATCH, + DataFailCause.MIP_HA_MALFORMED_REQUEST, + DataFailCause.MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS, + DataFailCause.MIP_HA_REVERSE_TUNNEL_UNAVAILABLE, + DataFailCause.MIP_HA_REVERSE_TUNNEL_IS_MANDATORY, + DataFailCause.MIP_HA_ENCAPSULATION_UNAVAILABLE, + DataFailCause.CLOSE_IN_PROGRESS, + DataFailCause.NETWORK_INITIATED_TERMINATION, + DataFailCause.MODEM_APP_PREEMPTED, + DataFailCause.PDN_IPV4_CALL_DISALLOWED, + DataFailCause.PDN_IPV4_CALL_THROTTLED, + DataFailCause.PDN_IPV6_CALL_DISALLOWED, + DataFailCause.PDN_IPV6_CALL_THROTTLED, + DataFailCause.MODEM_RESTART, + DataFailCause.PDP_PPP_NOT_SUPPORTED, + DataFailCause.UNPREFERRED_RAT, + DataFailCause.PHYSICAL_LINK_CLOSE_IN_PROGRESS, + DataFailCause.APN_PENDING_HANDOVER, + DataFailCause.PROFILE_BEARER_INCOMPATIBLE, + DataFailCause.SIM_CARD_CHANGED, + DataFailCause.LOW_POWER_MODE_OR_POWERING_DOWN, + DataFailCause.APN_DISABLED, + DataFailCause.MAX_PPP_INACTIVITY_TIMER_EXPIRED, + DataFailCause.IPV6_ADDRESS_TRANSFER_FAILED, + DataFailCause.TRAT_SWAP_FAILED, + DataFailCause.EHRPD_TO_HRPD_FALLBACK, + DataFailCause.MIP_CONFIG_FAILURE, + DataFailCause.PDN_INACTIVITY_TIMER_EXPIRED, + DataFailCause.MAX_IPV4_CONNECTIONS, + DataFailCause.MAX_IPV6_CONNECTIONS, + DataFailCause.APN_MISMATCH, + DataFailCause.IP_VERSION_MISMATCH, + DataFailCause.DUN_CALL_DISALLOWED, + DataFailCause.INTERNAL_EPC_NONEPC_TRANSITION, + DataFailCause.INTERFACE_IN_USE, + DataFailCause.APN_DISALLOWED_ON_ROAMING, + DataFailCause.APN_PARAMETERS_CHANGED, + DataFailCause.NULL_APN_DISALLOWED, + DataFailCause.THERMAL_MITIGATION, + DataFailCause.DATA_SETTINGS_DISABLED, + DataFailCause.DATA_ROAMING_SETTINGS_DISABLED, + DataFailCause.DDS_SWITCHED, + DataFailCause.FORBIDDEN_APN_NAME, + DataFailCause.DDS_SWITCH_IN_PROGRESS, + DataFailCause.CALL_DISALLOWED_IN_ROAMING, + DataFailCause.NON_IP_NOT_SUPPORTED, + DataFailCause.PDN_NON_IP_CALL_THROTTLED, + DataFailCause.PDN_NON_IP_CALL_DISALLOWED, + DataFailCause.CDMA_LOCK, + DataFailCause.CDMA_INTERCEPT, + DataFailCause.CDMA_REORDER, + DataFailCause.CDMA_RELEASE_DUE_TO_SO_REJECTION, + DataFailCause.CDMA_INCOMING_CALL, + DataFailCause.CDMA_ALERT_STOP, + DataFailCause.CHANNEL_ACQUISITION_FAILURE, + DataFailCause.MAX_ACCESS_PROBE, + DataFailCause.CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION, + DataFailCause.NO_RESPONSE_FROM_BASE_STATION, + DataFailCause.REJECTED_BY_BASE_STATION, + DataFailCause.CONCURRENT_SERVICES_INCOMPATIBLE, + DataFailCause.NO_CDMA_SERVICE, + DataFailCause.RUIM_NOT_PRESENT, + DataFailCause.CDMA_RETRY_ORDER, + DataFailCause.ACCESS_BLOCK, + DataFailCause.ACCESS_BLOCK_ALL, + DataFailCause.IS707B_MAX_ACCESS_PROBES, + DataFailCause.THERMAL_EMERGENCY, + DataFailCause.CONCURRENT_SERVICES_NOT_ALLOWED, + DataFailCause.INCOMING_CALL_REJECTED, + DataFailCause.NO_SERVICE_ON_GATEWAY, + DataFailCause.NO_GPRS_CONTEXT, + DataFailCause.ILLEGAL_MS, + DataFailCause.ILLEGAL_ME, + DataFailCause.GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED, + DataFailCause.GPRS_SERVICES_NOT_ALLOWED, + DataFailCause.MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK, + DataFailCause.IMPLICITLY_DETACHED, + DataFailCause.PLMN_NOT_ALLOWED, + DataFailCause.LOCATION_AREA_NOT_ALLOWED, + DataFailCause.GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN, + DataFailCause.PDP_DUPLICATE, + DataFailCause.UE_RAT_CHANGE, + DataFailCause.CONGESTION, + DataFailCause.NO_PDP_CONTEXT_ACTIVATED, + DataFailCause.ACCESS_CLASS_DSAC_REJECTION, + DataFailCause.PDP_ACTIVATE_MAX_RETRY_FAILED, + DataFailCause.RADIO_ACCESS_BEARER_FAILURE, + DataFailCause.ESM_UNKNOWN_EPS_BEARER_CONTEXT, + DataFailCause.DRB_RELEASED_BY_RRC, + DataFailCause.CONNECTION_RELEASED, + DataFailCause.EMM_DETACHED, + DataFailCause.EMM_ATTACH_FAILED, + DataFailCause.EMM_ATTACH_STARTED, + DataFailCause.LTE_NAS_SERVICE_REQUEST_FAILED, + DataFailCause.DUPLICATE_BEARER_ID, + DataFailCause.ESM_COLLISION_SCENARIOS, + DataFailCause.ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK, + DataFailCause.ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER, + DataFailCause.ESM_BAD_OTA_MESSAGE, + DataFailCause.ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL, + DataFailCause.ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT, + DataFailCause.DS_EXPLICIT_DEACTIVATION, + DataFailCause.ESM_LOCAL_CAUSE_NONE, + DataFailCause.LTE_THROTTLING_NOT_REQUIRED, + DataFailCause.ACCESS_CONTROL_LIST_CHECK_FAILURE, + DataFailCause.SERVICE_NOT_ALLOWED_ON_PLMN, + DataFailCause.EMM_T3417_EXPIRED, + DataFailCause.EMM_T3417_EXT_EXPIRED, + DataFailCause.RRC_UPLINK_DATA_TRANSMISSION_FAILURE, + DataFailCause.RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER, + DataFailCause.RRC_UPLINK_CONNECTION_RELEASE, + DataFailCause.RRC_UPLINK_RADIO_LINK_FAILURE, + DataFailCause.RRC_UPLINK_ERROR_REQUEST_FROM_NAS, + DataFailCause.RRC_CONNECTION_ACCESS_STRATUM_FAILURE, + DataFailCause.RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS, + DataFailCause.RRC_CONNECTION_ACCESS_BARRED, + DataFailCause.RRC_CONNECTION_CELL_RESELECTION, + DataFailCause.RRC_CONNECTION_CONFIG_FAILURE, + DataFailCause.RRC_CONNECTION_TIMER_EXPIRED, + DataFailCause.RRC_CONNECTION_LINK_FAILURE, + DataFailCause.RRC_CONNECTION_CELL_NOT_CAMPED, + DataFailCause.RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE, + DataFailCause.RRC_CONNECTION_REJECT_BY_NETWORK, + DataFailCause.RRC_CONNECTION_NORMAL_RELEASE, + DataFailCause.RRC_CONNECTION_RADIO_LINK_FAILURE, + DataFailCause.RRC_CONNECTION_REESTABLISHMENT_FAILURE, + DataFailCause.RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER, + DataFailCause.RRC_CONNECTION_ABORT_REQUEST, + DataFailCause.RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR, + DataFailCause.NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH, + DataFailCause.NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH, + DataFailCause.ESM_PROCEDURE_TIME_OUT, + DataFailCause.INVALID_CONNECTION_ID, + DataFailCause.MAXIMIUM_NSAPIS_EXCEEDED, + DataFailCause.INVALID_PRIMARY_NSAPI, + DataFailCause.CANNOT_ENCODE_OTA_MESSAGE, + DataFailCause.RADIO_ACCESS_BEARER_SETUP_FAILURE, + DataFailCause.PDP_ESTABLISH_TIMEOUT_EXPIRED, + DataFailCause.PDP_MODIFY_TIMEOUT_EXPIRED, + DataFailCause.PDP_INACTIVE_TIMEOUT_EXPIRED, + DataFailCause.PDP_LOWERLAYER_ERROR, + DataFailCause.PDP_MODIFY_COLLISION, + DataFailCause.MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED, + DataFailCause.NAS_REQUEST_REJECTED_BY_NETWORK, + DataFailCause.RRC_CONNECTION_INVALID_REQUEST, + DataFailCause.RRC_CONNECTION_TRACKING_AREA_ID_CHANGED, + DataFailCause.RRC_CONNECTION_RF_UNAVAILABLE, + DataFailCause.RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE, + DataFailCause.RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE, + DataFailCause.RRC_CONNECTION_ABORTED_AFTER_HANDOVER, + DataFailCause.RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE, + DataFailCause.RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE, + DataFailCause.IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER, + DataFailCause.IMEI_NOT_ACCEPTED, + DataFailCause.EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, + DataFailCause.EPS_SERVICES_NOT_ALLOWED_IN_PLMN, + DataFailCause.MSC_TEMPORARILY_NOT_REACHABLE, + DataFailCause.CS_DOMAIN_NOT_AVAILABLE, + DataFailCause.ESM_FAILURE, + DataFailCause.MAC_FAILURE, + DataFailCause.SYNCHRONIZATION_FAILURE, + DataFailCause.UE_SECURITY_CAPABILITIES_MISMATCH, + DataFailCause.SECURITY_MODE_REJECTED, + DataFailCause.UNACCEPTABLE_NON_EPS_AUTHENTICATION, + DataFailCause.CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED, + DataFailCause.NO_EPS_BEARER_CONTEXT_ACTIVATED, + DataFailCause.INVALID_EMM_STATE, + DataFailCause.NAS_LAYER_FAILURE, + DataFailCause.MULTIPLE_PDP_CALL_NOT_ALLOWED, + DataFailCause.EMBMS_NOT_ENABLED, + DataFailCause.IRAT_HANDOVER_FAILED, + DataFailCause.EMBMS_REGULAR_DEACTIVATION, + DataFailCause.TEST_LOOPBACK_REGULAR_DEACTIVATION, + DataFailCause.LOWER_LAYER_REGISTRATION_FAILURE, + DataFailCause.DATA_PLAN_EXPIRED, + DataFailCause.UMTS_HANDOVER_TO_IWLAN, + DataFailCause.EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY, + DataFailCause.EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE, + DataFailCause.EVDO_HDR_CHANGED, + DataFailCause.EVDO_HDR_EXITED, + DataFailCause.EVDO_HDR_NO_SESSION, + DataFailCause.EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL, + DataFailCause.EVDO_HDR_CONNECTION_SETUP_TIMEOUT, + DataFailCause.FAILED_TO_ACQUIRE_COLOCATED_HDR, + DataFailCause.OTASP_COMMIT_IN_PROGRESS, + DataFailCause.NO_HYBRID_HDR_SERVICE, + DataFailCause.HDR_NO_LOCK_GRANTED, + DataFailCause.DBM_OR_SMS_IN_PROGRESS, + DataFailCause.HDR_FADE, + DataFailCause.HDR_ACCESS_FAILURE, + DataFailCause.UNSUPPORTED_1X_PREV, + DataFailCause.LOCAL_END, + DataFailCause.NO_SERVICE, + DataFailCause.FADE, + DataFailCause.NORMAL_RELEASE, + DataFailCause.ACCESS_ATTEMPT_ALREADY_IN_PROGRESS, + DataFailCause.REDIRECTION_OR_HANDOFF_IN_PROGRESS, + DataFailCause.EMERGENCY_MODE, + DataFailCause.PHONE_IN_USE, + DataFailCause.INVALID_MODE, + DataFailCause.INVALID_SIM_STATE, + DataFailCause.NO_COLLOCATED_HDR, + DataFailCause.UE_IS_ENTERING_POWERSAVE_MODE, + DataFailCause.DUAL_SWITCH, + DataFailCause.PPP_TIMEOUT, + DataFailCause.PPP_AUTH_FAILURE, + DataFailCause.PPP_OPTION_MISMATCH, + DataFailCause.PPP_PAP_FAILURE, + DataFailCause.PPP_CHAP_FAILURE, + DataFailCause.PPP_CLOSE_IN_PROGRESS, + DataFailCause.LIMITED_TO_IPV4, + DataFailCause.LIMITED_TO_IPV6, + DataFailCause.VSNCP_TIMEOUT, + DataFailCause.VSNCP_GEN_ERROR, + DataFailCause.VSNCP_APN_UNATHORIZED, + DataFailCause.VSNCP_PDN_LIMIT_EXCEEDED, + DataFailCause.VSNCP_NO_PDN_GATEWAY_ADDRESS, + DataFailCause.VSNCP_PDN_GATEWAY_UNREACHABLE, + DataFailCause.VSNCP_PDN_GATEWAY_REJECT, + DataFailCause.VSNCP_INSUFFICIENT_PARAMETERS, + DataFailCause.VSNCP_RESOURCE_UNAVAILABLE, + DataFailCause.VSNCP_ADMINISTRATIVELY_PROHIBITED, + DataFailCause.VSNCP_PDN_ID_IN_USE, + DataFailCause.VSNCP_SUBSCRIBER_LIMITATION, + DataFailCause.VSNCP_PDN_EXISTS_FOR_THIS_APN, + DataFailCause.VSNCP_RECONNECT_NOT_ALLOWED, + DataFailCause.IPV6_PREFIX_UNAVAILABLE, + DataFailCause.HANDOFF_PREFERENCE_CHANGED, + DataFailCause.OEM_DCFAILCAUSE_1, + DataFailCause.OEM_DCFAILCAUSE_2, + DataFailCause.OEM_DCFAILCAUSE_3, + DataFailCause.OEM_DCFAILCAUSE_4, + DataFailCause.OEM_DCFAILCAUSE_5, + DataFailCause.OEM_DCFAILCAUSE_6, + DataFailCause.OEM_DCFAILCAUSE_7, + DataFailCause.OEM_DCFAILCAUSE_8, + DataFailCause.OEM_DCFAILCAUSE_9, + DataFailCause.OEM_DCFAILCAUSE_10, + DataFailCause.OEM_DCFAILCAUSE_11, + DataFailCause.OEM_DCFAILCAUSE_12, + DataFailCause.OEM_DCFAILCAUSE_13, + DataFailCause.OEM_DCFAILCAUSE_14, + DataFailCause.OEM_DCFAILCAUSE_15, + DataFailCause.REGISTRATION_FAIL, + DataFailCause.GPRS_REGISTRATION_FAIL, + DataFailCause.SIGNAL_LOST, + DataFailCause.PREF_RADIO_TECH_CHANGED, + DataFailCause.RADIO_POWER_OFF, + DataFailCause.TETHERED_CALL_ACTIVE, + DataFailCause.ERROR_UNSPECIFIED, + DataFailCause.UNKNOWN, + DataFailCause.RADIO_NOT_AVAILABLE, + DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER, + DataFailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN, + DataFailCause.LOST_CONNECTION, + DataFailCause.RESET_BY_FRAMEWORK + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DataFailureCause { + } +} diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java index 1c03d8089df7..cd830adf23b0 100644 --- a/telephony/java/android/telephony/CallAttributes.java +++ b/telephony/java/android/telephony/CallAttributes.java @@ -21,8 +21,8 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.TelephonyManager.NetworkType; +import android.telephony.Annotation.NetworkType; import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java index 028280c332e2..e01deb2802ff 100644 --- a/telephony/java/android/telephony/CallQuality.java +++ b/telephony/java/android/telephony/CallQuality.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -40,6 +41,7 @@ import java.util.Objects; * @hide */ @SystemApi +@TestApi public final class CallQuality implements Parcelable { // Constants representing the call quality level (see #CallQuality); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index e458ae6b1d3d..a0aa8928dae8 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -809,7 +809,9 @@ public class CarrierConfigManager { /** * The default flag specifying whether ETWS/CMAS test setting is forcibly disabled in * Settings->More->Emergency broadcasts menu even though developer options is turned on. + * @deprecated moved to cellbroadcastreceiver resource show_test_settings */ + @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; @@ -828,13 +830,6 @@ public class CarrierConfigManager { "disable_severe_when_extreme_disabled_bool"; /** - * The message expiration time in milliseconds for duplicate detection purposes. - * @hide - */ - public static final String KEY_MESSAGE_EXPIRATION_TIME_LONG = - "message_expiration_time_long"; - - /** * The data call retry configuration for different types of APN. * @hide */ @@ -1750,6 +1745,15 @@ public class CarrierConfigManager { "allow_emergency_video_calls_bool"; /** + * Flag indicating whether or not an ongoing call will be held when an outgoing emergency call + * is placed. If true, ongoing calls will be put on hold when an emergency call is placed. If + * false, placing an emergency call will trigger the disconnect of all ongoing calls before + * the emergency call is placed. + */ + public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = + "allow_hold_call_during_emergency_bool"; + + /** * Flag indicating whether the carrier supports RCS presence indication for * User Capability Exchange (UCE). When presence is supported, the device should use the * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the @@ -2287,6 +2291,77 @@ public class CarrierConfigManager { "use_only_rsrp_for_lte_signal_bar_bool"; /** + * List of 4 customized 5G SS reference signal received power (SSRSRP) thresholds. + * + * Reference: 3GPP TS 38.215 + * + * 4 threshold integers must be within the boundaries [-140 dB, -44 dB], and the levels are: + * "NONE: [-140, threshold1]" + * "POOR: (threshold1, threshold2]" + * "MODERATE: (threshold2, threshold3]" + * "GOOD: (threshold3, threshold4]" + * "EXCELLENT: (threshold4, -44]" + * + * This key is considered invalid if the format is violated. If the key is invalid or + * not configured, a default value set will apply. + */ + public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = + "5g_nr_ssrsrp_thresholds_int_array"; + + /** + * List of 4 customized 5G SS reference signal received quality (SSRSRQ) thresholds. + * + * Reference: 3GPP TS 38.215 + * + * 4 threshold integers must be within the boundaries [-20 dB, -3 dB], and the levels are: + * "NONE: [-23, threshold1]" + * "POOR: (threshold1, threshold2]" + * "MODERATE: (threshold2, threshold3]" + * "GOOD: (threshold3, threshold4]" + * "EXCELLENT: (threshold4, -3]" + * + * This key is considered invalid if the format is violated. If the key is invalid or + * not configured, a default value set will apply. + */ + public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = + "5g_nr_ssrsrq_thresholds_int_array"; + + /** + * List of 4 customized 5G SS signal-to-noise and interference ratio (SSSINR) thresholds. + * + * Reference: 3GPP TS 38.215, + * 3GPP TS 38.133 10.1.16.1 + * + * 4 threshold integers must be within the boundaries [-23 dB, 40 dB], and the levels are: + * "NONE: [-23, threshold1]" + * "POOR: (threshold1, threshold2]" + * "MODERATE: (threshold2, threshold3]" + * "GOOD: (threshold3, threshold4]" + * "EXCELLENT: (threshold4, 40]" + * + * This key is considered invalid if the format is violated. If the key is invalid or + * not configured, a default value set will apply. + */ + public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = + "5g_nr_sssinr_thresholds_int_array"; + + /** + * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP), + * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference + * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the + * parameter whose value is smallest is used to indicate the signal bar. + * + * SSRSRP = 1 << 0, + * SSRSRQ = 1 << 1, + * SSSINR = 1 << 2, + * + * Reference: 3GPP TS 38.215, + * 3GPP TS 38.133 10.1.16.1 + */ + public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT = + "parameters_use_for_5g_nr_signal_bar_int"; + + /** * Key identifying if voice call barring notification is required to be shown to the user. * @hide */ @@ -2833,6 +2908,16 @@ public class CarrierConfigManager { "always_show_primary_signal_bar_in_opportunistic_network_boolean"; /** + * Upon data switching between subscriptions within a carrier group, if switch depends on + * validation result, this value defines customized value of how long we wait for validation + * success before we fail and revoke the switch. + * Time out is in milliseconds. + * @hide + */ + public static final String KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG = + "data_switch_validation_timeout_long"; + + /** * GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration. * @hide */ @@ -3306,7 +3391,6 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false); sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false); sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true); - sDefaults.putLong(KEY_MESSAGE_EXPIRATION_TIME_LONG, 86400000L); sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{ "default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000," + "320000:5000,640000:5000,1280000:5000,1800000:5000", @@ -3426,6 +3510,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_MMS_USER_AGENT_STRING, ""); sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true); sDefaults.putInt(KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 0); + sDefaults.putBoolean(KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL, true); sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false); sDefaults.putBoolean(KEY_USE_RCS_SIP_OPTIONS_BOOL, false); sDefaults.putBoolean(KEY_FORCE_IMEI_BOOL, false); @@ -3613,6 +3698,7 @@ public class CarrierConfigManager { sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY, new int[] {4 /* BUSY */}); sDefaults.putBoolean(KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL, false); + sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, 2000); } /** diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java index 0b73252a1e1b..f4ce6e75769c 100644 --- a/telephony/java/com/android/internal/telephony/CbGeoUtils.java +++ b/telephony/java/android/telephony/CbGeoUtils.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.internal.telephony; +package android.telephony; import android.annotation.NonNull; -import android.telephony.Rlog; +import android.annotation.SystemApi; import android.text.TextUtils; import java.util.ArrayList; @@ -30,8 +30,17 @@ import java.util.stream.Collectors; * The coordinates used by this utils class are latitude and longitude, but some algorithms in this * class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use * this class for anything other then geo-targeting of cellbroadcast messages. + * @hide */ +@SystemApi public class CbGeoUtils { + + /** + * This class is never instantiated + * @hide + */ + private CbGeoUtils() {} + /** Geometric interface. */ public interface Geometry { /** @@ -39,27 +48,36 @@ public class CbGeoUtils { * @param p point in latitude, longitude format. * @return {@code True} if the given point is inside the geometry. */ - boolean contains(LatLng p); + boolean contains(@NonNull LatLng p); } /** * Tolerance for determining if the value is 0. If the absolute value of a value is less than * this tolerance, it will be treated as 0. + * @hide */ public static final double EPS = 1e-7; - /** The radius of earth. */ + /** + * The radius of earth. + * @hide + */ public static final int EARTH_RADIUS_METER = 6371 * 1000; private static final String TAG = "CbGeoUtils"; - /** The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. */ + // The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. + /** @hide */ public static final int GEO_FENCING_MAXIMUM_WAIT_TIME = 0x01; + /** @hide */ public static final int GEOMETRY_TYPE_POLYGON = 0x02; + /** @hide */ public static final int GEOMETRY_TYPE_CIRCLE = 0x03; - /** The identifier of geometry in the encoded string. */ + // The identifier of geometry in the encoded string. + /** @hide */ private static final String CIRCLE_SYMBOL = "circle"; + /** @hide */ private static final String POLYGON_SYMBOL = "polygon"; /** Point represent by (latitude, longitude). */ @@ -81,7 +99,8 @@ public class CbGeoUtils { * @param p the point use to calculate the subtraction result. * @return the result of this point subtract the given point {@code p}. */ - public LatLng subtract(LatLng p) { + @NonNull + public LatLng subtract(@NonNull LatLng p) { return new LatLng(lat - p.lat, lng - p.lng); } @@ -90,7 +109,7 @@ public class CbGeoUtils { * @param p the point use to calculate the distance. * @return the distance in meter. */ - public double distance(LatLng p) { + public double distance(@NonNull LatLng p) { double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat)); double dlng = Math.sin(0.5 * Math.toRadians(lng - p.lng)); double x = dlat * dlat @@ -106,6 +125,7 @@ public class CbGeoUtils { /** * The class represents a simple polygon with at least 3 points. + * @hide */ public static class Polygon implements Geometry { /** @@ -239,7 +259,10 @@ public class CbGeoUtils { } } - /** The class represents a circle. */ + /** + * The class represents a circle. + * @hide + */ public static class Circle implements Geometry { private final LatLng mCenter; private final double mRadiusMeter; @@ -266,6 +289,7 @@ public class CbGeoUtils { /** * Parse the geometries from the encoded string {@code str}. The string must follow the * geometry encoding specified by {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. + * @hide */ @NonNull public static List<Geometry> parseGeometriesFromString(@NonNull String str) { @@ -297,6 +321,7 @@ public class CbGeoUtils { * * @param geometries the list of geometry objects need to be encoded. * @return the encoded string. + * @hide */ @NonNull public static String encodeGeometriesToString(List<Geometry> geometries) { @@ -313,6 +338,7 @@ public class CbGeoUtils { * {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. * @param geometry the geometry object need to be encoded. * @return the encoded string. + * @hide */ @NonNull private static String encodeGeometryToString(@NonNull Geometry geometry) { @@ -351,6 +377,7 @@ public class CbGeoUtils { * * @param str encoded lat/lng string. * @Return {@link LatLng} object. + * @hide */ @NonNull public static LatLng parseLatLngFromString(@NonNull String str) { @@ -361,6 +388,7 @@ public class CbGeoUtils { /** * @Return the sign of the given value {@code value} with the specified tolerance. Return 1 * means the sign is positive, -1 means negative, 0 means the value will be treated as 0. + * @hide */ public static int sign(double value) { if (value > EPS) return 1; diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java index d5e447e6c73d..f841df2320e0 100644 --- a/telephony/java/android/telephony/CellBroadcastService.java +++ b/telephony/java/android/telephony/CellBroadcastService.java @@ -17,10 +17,18 @@ package android.telephony; import android.annotation.CallSuper; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; +import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteCallback; +import android.telephony.cdma.CdmaSmsCbProgramData; + +import java.util.List; +import java.util.function.Consumer; /** * A service which exposes the cell broadcast handling module to the system. @@ -45,6 +53,7 @@ import android.os.IBinder; * </service> * </manifest> * }</pre> + * * @hide */ @SystemApi @@ -61,17 +70,36 @@ public abstract class CellBroadcastService extends Service { /** * Handle a GSM cell broadcast SMS message forwarded from the system. + * * @param slotIndex the index of the slot which received the message - * @param message the SMS PDU + * @param message the SMS PDU */ - public abstract void onGsmCellBroadcastSms(int slotIndex, byte[] message); + public abstract void onGsmCellBroadcastSms(int slotIndex, @NonNull byte[] message); /** * Handle a CDMA cell broadcast SMS message forwarded from the system. - * @param slotIndex the index of the slot which received the message - * @param message the SMS PDU + * + * @param slotIndex the index of the slot which received the message + * @param bearerData the CDMA SMS bearer data + * @param serviceCategory the CDMA SCPT service category + */ + public abstract void onCdmaCellBroadcastSms(int slotIndex, @NonNull byte[] bearerData, + @CdmaSmsCbProgramData.Category int serviceCategory); + + /** + * Handle a CDMA cell broadcast SMS message forwarded from the system. + * + * @param slotIndex the index of the slot which received the message + * @param smsCbProgramData the SMS CB program data of the message + * @param originatingAddress the originating address of the message, as a non-separated dial + * string + * @param callback a callback to run after each cell broadcast receiver has handled + * the SCP message. The bundle will contain a non-separated + * dial string as and an ArrayList of {@link CdmaSmsCbProgramResults}. */ - public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] message); + public abstract void onCdmaScpMessage(int slotIndex, + @NonNull List<CdmaSmsCbProgramData> smsCbProgramData, + @NonNull String originatingAddress, @NonNull Consumer<Bundle> callback); /** * If overriding this method, call through to the super method for any unknown actions. @@ -79,20 +107,23 @@ public abstract class CellBroadcastService extends Service { */ @Override @CallSuper - public IBinder onBind(Intent intent) { + @NonNull + public IBinder onBind(@Nullable Intent intent) { return mStubWrapper; } /** * A wrapper around ICellBroadcastService that forwards calls to implementations of * {@link CellBroadcastService}. + * * @hide */ public class ICellBroadcastServiceWrapper extends ICellBroadcastService.Stub { /** * Handle a GSM cell broadcast SMS. + * * @param slotIndex the index of the slot which received the broadcast - * @param message the SMS message PDU + * @param message the SMS message PDU */ @Override public void handleGsmCellBroadcastSms(int slotIndex, byte[] message) { @@ -101,12 +132,36 @@ public abstract class CellBroadcastService extends Service { /** * Handle a CDMA cell broadcast SMS. - * @param slotIndex the index of the slot which received the broadcast - * @param message the SMS message PDU + * + * @param slotIndex the index of the slot which received the broadcast + * @param bearerData the CDMA SMS bearer data + * @param serviceCategory the CDMA SCPT service category + */ + @Override + public void handleCdmaCellBroadcastSms(int slotIndex, byte[] bearerData, + int serviceCategory) { + CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, bearerData, + serviceCategory); + } + + /** + * Handle a CDMA Service Category Program message. + * + * @param slotIndex the index of the slot which received the message + * @param smsCbProgramData the SMS CB program data of the message + * @param originatingAddress the originating address of the message + * @param callback a callback to run after each cell broadcast receiver has + * handled the SCP message */ @Override - public void handleCdmaCellBroadcastSms(int slotIndex, byte[] message) { - CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, message); + public void handleCdmaScpMessage(int slotIndex, + List<CdmaSmsCbProgramData> smsCbProgramData, String originatingAddress, + RemoteCallback callback) { + Consumer<Bundle> consumer = bundle -> { + callback.sendResult(bundle); + }; + CellBroadcastService.this.onCdmaScpMessage(slotIndex, smsCbProgramData, + originatingAddress, consumer); } } } diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java index 7edc91cd67e8..18687d400faf 100644 --- a/telephony/java/android/telephony/CellInfo.java +++ b/telephony/java/android/telephony/CellInfo.java @@ -189,11 +189,15 @@ public abstract class CellInfo implements Parcelable { mTimeStamp = ts; } - /** @hide */ + /** + * @return a {@link CellIdentity} instance. + */ @NonNull public abstract CellIdentity getCellIdentity(); - /** @hide */ + /** + * @return a {@link CellSignalStrength} instance. + */ @NonNull public abstract CellSignalStrength getCellSignalStrength(); diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index 1912c60ac122..f9b7f6dbc193 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -194,13 +194,13 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa /** @hide */ @Override public void updateLevel(PersistableBundle cc, ServiceState ss) { - if (mCsiRsrp == CellInfo.UNAVAILABLE) { + if (mSsRsrp == CellInfo.UNAVAILABLE) { mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) { mLevel = SIGNAL_STRENGTH_GREAT; - } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) { mLevel = SIGNAL_STRENGTH_GOOD; - } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) { + } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) { mLevel = SIGNAL_STRENGTH_MODERATE; } else { mLevel = SIGNAL_STRENGTH_POOR; @@ -212,7 +212,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa * * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 * - * @return RSCP in ASU 0..97, 255, or UNAVAILABLE + * @return RSRP in ASU 0..97, 255, or UNAVAILABLE */ @Override public int getAsuLevel() { @@ -231,11 +231,11 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa } /** - * Get the CSI-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. + * Get the SS-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. */ @Override public int getDbm() { - return mCsiRsrp; + return mSsRsrp; } /** @hide */ diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java index cdf01dab0059..4dc54f0fef58 100644 --- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java @@ -245,9 +245,12 @@ public final class CellSignalStrengthWcdma extends CellSignalStrength implements } /** - * Get the Ec/No as dB + * Get the Ec/No (Energy per chip over the noise spectral density) as dB. * - * @hide + * Reference: TS 25.133 Section 9.1.2.3 + * + * @return the Ec/No of the measured cell in the range [-24, 1] or + * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable */ public int getEcNo() { return mEcNo; diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index ca264f738e1d..246bec7de59e 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -21,6 +21,7 @@ import android.annotation.SystemApi; import android.content.Context; import android.os.PersistableBundle; +import android.telephony.Annotation.DataFailureCause; import com.android.internal.util.ArrayUtils; import java.lang.annotation.Retention; @@ -968,355 +969,6 @@ public final class DataFailCause { */ public static final int HANDOVER_FAILED = 0x10006; - /** @hide */ - @IntDef(value = { - NONE, - OPERATOR_BARRED, - NAS_SIGNALLING, - LLC_SNDCP, - INSUFFICIENT_RESOURCES, - MISSING_UNKNOWN_APN, - UNKNOWN_PDP_ADDRESS_TYPE, - USER_AUTHENTICATION, - ACTIVATION_REJECT_GGSN, - ACTIVATION_REJECT_UNSPECIFIED, - SERVICE_OPTION_NOT_SUPPORTED, - SERVICE_OPTION_NOT_SUBSCRIBED, - SERVICE_OPTION_OUT_OF_ORDER, - NSAPI_IN_USE, - REGULAR_DEACTIVATION, - QOS_NOT_ACCEPTED, - NETWORK_FAILURE, - UMTS_REACTIVATION_REQ, - FEATURE_NOT_SUPP, - TFT_SEMANTIC_ERROR, - TFT_SYTAX_ERROR, - UNKNOWN_PDP_CONTEXT, - FILTER_SEMANTIC_ERROR, - FILTER_SYTAX_ERROR, - PDP_WITHOUT_ACTIVE_TFT, - ACTIVATION_REJECTED_BCM_VIOLATION, - ONLY_IPV4_ALLOWED, - ONLY_IPV6_ALLOWED, - ONLY_SINGLE_BEARER_ALLOWED, - ESM_INFO_NOT_RECEIVED, - PDN_CONN_DOES_NOT_EXIST, - MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED, - COLLISION_WITH_NETWORK_INITIATED_REQUEST, - ONLY_IPV4V6_ALLOWED, - ONLY_NON_IP_ALLOWED, - UNSUPPORTED_QCI_VALUE, - BEARER_HANDLING_NOT_SUPPORTED, - ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED, - UNSUPPORTED_APN_IN_CURRENT_PLMN, - INVALID_TRANSACTION_ID, - MESSAGE_INCORRECT_SEMANTIC, - INVALID_MANDATORY_INFO, - MESSAGE_TYPE_UNSUPPORTED, - MSG_TYPE_NONCOMPATIBLE_STATE, - UNKNOWN_INFO_ELEMENT, - CONDITIONAL_IE_ERROR, - MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE, - PROTOCOL_ERRORS, - APN_TYPE_CONFLICT, - INVALID_PCSCF_ADDR, - INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN, - EMM_ACCESS_BARRED, - EMERGENCY_IFACE_ONLY, - IFACE_MISMATCH, - COMPANION_IFACE_IN_USE, - IP_ADDRESS_MISMATCH, - IFACE_AND_POL_FAMILY_MISMATCH, - EMM_ACCESS_BARRED_INFINITE_RETRY, - AUTH_FAILURE_ON_EMERGENCY_CALL, - INVALID_DNS_ADDR, - INVALID_PCSCF_OR_DNS_ADDRESS, - CALL_PREEMPT_BY_EMERGENCY_APN, - UE_INITIATED_DETACH_OR_DISCONNECT, - MIP_FA_REASON_UNSPECIFIED, - MIP_FA_ADMIN_PROHIBITED, - MIP_FA_INSUFFICIENT_RESOURCES, - MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE, - MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE, - MIP_FA_REQUESTED_LIFETIME_TOO_LONG, - MIP_FA_MALFORMED_REQUEST, - MIP_FA_MALFORMED_REPLY, - MIP_FA_ENCAPSULATION_UNAVAILABLE, - MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE, - MIP_FA_REVERSE_TUNNEL_UNAVAILABLE, - MIP_FA_REVERSE_TUNNEL_IS_MANDATORY, - MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED, - MIP_FA_MISSING_NAI, - MIP_FA_MISSING_HOME_AGENT, - MIP_FA_MISSING_HOME_ADDRESS, - MIP_FA_UNKNOWN_CHALLENGE, - MIP_FA_MISSING_CHALLENGE, - MIP_FA_STALE_CHALLENGE, - MIP_HA_REASON_UNSPECIFIED, - MIP_HA_ADMIN_PROHIBITED, - MIP_HA_INSUFFICIENT_RESOURCES, - MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE, - MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE, - MIP_HA_REGISTRATION_ID_MISMATCH, - MIP_HA_MALFORMED_REQUEST, - MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS, - MIP_HA_REVERSE_TUNNEL_UNAVAILABLE, - MIP_HA_REVERSE_TUNNEL_IS_MANDATORY, - MIP_HA_ENCAPSULATION_UNAVAILABLE, - CLOSE_IN_PROGRESS, - NETWORK_INITIATED_TERMINATION, - MODEM_APP_PREEMPTED, - PDN_IPV4_CALL_DISALLOWED, - PDN_IPV4_CALL_THROTTLED, - PDN_IPV6_CALL_DISALLOWED, - PDN_IPV6_CALL_THROTTLED, - MODEM_RESTART, - PDP_PPP_NOT_SUPPORTED, - UNPREFERRED_RAT, - PHYSICAL_LINK_CLOSE_IN_PROGRESS, - APN_PENDING_HANDOVER, - PROFILE_BEARER_INCOMPATIBLE, - SIM_CARD_CHANGED, - LOW_POWER_MODE_OR_POWERING_DOWN, - APN_DISABLED, - MAX_PPP_INACTIVITY_TIMER_EXPIRED, - IPV6_ADDRESS_TRANSFER_FAILED, - TRAT_SWAP_FAILED, - EHRPD_TO_HRPD_FALLBACK, - MIP_CONFIG_FAILURE, - PDN_INACTIVITY_TIMER_EXPIRED, - MAX_IPV4_CONNECTIONS, - MAX_IPV6_CONNECTIONS, - APN_MISMATCH, - IP_VERSION_MISMATCH, - DUN_CALL_DISALLOWED, - INTERNAL_EPC_NONEPC_TRANSITION, - INTERFACE_IN_USE, - APN_DISALLOWED_ON_ROAMING, - APN_PARAMETERS_CHANGED, - NULL_APN_DISALLOWED, - THERMAL_MITIGATION, - DATA_SETTINGS_DISABLED, - DATA_ROAMING_SETTINGS_DISABLED, - DDS_SWITCHED, - FORBIDDEN_APN_NAME, - DDS_SWITCH_IN_PROGRESS, - CALL_DISALLOWED_IN_ROAMING, - NON_IP_NOT_SUPPORTED, - PDN_NON_IP_CALL_THROTTLED, - PDN_NON_IP_CALL_DISALLOWED, - CDMA_LOCK, - CDMA_INTERCEPT, - CDMA_REORDER, - CDMA_RELEASE_DUE_TO_SO_REJECTION, - CDMA_INCOMING_CALL, - CDMA_ALERT_STOP, - CHANNEL_ACQUISITION_FAILURE, - MAX_ACCESS_PROBE, - CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION, - NO_RESPONSE_FROM_BASE_STATION, - REJECTED_BY_BASE_STATION, - CONCURRENT_SERVICES_INCOMPATIBLE, - NO_CDMA_SERVICE, - RUIM_NOT_PRESENT, - CDMA_RETRY_ORDER, - ACCESS_BLOCK, - ACCESS_BLOCK_ALL, - IS707B_MAX_ACCESS_PROBES, - THERMAL_EMERGENCY, - CONCURRENT_SERVICES_NOT_ALLOWED, - INCOMING_CALL_REJECTED, - NO_SERVICE_ON_GATEWAY, - NO_GPRS_CONTEXT, - ILLEGAL_MS, - ILLEGAL_ME, - GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED, - GPRS_SERVICES_NOT_ALLOWED, - MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK, - IMPLICITLY_DETACHED, - PLMN_NOT_ALLOWED, - LOCATION_AREA_NOT_ALLOWED, - GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN, - PDP_DUPLICATE, - UE_RAT_CHANGE, - CONGESTION, - NO_PDP_CONTEXT_ACTIVATED, - ACCESS_CLASS_DSAC_REJECTION, - PDP_ACTIVATE_MAX_RETRY_FAILED, - RADIO_ACCESS_BEARER_FAILURE, - ESM_UNKNOWN_EPS_BEARER_CONTEXT, - DRB_RELEASED_BY_RRC, - CONNECTION_RELEASED, - EMM_DETACHED, - EMM_ATTACH_FAILED, - EMM_ATTACH_STARTED, - LTE_NAS_SERVICE_REQUEST_FAILED, - DUPLICATE_BEARER_ID, - ESM_COLLISION_SCENARIOS, - ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK, - ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER, - ESM_BAD_OTA_MESSAGE, - ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL, - ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT, - DS_EXPLICIT_DEACTIVATION, - ESM_LOCAL_CAUSE_NONE, - LTE_THROTTLING_NOT_REQUIRED, - ACCESS_CONTROL_LIST_CHECK_FAILURE, - SERVICE_NOT_ALLOWED_ON_PLMN, - EMM_T3417_EXPIRED, - EMM_T3417_EXT_EXPIRED, - RRC_UPLINK_DATA_TRANSMISSION_FAILURE, - RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER, - RRC_UPLINK_CONNECTION_RELEASE, - RRC_UPLINK_RADIO_LINK_FAILURE, - RRC_UPLINK_ERROR_REQUEST_FROM_NAS, - RRC_CONNECTION_ACCESS_STRATUM_FAILURE, - RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS, - RRC_CONNECTION_ACCESS_BARRED, - RRC_CONNECTION_CELL_RESELECTION, - RRC_CONNECTION_CONFIG_FAILURE, - RRC_CONNECTION_TIMER_EXPIRED, - RRC_CONNECTION_LINK_FAILURE, - RRC_CONNECTION_CELL_NOT_CAMPED, - RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE, - RRC_CONNECTION_REJECT_BY_NETWORK, - RRC_CONNECTION_NORMAL_RELEASE, - RRC_CONNECTION_RADIO_LINK_FAILURE, - RRC_CONNECTION_REESTABLISHMENT_FAILURE, - RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER, - RRC_CONNECTION_ABORT_REQUEST, - RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR, - NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH, - NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH, - ESM_PROCEDURE_TIME_OUT, - INVALID_CONNECTION_ID, - MAXIMIUM_NSAPIS_EXCEEDED, - INVALID_PRIMARY_NSAPI, - CANNOT_ENCODE_OTA_MESSAGE, - RADIO_ACCESS_BEARER_SETUP_FAILURE, - PDP_ESTABLISH_TIMEOUT_EXPIRED, - PDP_MODIFY_TIMEOUT_EXPIRED, - PDP_INACTIVE_TIMEOUT_EXPIRED, - PDP_LOWERLAYER_ERROR, - PDP_MODIFY_COLLISION, - MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED, - NAS_REQUEST_REJECTED_BY_NETWORK, - RRC_CONNECTION_INVALID_REQUEST, - RRC_CONNECTION_TRACKING_AREA_ID_CHANGED, - RRC_CONNECTION_RF_UNAVAILABLE, - RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE, - RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE, - RRC_CONNECTION_ABORTED_AFTER_HANDOVER, - RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE, - RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE, - IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER, - IMEI_NOT_ACCEPTED, - EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, - EPS_SERVICES_NOT_ALLOWED_IN_PLMN, - MSC_TEMPORARILY_NOT_REACHABLE, - CS_DOMAIN_NOT_AVAILABLE, - ESM_FAILURE, - MAC_FAILURE, - SYNCHRONIZATION_FAILURE, - UE_SECURITY_CAPABILITIES_MISMATCH, - SECURITY_MODE_REJECTED, - UNACCEPTABLE_NON_EPS_AUTHENTICATION, - CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED, - NO_EPS_BEARER_CONTEXT_ACTIVATED, - INVALID_EMM_STATE, - NAS_LAYER_FAILURE, - MULTIPLE_PDP_CALL_NOT_ALLOWED, - EMBMS_NOT_ENABLED, - IRAT_HANDOVER_FAILED, - EMBMS_REGULAR_DEACTIVATION, - TEST_LOOPBACK_REGULAR_DEACTIVATION, - LOWER_LAYER_REGISTRATION_FAILURE, - DATA_PLAN_EXPIRED, - UMTS_HANDOVER_TO_IWLAN, - EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY, - EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE, - EVDO_HDR_CHANGED, - EVDO_HDR_EXITED, - EVDO_HDR_NO_SESSION, - EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL, - EVDO_HDR_CONNECTION_SETUP_TIMEOUT, - FAILED_TO_ACQUIRE_COLOCATED_HDR, - OTASP_COMMIT_IN_PROGRESS, - NO_HYBRID_HDR_SERVICE, - HDR_NO_LOCK_GRANTED, - DBM_OR_SMS_IN_PROGRESS, - HDR_FADE, - HDR_ACCESS_FAILURE, - UNSUPPORTED_1X_PREV, - LOCAL_END, - NO_SERVICE, - FADE, - NORMAL_RELEASE, - ACCESS_ATTEMPT_ALREADY_IN_PROGRESS, - REDIRECTION_OR_HANDOFF_IN_PROGRESS, - EMERGENCY_MODE, - PHONE_IN_USE, - INVALID_MODE, - INVALID_SIM_STATE, - NO_COLLOCATED_HDR, - UE_IS_ENTERING_POWERSAVE_MODE, - DUAL_SWITCH, - PPP_TIMEOUT, - PPP_AUTH_FAILURE, - PPP_OPTION_MISMATCH, - PPP_PAP_FAILURE, - PPP_CHAP_FAILURE, - PPP_CLOSE_IN_PROGRESS, - LIMITED_TO_IPV4, - LIMITED_TO_IPV6, - VSNCP_TIMEOUT, - VSNCP_GEN_ERROR, - VSNCP_APN_UNATHORIZED, - VSNCP_PDN_LIMIT_EXCEEDED, - VSNCP_NO_PDN_GATEWAY_ADDRESS, - VSNCP_PDN_GATEWAY_UNREACHABLE, - VSNCP_PDN_GATEWAY_REJECT, - VSNCP_INSUFFICIENT_PARAMETERS, - VSNCP_RESOURCE_UNAVAILABLE, - VSNCP_ADMINISTRATIVELY_PROHIBITED, - VSNCP_PDN_ID_IN_USE, - VSNCP_SUBSCRIBER_LIMITATION, - VSNCP_PDN_EXISTS_FOR_THIS_APN, - VSNCP_RECONNECT_NOT_ALLOWED, - IPV6_PREFIX_UNAVAILABLE, - HANDOFF_PREFERENCE_CHANGED, - OEM_DCFAILCAUSE_1, - OEM_DCFAILCAUSE_2, - OEM_DCFAILCAUSE_3, - OEM_DCFAILCAUSE_4, - OEM_DCFAILCAUSE_5, - OEM_DCFAILCAUSE_6, - OEM_DCFAILCAUSE_7, - OEM_DCFAILCAUSE_8, - OEM_DCFAILCAUSE_9, - OEM_DCFAILCAUSE_10, - OEM_DCFAILCAUSE_11, - OEM_DCFAILCAUSE_12, - OEM_DCFAILCAUSE_13, - OEM_DCFAILCAUSE_14, - OEM_DCFAILCAUSE_15, - REGISTRATION_FAIL, - GPRS_REGISTRATION_FAIL, - SIGNAL_LOST, - PREF_RADIO_TECH_CHANGED, - RADIO_POWER_OFF, - TETHERED_CALL_ACTIVE, - ERROR_UNSPECIFIED, - UNKNOWN, - RADIO_NOT_AVAILABLE, - UNACCEPTABLE_NETWORK_PARAMETER, - CONNECTION_TO_DATACONNECTIONAC_BROKEN, - LOST_CONNECTION, - RESET_BY_FRAMEWORK - }) - @Retention(RetentionPolicy.SOURCE) - public @interface FailCause{} - private static final Map<Integer, String> sFailCauseMap; static { sFailCauseMap = new HashMap<>(); @@ -1737,7 +1389,8 @@ public final class DataFailCause { * * @hide */ - public static boolean isRadioRestartFailure(@NonNull Context context, @FailCause int cause, + public static boolean isRadioRestartFailure(@NonNull Context context, + @DataFailureCause int cause, int subId) { CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); @@ -1765,7 +1418,8 @@ public final class DataFailCause { } /** @hide */ - public static boolean isPermanentFailure(@NonNull Context context, @FailCause int failCause, + public static boolean isPermanentFailure(@NonNull Context context, + @DataFailureCause int failCause, int subId) { synchronized (sPermanentFailureCache) { @@ -1825,7 +1479,7 @@ public final class DataFailCause { } /** @hide */ - public static boolean isEventLoggable(@FailCause int dataFailCause) { + public static boolean isEventLoggable(@DataFailureCause int dataFailCause) { return (dataFailCause == OPERATOR_BARRED) || (dataFailCause == INSUFFICIENT_RESOURCES) || (dataFailCause == UNKNOWN_PDP_ADDRESS_TYPE) || (dataFailCause == USER_AUTHENTICATION) @@ -1845,13 +1499,13 @@ public final class DataFailCause { } /** @hide */ - public static String toString(@FailCause int dataFailCause) { + public static String toString(@DataFailureCause int dataFailCause) { int cause = getFailCause(dataFailCause); return (cause == UNKNOWN) ? "UNKNOWN(" + dataFailCause + ")" : sFailCauseMap.get(cause); } /** @hide */ - public static int getFailCause(@FailCause int failCause) { + public static int getFailCause(@DataFailureCause int failCause) { if (sFailCauseMap.containsKey(failCause)) { return failCause; } else { diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 407ced71a0e7..270eafe642b7 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -203,9 +203,12 @@ public final class DataSpecificRegistrationInfo implements Parcelable { } /** + * Get whether network has configured carrier aggregation or not. + * * @return {@code true} if using carrier aggregation. * @hide */ + @SystemApi public boolean isUsingCarrierAggregation() { return mIsUsingCarrierAggregation; } diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index aa7e21a82500..04ec4b6949af 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -16,6 +16,7 @@ package android.telephony; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; @@ -353,6 +354,12 @@ public final class DisconnectCause { */ public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79; + /** + * Indicates that an emergency call was placed, which caused the existing connection to be + * hung up. + */ + public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; + //********************************************************************************************* // When adding a disconnect type: // 1) Update toString() with the newly added disconnect type. @@ -369,7 +376,7 @@ public final class DisconnectCause { * @hide */ @UnsupportedAppUsage - public static String toString(int cause) { + public static @NonNull String toString(int cause) { switch (cause) { case NOT_DISCONNECTED: return "NOT_DISCONNECTED"; @@ -527,6 +534,8 @@ public final class DisconnectCause { return "EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE"; case WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION: return "WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION"; + case OUTGOING_EMERGENCY_CALL_PLACED: + return "OUTGOING_EMERGENCY_CALL_PLACED"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl index eff64a2e35ba..11263d99cb8f 100644 --- a/telephony/java/android/telephony/ICellBroadcastService.aidl +++ b/telephony/java/android/telephony/ICellBroadcastService.aidl @@ -16,6 +16,9 @@ package android.telephony; +import android.os.RemoteCallback; +import android.telephony.cdma.CdmaSmsCbProgramData; + /** * Service bound to by the system to allow custom handling of cell broadcast messages. * <p> @@ -28,5 +31,9 @@ interface ICellBroadcastService { oneway void handleGsmCellBroadcastSms(int slotId, in byte[] message); /** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */ - oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] message); + oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] bearerData, int serviceCategory); + + /** @see android.telephony.CellBroadcastService#onCdmaScpMessage */ + oneway void handleCdmaScpMessage(int slotId, in List<CdmaSmsCbProgramData> programData, + String originatingAddress, in RemoteCallback callback); } diff --git a/telephony/java/android/telephony/ICellInfoCallback.aidl b/telephony/java/android/telephony/ICellInfoCallback.aidl index ee3c1b1be6d9..60732a3db59a 100644 --- a/telephony/java/android/telephony/ICellInfoCallback.aidl +++ b/telephony/java/android/telephony/ICellInfoCallback.aidl @@ -16,7 +16,6 @@ package android.telephony; -import android.os.ParcelableException; import android.telephony.CellInfo; import java.util.List; @@ -28,5 +27,5 @@ import java.util.List; oneway interface ICellInfoCallback { void onCellInfo(in List<CellInfo> state); - void onError(in int errorCode, in ParcelableException detail); + void onError(in int errorCode, in String exceptionName, in String message); } diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java new file mode 100644 index 000000000000..02d8be3ccfd5 --- /dev/null +++ b/telephony/java/android/telephony/ImsManager.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 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.ims; + +import android.annotation.SystemService; +import android.content.Context; +import android.telephony.SubscriptionManager; + +/** + * Provides access to information about Telephony IMS services on the device. + * + * @hide + */ +@SystemService(Context.TELEPHONY_IMS_SERVICE) +public class ImsManager { + + private Context mContext; + + public ImsManager(Context context) { + mContext = context; + } + + /** + * Create an instance of ImsRcsManager for the subscription id specified. + * + * @param subscriptionId The ID of the subscription that this ImsRcsManager will use. + * @throws IllegalArgumentException if the subscription is invalid. + * @return a ImsRcsManager instance with the specific subscription ID. + */ + public ImsRcsManager getImsRcsManager(int subscriptionId) { + if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId); + } + + return new ImsRcsManager(mContext, subscriptionId); + } + + /** + * Create an instance of ImsMmTelManager for the subscription id specified. + * + * @param subscriptionId The ID of the subscription that this ImsMmTelManager will use. + * @throws IllegalArgumentException if the subscription is invalid. + * @return a ImsMmTelManager instance with the specific subscription ID. + */ + public ImsMmTelManager getImsMmTelManager(int subscriptionId) { + if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId); + } + + return new ImsMmTelManager(subscriptionId); + } +} diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index a76b8da09064..bbf746fcf3c4 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -24,8 +24,8 @@ import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.AccessNetworkConstants.TransportType; -import android.telephony.TelephonyManager.NetworkType; +import android.telephony.Annotation.NetworkType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -323,9 +323,12 @@ public final class NetworkRegistrationInfo implements Parcelable { public @Domain int getDomain() { return mDomain; } /** + * Get the 5G NR connection state. + * * @return the 5G NR connection state. * @hide */ + @SystemApi public @NRState int getNrState() { return mNrState; } diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index af3ba5e44158..4a1bc1f6343f 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -16,12 +16,12 @@ package android.telephony; -import com.android.i18n.phonenumbers.NumberParseException; -import com.android.i18n.phonenumbers.PhoneNumberUtil; -import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; -import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.content.Context; @@ -42,7 +42,10 @@ import android.text.TextUtils; import android.text.style.TtsSpan; import android.util.SparseIntArray; -import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING; +import com.android.i18n.phonenumbers.NumberParseException; +import com.android.i18n.phonenumbers.PhoneNumberUtil; +import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; +import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -2247,8 +2250,10 @@ public class PhoneNumberUtils { * to read the VM number. * @hide */ - @UnsupportedAppUsage - public static boolean isVoiceMailNumber(Context context, int subId, String number) { + @SystemApi + @TestApi + public static boolean isVoiceMailNumber(@NonNull Context context, int subId, + @Nullable String number) { String vmNumber, mdn; try { final TelephonyManager tm; @@ -2734,8 +2739,9 @@ public class PhoneNumberUtils { * @param number * @return true if number contains @ */ - @UnsupportedAppUsage - public static boolean isUriNumber(String number) { + @SystemApi + @TestApi + public static boolean isUriNumber(@Nullable String number) { // Note we allow either "@" or "%40" to indicate a URI, in case // the passed-in string is URI-escaped. (Neither "@" nor "%40" // will ever be found in a legal PSTN number.) @@ -2752,8 +2758,9 @@ public class PhoneNumberUtils { * * @hide */ - @UnsupportedAppUsage - public static String getUsernameFromUriNumber(String number) { + @SystemApi + @TestApi + public static @NonNull String getUsernameFromUriNumber(@NonNull String number) { // The delimiter between username and domain name can be // either "@" or "%40" (the URI-escaped equivalent.) int delimiterIndex = number.indexOf('@'); diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index e1763ab44fba..4273f5a4a16e 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -19,8 +19,8 @@ package android.telephony; import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.TelephonyManager.NetworkType; +import android.telephony.Annotation.NetworkType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index 701a375a3039..f929649453b9 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -41,7 +41,7 @@ import java.util.Objects; * <li>Precise background call state. * </ul> * - * @see android.telephony.TelephonyManager.CallState which contains generic call states. + * @see android.telephony.Annotation.CallState which contains generic call states. * * @hide */ diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index 90d443a6d8ee..257d634f1577 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -23,6 +23,10 @@ import android.annotation.UnsupportedAppUsage; import android.net.LinkProperties; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.ApnType; +import android.telephony.Annotation.DataFailureCause; +import android.telephony.Annotation.DataState; +import android.telephony.Annotation.NetworkType; import android.telephony.data.ApnSetting; import java.util.Objects; @@ -47,10 +51,10 @@ import java.util.Objects; @SystemApi public final class PreciseDataConnectionState implements Parcelable { - private @TelephonyManager.DataState int mState = TelephonyManager.DATA_UNKNOWN; - private @TelephonyManager.NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - private @DataFailCause.FailCause int mFailCause = DataFailCause.NONE; - private @ApnSetting.ApnType int mAPNTypes = ApnSetting.TYPE_NONE; + private @DataState int mState = TelephonyManager.DATA_UNKNOWN; + private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + private @DataFailureCause int mFailCause = DataFailCause.NONE; + private @ApnType int mAPNTypes = ApnSetting.TYPE_NONE; private String mAPN = ""; private LinkProperties mLinkProperties = null; @@ -60,11 +64,11 @@ public final class PreciseDataConnectionState implements Parcelable { * @hide */ @UnsupportedAppUsage - public PreciseDataConnectionState(@TelephonyManager.DataState int state, - @TelephonyManager.NetworkType int networkType, - @ApnSetting.ApnType int apnTypes, String apn, + public PreciseDataConnectionState(@DataState int state, + @NetworkType int networkType, + @ApnType int apnTypes, String apn, LinkProperties linkProperties, - @DataFailCause.FailCause int failCause) { + @DataFailureCause int failCause) { mState = state; mNetworkType = networkType; mAPNTypes = apnTypes; @@ -99,7 +103,7 @@ public final class PreciseDataConnectionState implements Parcelable { * Returns the state of data connection that supported the apn types returned by * {@link #getDataConnectionApnTypeBitMask()} */ - public @TelephonyManager.DataState int getDataConnectionState() { + public @DataState int getDataConnectionState() { return mState; } @@ -107,7 +111,7 @@ public final class PreciseDataConnectionState implements Parcelable { * Returns the network type associated with this data connection. * @hide */ - public @TelephonyManager.NetworkType int getDataConnectionNetworkType() { + public @NetworkType int getDataConnectionNetworkType() { return mNetworkType; } @@ -115,7 +119,7 @@ public final class PreciseDataConnectionState implements Parcelable { * Returns the data connection APN types supported by this connection and triggers * {@link PreciseDataConnectionState} change. */ - public @ApnSetting.ApnType int getDataConnectionApnTypeBitMask() { + public @ApnType int getDataConnectionApnTypeBitMask() { return mAPNTypes; } @@ -139,7 +143,7 @@ public final class PreciseDataConnectionState implements Parcelable { /** * Returns data connection fail cause, in case there was a failure. */ - public @DataFailCause.FailCause int getDataConnectionFailCause() { + public @Annotation.DataFailureCause int getDataConnectionFailCause() { return mFailCause; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index a985a6bd0787..3fd8990ffc9a 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -29,6 +29,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.AccessNetworkConstants.TransportType; +import android.telephony.Annotation.NetworkType; import android.telephony.NetworkRegistrationInfo.Domain; import android.telephony.NetworkRegistrationInfo.NRState; import android.text.TextUtils; @@ -987,6 +988,9 @@ public class ServiceState implements Parcelable { case RIL_RADIO_TECHNOLOGY_LTE_CA: rtString = "LTE_CA"; break; + case RIL_RADIO_TECHNOLOGY_NR: + rtString = "LTE_NR"; + break; default: rtString = "Unexpected"; Rlog.w(LOG_TAG, "Unexpected radioTechnology=" + rt); @@ -1405,9 +1409,12 @@ public class ServiceState implements Parcelable { } /** + * Get the 5G NR frequency range the device is currently registered. + * * @return the frequency range of 5G NR. * @hide */ + @SystemApi public @FrequencyRange int getNrFrequencyRange() { return mNrFrequencyRange; } @@ -1485,44 +1492,44 @@ public class ServiceState implements Parcelable { /** @hide */ public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rat) { switch(rat) { - case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS: + case RIL_RADIO_TECHNOLOGY_GPRS: return TelephonyManager.NETWORK_TYPE_GPRS; - case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE: + case RIL_RADIO_TECHNOLOGY_EDGE: return TelephonyManager.NETWORK_TYPE_EDGE; - case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS: + case RIL_RADIO_TECHNOLOGY_UMTS: return TelephonyManager.NETWORK_TYPE_UMTS; - case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA: + case RIL_RADIO_TECHNOLOGY_HSDPA: return TelephonyManager.NETWORK_TYPE_HSDPA; - case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA: + case RIL_RADIO_TECHNOLOGY_HSUPA: return TelephonyManager.NETWORK_TYPE_HSUPA; - case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA: + case RIL_RADIO_TECHNOLOGY_HSPA: return TelephonyManager.NETWORK_TYPE_HSPA; - case ServiceState.RIL_RADIO_TECHNOLOGY_IS95A: - case ServiceState.RIL_RADIO_TECHNOLOGY_IS95B: + case RIL_RADIO_TECHNOLOGY_IS95A: + case RIL_RADIO_TECHNOLOGY_IS95B: return TelephonyManager.NETWORK_TYPE_CDMA; - case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT: + case RIL_RADIO_TECHNOLOGY_1xRTT: return TelephonyManager.NETWORK_TYPE_1xRTT; - case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0: + case RIL_RADIO_TECHNOLOGY_EVDO_0: return TelephonyManager.NETWORK_TYPE_EVDO_0; - case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A: + case RIL_RADIO_TECHNOLOGY_EVDO_A: return TelephonyManager.NETWORK_TYPE_EVDO_A; - case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B: + case RIL_RADIO_TECHNOLOGY_EVDO_B: return TelephonyManager.NETWORK_TYPE_EVDO_B; - case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD: + case RIL_RADIO_TECHNOLOGY_EHRPD: return TelephonyManager.NETWORK_TYPE_EHRPD; - case ServiceState.RIL_RADIO_TECHNOLOGY_LTE: + case RIL_RADIO_TECHNOLOGY_LTE: return TelephonyManager.NETWORK_TYPE_LTE; - case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: + case RIL_RADIO_TECHNOLOGY_HSPAP: return TelephonyManager.NETWORK_TYPE_HSPAP; - case ServiceState.RIL_RADIO_TECHNOLOGY_GSM: + case RIL_RADIO_TECHNOLOGY_GSM: return TelephonyManager.NETWORK_TYPE_GSM; - case ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA: + case RIL_RADIO_TECHNOLOGY_TD_SCDMA: return TelephonyManager.NETWORK_TYPE_TD_SCDMA; - case ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN: + case RIL_RADIO_TECHNOLOGY_IWLAN: return TelephonyManager.NETWORK_TYPE_IWLAN; - case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA: + case RIL_RADIO_TECHNOLOGY_LTE_CA: return TelephonyManager.NETWORK_TYPE_LTE_CA; - case ServiceState.RIL_RADIO_TECHNOLOGY_NR: + case RIL_RADIO_TECHNOLOGY_NR: return TelephonyManager.NETWORK_TYPE_NR; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; @@ -1553,6 +1560,7 @@ public class ServiceState implements Parcelable { return AccessNetworkType.CDMA2000; case RIL_RADIO_TECHNOLOGY_LTE: case RIL_RADIO_TECHNOLOGY_LTE_CA: + case RIL_RADIO_TECHNOLOGY_NR: return AccessNetworkType.EUTRAN; case RIL_RADIO_TECHNOLOGY_IWLAN: return AccessNetworkType.IWLAN; @@ -1566,43 +1574,45 @@ public class ServiceState implements Parcelable { public static int networkTypeToRilRadioTechnology(int networkType) { switch(networkType) { case TelephonyManager.NETWORK_TYPE_GPRS: - return ServiceState.RIL_RADIO_TECHNOLOGY_GPRS; + return RIL_RADIO_TECHNOLOGY_GPRS; case TelephonyManager.NETWORK_TYPE_EDGE: - return ServiceState.RIL_RADIO_TECHNOLOGY_EDGE; + return RIL_RADIO_TECHNOLOGY_EDGE; case TelephonyManager.NETWORK_TYPE_UMTS: - return ServiceState.RIL_RADIO_TECHNOLOGY_UMTS; + return RIL_RADIO_TECHNOLOGY_UMTS; case TelephonyManager.NETWORK_TYPE_HSDPA: - return ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA; + return RIL_RADIO_TECHNOLOGY_HSDPA; case TelephonyManager.NETWORK_TYPE_HSUPA: - return ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA; + return RIL_RADIO_TECHNOLOGY_HSUPA; case TelephonyManager.NETWORK_TYPE_HSPA: - return ServiceState.RIL_RADIO_TECHNOLOGY_HSPA; + return RIL_RADIO_TECHNOLOGY_HSPA; case TelephonyManager.NETWORK_TYPE_CDMA: - return ServiceState.RIL_RADIO_TECHNOLOGY_IS95A; + return RIL_RADIO_TECHNOLOGY_IS95A; case TelephonyManager.NETWORK_TYPE_1xRTT: - return ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT; + return RIL_RADIO_TECHNOLOGY_1xRTT; case TelephonyManager.NETWORK_TYPE_EVDO_0: - return ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0; + return RIL_RADIO_TECHNOLOGY_EVDO_0; case TelephonyManager.NETWORK_TYPE_EVDO_A: - return ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A; + return RIL_RADIO_TECHNOLOGY_EVDO_A; case TelephonyManager.NETWORK_TYPE_EVDO_B: - return ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B; + return RIL_RADIO_TECHNOLOGY_EVDO_B; case TelephonyManager.NETWORK_TYPE_EHRPD: - return ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD; + return RIL_RADIO_TECHNOLOGY_EHRPD; case TelephonyManager.NETWORK_TYPE_LTE: - return ServiceState.RIL_RADIO_TECHNOLOGY_LTE; + return RIL_RADIO_TECHNOLOGY_LTE; case TelephonyManager.NETWORK_TYPE_HSPAP: - return ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP; + return RIL_RADIO_TECHNOLOGY_HSPAP; case TelephonyManager.NETWORK_TYPE_GSM: - return ServiceState.RIL_RADIO_TECHNOLOGY_GSM; + return RIL_RADIO_TECHNOLOGY_GSM; case TelephonyManager.NETWORK_TYPE_TD_SCDMA: - return ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA; + return RIL_RADIO_TECHNOLOGY_TD_SCDMA; case TelephonyManager.NETWORK_TYPE_IWLAN: - return ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN; + return RIL_RADIO_TECHNOLOGY_IWLAN; case TelephonyManager.NETWORK_TYPE_LTE_CA: - return ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA; + return RIL_RADIO_TECHNOLOGY_LTE_CA; + case TelephonyManager.NETWORK_TYPE_NR: + return RIL_RADIO_TECHNOLOGY_NR; default: - return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; + return RIL_RADIO_TECHNOLOGY_UNKNOWN; } } @@ -1617,7 +1627,7 @@ public class ServiceState implements Parcelable { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public @TelephonyManager.NetworkType int getDataNetworkType() { + public @NetworkType int getDataNetworkType() { final NetworkRegistrationInfo iwlanRegInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN); final NetworkRegistrationInfo wwanRegInfo = getNetworkRegistrationInfo( @@ -1644,7 +1654,7 @@ public class ServiceState implements Parcelable { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public @TelephonyManager.NetworkType int getVoiceNetworkType() { + public @NetworkType int getVoiceNetworkType() { final NetworkRegistrationInfo regState = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (regState != null) { @@ -1691,7 +1701,8 @@ public class ServiceState implements Parcelable { || radioTechnology == RIL_RADIO_TECHNOLOGY_GSM || radioTechnology == RIL_RADIO_TECHNOLOGY_TD_SCDMA || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN - || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA; + || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA + || radioTechnology == RIL_RADIO_TECHNOLOGY_NR; } @@ -1967,8 +1978,11 @@ public class ServiceState implements Parcelable { /** * The current registered raw data network operator name in long alphanumeric format. * + * @return long raw name of operator, null if unregistered or unknown * @hide */ + @Nullable + @SystemApi public String getOperatorAlphaLongRaw() { return mOperatorAlphaLongRaw; } @@ -1983,8 +1997,11 @@ public class ServiceState implements Parcelable { /** * The current registered raw data network operator name in short alphanumeric format. * + * @return short raw name of operator, null if unregistered or unknown * @hide */ + @Nullable + @SystemApi public String getOperatorAlphaShortRaw() { return mOperatorAlphaShortRaw; } diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index dc991b9a3ea7..3e044e52d28b 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -25,9 +25,7 @@ import android.database.Cursor; import android.os.Parcel; import android.os.Parcelable; import android.provider.Telephony.CellBroadcasts; - -import com.android.internal.telephony.CbGeoUtils; -import com.android.internal.telephony.CbGeoUtils.Geometry; +import android.telephony.CbGeoUtils.Geometry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -414,9 +412,8 @@ public final class SmsCbMessage implements Parcelable { /** * Get the Geo-Fencing Maximum Wait Time. * @return the time in second. - * @hide */ - public int getMaximumWaitingTime() { + public int getMaximumWaitingDuration() { return mMaximumWaitTimeSec; } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 209d46253a07..daeacf8206b4 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -27,25 +27,20 @@ import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.app.PendingIntent; -import android.content.ContentValues; import android.content.Context; -import android.content.Intent; import android.content.pm.PackageManager; import android.database.CursorWindow; import android.net.Uri; -import android.os.BaseBundle; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.provider.Telephony; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import com.android.internal.telephony.IIntegerConsumer; -import com.android.internal.telephony.IMms; import com.android.internal.telephony.ISms; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.SmsRawData; @@ -292,12 +287,6 @@ public final class SmsManager { */ public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1; - /** - * Extra key passed into a PendingIntent when the SMS operation failed due to there being no - * default set. - */ - private static final String NO_DEFAULT_EXTRA = "noDefault"; - // result of asking the user for a subscription to perform an operation. private interface SubscriptionResolverResult { void onSuccess(int subId); @@ -338,9 +327,59 @@ public final class SmsManager { * <code>RESULT_ERROR_RADIO_OFF</code><br> * <code>RESULT_ERROR_NULL_PDU</code><br> * <code>RESULT_ERROR_NO_SERVICE</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> + * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> + * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_NETWORK_REJECT</code><br> + * <code>RESULT_INVALID_ARGUMENTS</code><br> + * <code>RESULT_INVALID_STATE</code><br> + * <code>RESULT_NO_MEMORY</code><br> + * <code>RESULT_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_SYSTEM_ERROR</code><br> + * <code>RESULT_MODEM_ERROR</code><br> + * <code>RESULT_NETWORK_ERROR</code><br> + * <code>RESULT_ENCODING_ERROR</code><br> + * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_INTERNAL_ERROR</code><br> + * <code>RESULT_NO_RESOURCES</code><br> + * <code>RESULT_CANCELLED</code><br> + * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> + * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> + * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> + * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> + * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> + * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> + * <code>RESULT_REMOTE_EXCEPTION</code><br> + * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> + * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> + * <code>RESULT_RIL_NETWORK_REJECT</code><br> + * <code>RESULT_RIL_INVALID_STATE</code><br> + * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> + * <code>RESULT_RIL_NO_MEMORY</code><br> + * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> + * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_RIL_SYSTEM_ERR</code><br> + * <code>RESULT_RIL_ENCODING_ERR</code><br> + * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_RIL_MODEM_ERR</code><br> + * <code>RESULT_RIL_NETWORK_ERR</code><br> + * <code>RESULT_RIL_INTERNAL_ERR</code><br> + * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> + * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> + * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_RIL_NO_RESOURCES</code><br> + * <code>RESULT_RIL_CANCELLED</code><br> + * <code>RESULT_RIL_SIM_ABSENT</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, + * the sentIntent may include the extra "errorCode" containing a radio technology specific + * value, generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. @@ -357,6 +396,119 @@ public final class SmsManager { true /* persistMessage*/, ActivityThread.currentPackageName()); } + /** + * Send a text based SMS with messaging options. + * + * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this + * manager on a multi-SIM device, this operation may fail sending the SMS message because no + * suitable default subscription could be found. In this case, if {@code sentIntent} is + * non-null, then the {@link PendingIntent} will be sent with an error code + * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the + * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions + * where this operation may fail. + * </p> + * + * @param destinationAddress the address to send the message to + * @param scAddress is the service center address or null to use + * the current default SMSC + * @param text the body of the message to send + * @param sentIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is successfully sent, or failed. + * The result code will be <code>Activity.RESULT_OK</code> for success, + * or one of these errors:<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> + * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> + * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_NETWORK_REJECT</code><br> + * <code>RESULT_INVALID_ARGUMENTS</code><br> + * <code>RESULT_INVALID_STATE</code><br> + * <code>RESULT_NO_MEMORY</code><br> + * <code>RESULT_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_SYSTEM_ERROR</code><br> + * <code>RESULT_MODEM_ERROR</code><br> + * <code>RESULT_NETWORK_ERROR</code><br> + * <code>RESULT_ENCODING_ERROR</code><br> + * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_INTERNAL_ERROR</code><br> + * <code>RESULT_NO_RESOURCES</code><br> + * <code>RESULT_CANCELLED</code><br> + * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> + * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> + * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> + * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> + * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> + * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> + * <code>RESULT_REMOTE_EXCEPTION</code><br> + * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> + * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> + * <code>RESULT_RIL_NETWORK_REJECT</code><br> + * <code>RESULT_RIL_INVALID_STATE</code><br> + * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> + * <code>RESULT_RIL_NO_MEMORY</code><br> + * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> + * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_RIL_SYSTEM_ERR</code><br> + * <code>RESULT_RIL_ENCODING_ERR</code><br> + * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_RIL_MODEM_ERR</code><br> + * <code>RESULT_RIL_NETWORK_ERR</code><br> + * <code>RESULT_RIL_INTERNAL_ERR</code><br> + * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> + * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> + * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_RIL_NO_RESOURCES</code><br> + * <code>RESULT_RIL_CANCELLED</code><br> + * <code>RESULT_RIL_SIM_ABSENT</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, + * the sentIntent may include the extra "errorCode" containing a radio technology specific + * value, generally only useful for troubleshooting.<br> + * The per-application based SMS control checks sentIntent. If sentIntent + * is NULL the caller will be checked against all unknown applications, + * which cause smaller number of SMS to be sent in checking period. + * @param deliveryIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is delivered to the recipient. The + * raw pdu of the status report is in the extended data ("pdu"). + * @param priority Priority level of the message + * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 + * --------------------------------- + * PRIORITY | Level of Priority + * --------------------------------- + * '00' | Normal + * '01' | Interactive + * '10' | Urgent + * '11' | Emergency + * ---------------------------------- + * Any Other values included Negative considered as Invalid Priority Indicator of the message. + * @param expectMore is a boolean to indicate the sending messages through same link or not. + * @param validityPeriod Validity Period of the message in mins. + * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. + * Validity Period(Minimum) -> 5 mins + * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). + * Any Other values included Negative considered as Invalid Validity Period of the message. + * + * @throws IllegalArgumentException if destinationAddress or text are empty + * {@hide} + */ + @UnsupportedAppUsage + public void sendTextMessage( + String destinationAddress, String scAddress, String text, + PendingIntent sentIntent, PendingIntent deliveryIntent, + int priority, boolean expectMore, int validityPeriod) { + sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, + true /* persistMessage*/, priority, expectMore, validityPeriod); + } + private void sendTextMessageInternal(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, String packageName) { @@ -368,7 +520,6 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message body"); } - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -391,13 +542,13 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - " + e.getMessage()); - notifySmsGenericError(sentIntent); + notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); } } @Override public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntent); + notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); } }); } else { @@ -411,7 +562,7 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendTextMessageInternal (no persist): Couldn't send SMS, exception - " + e.getMessage()); - notifySmsGenericError(sentIntent); + notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); } } } @@ -455,109 +606,6 @@ public final class SmsManager { false /* persistMessage */, ActivityThread.currentPackageName()); } - /** - * A variant of {@link SmsManager#sendTextMessage} that allows self to be the caller. This is - * for internal use only. - * - * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier - * applications or the Telephony framework and will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the SMS being sent on the subscription associated with logical - * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the - * correct subscription. - * </p> - * - * @param persistMessage whether to persist the sent message in the SMS app. the caller must be - * the Phone process if set to false. - * - * @hide - */ - public void sendTextMessageWithSelfPermissions( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - - if (TextUtils.isEmpty(text)) { - throw new IllegalArgumentException("Invalid message body"); - } - - try { - ISms iSms = getISmsServiceOrThrow(); - iSms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), - ActivityThread.currentPackageName(), - destinationAddress, - scAddress, text, sentIntent, deliveryIntent, persistMessage); - } catch (RemoteException ex) { - notifySmsGenericError(sentIntent); - } - } - - /** - * Send a text based SMS with messaging options. - * - * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this - * manager on a multi-SIM device, this operation may fail sending the SMS message because no - * suitable default subscription could be found. In this case, if {@code sentIntent} is - * non-null, then the {@link PendingIntent} will be sent with an error code - * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the - * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions - * where this operation may fail. - * </p> - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param text the body of the message to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is successfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK</code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * @param priority Priority level of the message - * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 - * --------------------------------- - * PRIORITY | Level of Priority - * --------------------------------- - * '00' | Normal - * '01' | Interactive - * '10' | Urgent - * '11' | Emergency - * ---------------------------------- - * Any Other values included Negative considered as Invalid Priority Indicator of the message. - * @param expectMore is a boolean to indicate the sending messages through same link or not. - * @param validityPeriod Validity Period of the message in mins. - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * Validity Period(Minimum) -> 5 mins - * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). - * Any Other values included Negative considered as Invalid Validity Period of the message. - * - * @throws IllegalArgumentException if destinationAddress or text are empty - * {@hide} - */ - @UnsupportedAppUsage - public void sendTextMessage( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent, - int priority, boolean expectMore, int validityPeriod) { - sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, - true /* persistMessage*/, priority, expectMore, validityPeriod); - } - private void sendTextMessageInternal( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, @@ -580,7 +628,6 @@ public final class SmsManager { final int finalPriority = priority; final int finalValidity = validityPeriod; - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -607,13 +654,13 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - " + e.getMessage()); - notifySmsGenericError(sentIntent); + notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); } } @Override public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntent); + notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); } }); } else { @@ -629,7 +676,7 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendTextMessageInternal(no persist): Couldn't send SMS, exception - " + e.getMessage()); - notifySmsGenericError(sentIntent); + notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); } } } @@ -711,7 +758,7 @@ public final class SmsManager { } catch (RemoteException ex) { try { if (receivedIntent != null) { - receivedIntent.send(Telephony.Sms.Intents.RESULT_SMS_GENERIC_ERROR); + receivedIntent.send(RESULT_REMOTE_EXCEPTION); } } catch (PendingIntent.CanceledException cx) { // Don't worry about it, we do not need to notify the caller if this is the case. @@ -767,12 +814,63 @@ public final class SmsManager { * broadcast when the corresponding message part has been sent. * The result code will be <code>Activity.RESULT_OK</code> for success, * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> + * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> + * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_NETWORK_REJECT</code><br> + * <code>RESULT_INVALID_ARGUMENTS</code><br> + * <code>RESULT_INVALID_STATE</code><br> + * <code>RESULT_NO_MEMORY</code><br> + * <code>RESULT_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_SYSTEM_ERROR</code><br> + * <code>RESULT_MODEM_ERROR</code><br> + * <code>RESULT_NETWORK_ERROR</code><br> + * <code>RESULT_ENCODING_ERROR</code><br> + * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_INTERNAL_ERROR</code><br> + * <code>RESULT_NO_RESOURCES</code><br> + * <code>RESULT_CANCELLED</code><br> + * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> + * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> + * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> + * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> + * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> + * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> + * <code>RESULT_REMOTE_EXCEPTION</code><br> + * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> + * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> + * <code>RESULT_RIL_NETWORK_REJECT</code><br> + * <code>RESULT_RIL_INVALID_STATE</code><br> + * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> + * <code>RESULT_RIL_NO_MEMORY</code><br> + * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> + * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_RIL_SYSTEM_ERR</code><br> + * <code>RESULT_RIL_ENCODING_ERR</code><br> + * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_RIL_MODEM_ERR</code><br> + * <code>RESULT_RIL_NETWORK_ERR</code><br> + * <code>RESULT_RIL_INTERNAL_ERR</code><br> + * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> + * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> + * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_RIL_NO_RESOURCES</code><br> + * <code>RESULT_RIL_CANCELLED</code><br> + * <code>RESULT_RIL_SIM_ABSENT</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, + * the sentIntent may include the extra "errorCode" containing a radio technology specific + * value, generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. @@ -809,10 +907,12 @@ public final class SmsManager { * {@link ActivityThread#currentPackageName()} is null. * @hide */ - public void sendMultipartTextMessageExternal( - String destinationAddress, String scAddress, ArrayList<String> parts, - ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, - String packageName) { + @SystemApi + @TestApi + public void sendMultipartTextMessage( + @NonNull String destinationAddress, @NonNull String scAddress, + @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents, + @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName) { sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, deliveryIntents, true /* persistMessage*/, ActivityThread.currentPackageName() == null @@ -831,7 +931,6 @@ public final class SmsManager { } if (parts.size() > 1) { - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -854,13 +953,13 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " + e.getMessage()); - notifySmsGenericError(sentIntents); + notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); } } @Override public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntents); + notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP); } }); } else { @@ -875,7 +974,7 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " + e.getMessage()); - notifySmsGenericError(sentIntents); + notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); } } } else { @@ -954,12 +1053,63 @@ public final class SmsManager { * broadcast when the corresponding message part has been sent. * The result code will be <code>Activity.RESULT_OK</code> for success, * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> + * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> + * <code>RESULT_ERROR_RADIO_OFF</code><br> + * <code>RESULT_ERROR_NULL_PDU</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> + * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> + * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_NETWORK_REJECT</code><br> + * <code>RESULT_INVALID_ARGUMENTS</code><br> + * <code>RESULT_INVALID_STATE</code><br> + * <code>RESULT_NO_MEMORY</code><br> + * <code>RESULT_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_SYSTEM_ERROR</code><br> + * <code>RESULT_MODEM_ERROR</code><br> + * <code>RESULT_NETWORK_ERROR</code><br> + * <code>RESULT_ENCODING_ERROR</code><br> + * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_INTERNAL_ERROR</code><br> + * <code>RESULT_NO_RESOURCES</code><br> + * <code>RESULT_CANCELLED</code><br> + * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> + * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> + * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> + * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> + * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> + * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> + * <code>RESULT_REMOTE_EXCEPTION</code><br> + * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> + * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> + * <code>RESULT_RIL_NETWORK_REJECT</code><br> + * <code>RESULT_RIL_INVALID_STATE</code><br> + * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> + * <code>RESULT_RIL_NO_MEMORY</code><br> + * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> + * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_RIL_SYSTEM_ERR</code><br> + * <code>RESULT_RIL_ENCODING_ERR</code><br> + * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_RIL_MODEM_ERR</code><br> + * <code>RESULT_RIL_NETWORK_ERR</code><br> + * <code>RESULT_RIL_INTERNAL_ERR</code><br> + * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> + * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> + * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_RIL_NO_RESOURCES</code><br> + * <code>RESULT_RIL_CANCELLED</code><br> + * <code>RESULT_RIL_SIM_ABSENT</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, + * the sentIntent may include the extra "errorCode" containing a radio technology specific + * value, generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. @@ -1021,7 +1171,6 @@ public final class SmsManager { if (parts.size() > 1) { final int finalPriority = priority; final int finalValidity = validityPeriod; - final Context context = ActivityThread.currentApplication().getApplicationContext(); if (persistMessage) { resolveSubscriptionForOperation(new SubscriptionResolverResult() { @Override @@ -1037,13 +1186,13 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - " + e.getMessage()); - notifySmsGenericError(sentIntents); + notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); } } @Override public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntents); + notifySmsError(sentIntents, RESULT_NO_DEFAULT_SMS_APP); } }); } else { @@ -1059,7 +1208,7 @@ public final class SmsManager { } catch (RemoteException e) { Log.e(TAG, "sendMultipartTextMessageInternal (no persist): Couldn't send SMS - " + e.getMessage()); - notifySmsGenericError(sentIntents); + notifySmsError(sentIntents, RESULT_REMOTE_EXCEPTION); } } } else { @@ -1078,37 +1227,6 @@ public final class SmsManager { } /** - * Send a multi-part text based SMS without writing it into the SMS Provider. - * - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier - * privileges. - * </p> - * - * <p class="note"><strong>Note:</strong> This method is intended for internal use the Telephony - * framework and will never trigger an SMS disambiguation dialog. If this method is called on a - * device that has multiple active subscriptions, this {@link SmsManager} instance has been - * created with {@link #getDefault()}, and no user-defined default subscription is defined, the - * subscription ID associated with this message will be INVALID, which will result in the SMS - * being sent on the subscription associated with logical slot 0. Use - * {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the correct - * subscription. - * </p> - * - * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, - * ArrayList, int, boolean, int) - * @hide - **/ - public void sendMultipartTextMessageWithoutPersisting( - String destinationAddress, String scAddress, List<String> parts, - List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, - int priority, boolean expectMore, int validityPeriod) { - sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, - deliveryIntents, false /* persistMessage*/, priority, expectMore, - validityPeriod); - } - - /** * Send a data based SMS to a specific application port. * * <p class="note"><strong>Note:</strong> Using this method requires that your app has the @@ -1135,9 +1253,60 @@ public final class SmsManager { * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> * <code>RESULT_ERROR_RADIO_OFF</code><br> * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_NO_SERVICE</code><br> + * <code>RESULT_ERROR_LIMIT_EXCEEDED</code><br> + * <code>RESULT_ERROR_FDN_CHECK_FAILURE</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br> + * <code>RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br> + * <code>RESULT_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_NETWORK_REJECT</code><br> + * <code>RESULT_INVALID_ARGUMENTS</code><br> + * <code>RESULT_INVALID_STATE</code><br> + * <code>RESULT_NO_MEMORY</code><br> + * <code>RESULT_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_SYSTEM_ERROR</code><br> + * <code>RESULT_MODEM_ERROR</code><br> + * <code>RESULT_NETWORK_ERROR</code><br> + * <code>RESULT_ENCODING_ERROR</code><br> + * <code>RESULT_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_INTERNAL_ERROR</code><br> + * <code>RESULT_NO_RESOURCES</code><br> + * <code>RESULT_CANCELLED</code><br> + * <code>RESULT_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_NO_BLUETOOTH_SERVICE</code><br> + * <code>RESULT_INVALID_BLUETOOTH_ADDRESS</code><br> + * <code>RESULT_BLUETOOTH_DISCONNECTED</code><br> + * <code>RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br> + * <code>RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br> + * <code>RESULT_SMS_SEND_RETRY_FAILED</code><br> + * <code>RESULT_REMOTE_EXCEPTION</code><br> + * <code>RESULT_NO_DEFAULT_SMS_APP</code><br> + * <code>RESULT_RIL_RADIO_NOT_AVAILABLE</code><br> + * <code>RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br> + * <code>RESULT_RIL_NETWORK_REJECT</code><br> + * <code>RESULT_RIL_INVALID_STATE</code><br> + * <code>RESULT_RIL_INVALID_ARGUMENTS</code><br> + * <code>RESULT_RIL_NO_MEMORY</code><br> + * <code>RESULT_RIL_REQUEST_RATE_LIMITED</code><br> + * <code>RESULT_RIL_INVALID_SMS_FORMAT</code><br> + * <code>RESULT_RIL_SYSTEM_ERR</code><br> + * <code>RESULT_RIL_ENCODING_ERR</code><br> + * <code>RESULT_RIL_INVALID_SMSC_ADDRESS</code><br> + * <code>RESULT_RIL_MODEM_ERR</code><br> + * <code>RESULT_RIL_NETWORK_ERR</code><br> + * <code>RESULT_RIL_INTERNAL_ERR</code><br> + * <code>RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br> + * <code>RESULT_RIL_INVALID_MODEM_STATE</code><br> + * <code>RESULT_RIL_NETWORK_NOT_READY</code><br> + * <code>RESULT_RIL_OPERATION_NOT_ALLOWED</code><br> + * <code>RESULT_RIL_NO_RESOURCES</code><br> + * <code>RESULT_RIL_CANCELLED</code><br> + * <code>RESULT_RIL_SIM_ABSENT</code><br> + * For <code>RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors, + * the sentIntent may include the extra "errorCode" containing a radio technology specific + * value, generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. @@ -1158,7 +1327,6 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message data"); } - final Context context = ActivityThread.currentApplication().getApplicationContext(); resolveSubscriptionForOperation(new SubscriptionResolverResult() { @Override public void onSuccess(int subId) { @@ -1169,56 +1337,17 @@ public final class SmsManager { sentIntent, deliveryIntent); } catch (RemoteException e) { Log.e(TAG, "sendDataMessage: Couldn't send SMS - Exception: " + e.getMessage()); - notifySmsGenericError(sentIntent); + notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION); } } @Override public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntent); + notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); } }); } /** - * A variant of {@link SmsManager#sendDataMessage} that allows self to be the caller. This is - * for internal use only. - * - * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier - * applications or the Telephony framework and will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the SMS being sent on the subscription associated with logical - * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the - * correct subscription. - * </p> - * - * @hide - */ - public void sendDataMessageWithSelfPermissions( - String destinationAddress, String scAddress, short destinationPort, - byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - - if (data == null || data.length == 0) { - throw new IllegalArgumentException("Invalid message data"); - } - - try { - ISms iSms = getISmsServiceOrThrow(); - iSms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), - ActivityThread.currentPackageName(), destinationAddress, scAddress, - destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); - } catch (RemoteException e) { - Log.e(TAG, "sendDataMessageWithSelfPermissions: Couldn't send SMS - Exception: " - + e.getMessage()); - notifySmsGenericError(sentIntent); - } - } - - /** * Get the SmsManager associated with the default subscription id. The instance will always be * associated with the default subscription id, even if the default subscription id changes. * @@ -1418,53 +1547,20 @@ public final class SmsManager { return binder; } - private static void notifySmsErrorNoDefaultSet(Context context, PendingIntent pendingIntent) { - if (pendingIntent != null) { - Intent errorMessage = new Intent(); - errorMessage.putExtra(NO_DEFAULT_EXTRA, true); - try { - pendingIntent.send(context, RESULT_ERROR_GENERIC_FAILURE, errorMessage); - } catch (PendingIntent.CanceledException e) { - // Don't worry about it, we do not need to notify the caller if this is the case. - } - } - } - - private static void notifySmsErrorNoDefaultSet(Context context, - List<PendingIntent> pendingIntents) { - if (pendingIntents != null) { - for (PendingIntent pendingIntent : pendingIntents) { - Intent errorMessage = new Intent(); - errorMessage.putExtra(NO_DEFAULT_EXTRA, true); - try { - pendingIntent.send(context, RESULT_ERROR_GENERIC_FAILURE, errorMessage); - } catch (PendingIntent.CanceledException e) { - // Don't worry about it, we do not need to notify the caller if this is the - // case. - } - } - } - } - - private static void notifySmsGenericError(PendingIntent pendingIntent) { + private static void notifySmsError(PendingIntent pendingIntent, int error) { if (pendingIntent != null) { try { - pendingIntent.send(RESULT_ERROR_GENERIC_FAILURE); + pendingIntent.send(error); } catch (PendingIntent.CanceledException e) { // Don't worry about it, we do not need to notify the caller if this is the case. } } } - private static void notifySmsGenericError(List<PendingIntent> pendingIntents) { + private static void notifySmsError(List<PendingIntent> pendingIntents, int error) { if (pendingIntents != null) { for (PendingIntent pendingIntent : pendingIntents) { - try { - pendingIntent.send(RESULT_ERROR_GENERIC_FAILURE); - } catch (PendingIntent.CanceledException e) { - // Don't worry about it, we do not need to notify the caller if this is the - // case. - } + notifySmsError(pendingIntent, error); } } } @@ -1650,100 +1746,6 @@ public final class SmsManager { /** * Enable reception of cell broadcast (SMS-CB) messages with the given - * message identifier and RAN type. The RAN type specify this message ID - * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients - * enable the same message identifier, they must both disable it for the device to stop - * receiving those messages. All received messages will be broadcast in an - * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". - * Note: This call is blocking, callers may want to avoid calling it from - * the main thread of an application. - * - * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier - * applications or the Telephony framework and will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the operation being completed on the subscription associated - * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the - * operation is performed on the correct subscription. - * </p> - * - * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) - * or C.R1001-G (3GPP2) - * @param ranType the message format as defined in {@link SmsCbMessage] - * @return true if successful, false otherwise - * @see #disableCellBroadcast(int, int) - * - * {@hide} - */ - public boolean enableCellBroadcast(int messageIdentifier, - @android.telephony.SmsCbMessage.MessageFormat int ranType) { - boolean success = false; - - try { - ISms iSms = getISmsService(); - if (iSms != null) { - // If getSubscriptionId() returns INVALID or an inactive subscription, we will use - // the default phone internally. - success = iSms.enableCellBroadcastForSubscriber(getSubscriptionId(), - messageIdentifier, ranType); - } - } catch (RemoteException ex) { - // ignore it - } - - return success; - } - - /** - * Disable reception of cell broadcast (SMS-CB) messages with the given - * message identifier and RAN type. The RAN type specify this message ID - * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients - * enable the same message identifier, they must both disable it for the - * device to stop receiving those messages. - * Note: This call is blocking, callers may want to avoid calling it from - * the main thread of an application. - * - * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier - * applications or the Telephony framework and will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the operation being completed on the subscription associated - * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the - * operation is performed on the correct subscription. - * </p> - * - * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) - * or C.R1001-G (3GPP2) - * @param ranType the message format as defined in {@link SmsCbMessage} - * @return true if successful, false otherwise - * - * @see #enableCellBroadcast(int, int) - * - * {@hide} - */ - public boolean disableCellBroadcast(int messageIdentifier, - @android.telephony.SmsCbMessage.MessageFormat int ranType) { - boolean success = false; - - try { - ISms iSms = getISmsService(); - if (iSms != null) { - // If getSubscriptionId() returns INVALID or an inactive subscription, we will use - // the default phone internally. - success = iSms.disableCellBroadcastForSubscriber(getSubscriptionId(), - messageIdentifier, ranType); - } - } catch (RemoteException ex) { - // ignore it - } - - return success; - } - - /** - * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier range and RAN type. The RAN type specifies if this message ID * belongs to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable * the same message identifier, they must both disable it for the device to stop @@ -2005,19 +2007,19 @@ public final class SmsManager { // see SmsMessage.getStatusOnIcc /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ - static public final int STATUS_ON_ICC_FREE = 0; + public static final int STATUS_ON_ICC_FREE = 0; /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ - static public final int STATUS_ON_ICC_READ = 1; + public static final int STATUS_ON_ICC_READ = 1; /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ - static public final int STATUS_ON_ICC_UNREAD = 3; + public static final int STATUS_ON_ICC_UNREAD = 3; /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ - static public final int STATUS_ON_ICC_SENT = 5; + public static final int STATUS_ON_ICC_SENT = 5; /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ - static public final int STATUS_ON_ICC_UNSENT = 7; + public static final int STATUS_ON_ICC_UNSENT = 7; // SMS send failure result codes @@ -2053,129 +2055,263 @@ public final class SmsManager { /** * No error. - * @hide */ - @SystemApi - static public final int RESULT_ERROR_NONE = 0; + public static final int RESULT_ERROR_NONE = 0; + /** Generic failure cause */ - static public final int RESULT_ERROR_GENERIC_FAILURE = 1; + public static final int RESULT_ERROR_GENERIC_FAILURE = 1; + /** Failed because radio was explicitly turned off */ - static public final int RESULT_ERROR_RADIO_OFF = 2; + public static final int RESULT_ERROR_RADIO_OFF = 2; + /** Failed because no pdu provided */ - static public final int RESULT_ERROR_NULL_PDU = 3; + public static final int RESULT_ERROR_NULL_PDU = 3; + /** Failed because service is currently unavailable */ - static public final int RESULT_ERROR_NO_SERVICE = 4; + public static final int RESULT_ERROR_NO_SERVICE = 4; + /** Failed because we reached the sending queue limit. */ - static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; + public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; + /** * Failed because FDN is enabled. - * @hide */ - @SystemApi - static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; + public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; + /** Failed because user denied the sending of this short code. */ - static public final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; + public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; + /** Failed because the user has denied this app ever send premium short codes. */ - static public final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; + public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; + /** * Failed because the radio was not available - * @hide */ - @SystemApi - static public final int RESULT_RADIO_NOT_AVAILABLE = 9; + public static final int RESULT_RADIO_NOT_AVAILABLE = 9; + /** * Failed because of network rejection - * @hide */ - @SystemApi - static public final int RESULT_NETWORK_REJECT = 10; + public static final int RESULT_NETWORK_REJECT = 10; + /** * Failed because of invalid arguments - * @hide */ - @SystemApi - static public final int RESULT_INVALID_ARGUMENTS = 11; + public static final int RESULT_INVALID_ARGUMENTS = 11; + /** * Failed because of an invalid state - * @hide */ - @SystemApi - static public final int RESULT_INVALID_STATE = 12; + public static final int RESULT_INVALID_STATE = 12; + /** * Failed because there is no memory - * @hide */ - @SystemApi - static public final int RESULT_NO_MEMORY = 13; + public static final int RESULT_NO_MEMORY = 13; + /** * Failed because the sms format is not valid - * @hide */ - @SystemApi - static public final int RESULT_INVALID_SMS_FORMAT = 14; + public static final int RESULT_INVALID_SMS_FORMAT = 14; + /** * Failed because of a system error - * @hide */ - @SystemApi - static public final int RESULT_SYSTEM_ERROR = 15; + public static final int RESULT_SYSTEM_ERROR = 15; + /** * Failed because of a modem error - * @hide */ - @SystemApi - static public final int RESULT_MODEM_ERROR = 16; + public static final int RESULT_MODEM_ERROR = 16; + /** * Failed because of a network error - * @hide */ - @SystemApi - static public final int RESULT_NETWORK_ERROR = 17; + public static final int RESULT_NETWORK_ERROR = 17; + /** * Failed because of an encoding error - * @hide */ - @SystemApi - static public final int RESULT_ENCODING_ERROR = 18; + public static final int RESULT_ENCODING_ERROR = 18; + /** * Failed because of an invalid smsc address - * @hide */ - @SystemApi - static public final int RESULT_INVALID_SMSC_ADDRESS = 19; + public static final int RESULT_INVALID_SMSC_ADDRESS = 19; + /** * Failed because the operation is not allowed - * @hide */ - @SystemApi - static public final int RESULT_OPERATION_NOT_ALLOWED = 20; + public static final int RESULT_OPERATION_NOT_ALLOWED = 20; + /** * Failed because of an internal error - * @hide */ - @SystemApi - static public final int RESULT_INTERNAL_ERROR = 21; + public static final int RESULT_INTERNAL_ERROR = 21; + /** * Failed because there are no resources - * @hide */ - @SystemApi - static public final int RESULT_NO_RESOURCES = 22; + public static final int RESULT_NO_RESOURCES = 22; + /** * Failed because the operation was cancelled - * @hide */ - @SystemApi - static public final int RESULT_CANCELLED = 23; + public static final int RESULT_CANCELLED = 23; + /** * Failed because the request is not supported - * @hide */ - @SystemApi - static public final int RESULT_REQUEST_NOT_SUPPORTED = 24; + public static final int RESULT_REQUEST_NOT_SUPPORTED = 24; + + /** + * Failed sending via bluetooth because the bluetooth service is not available + */ + public static final int RESULT_NO_BLUETOOTH_SERVICE = 25; + /** + * Failed sending via bluetooth because the bluetooth device address is invalid + */ + public static final int RESULT_INVALID_BLUETOOTH_ADDRESS = 26; - static private final String PHONE_PACKAGE_NAME = "com.android.phone"; + /** + * Failed sending via bluetooth because bluetooth disconnected + */ + public static final int RESULT_BLUETOOTH_DISCONNECTED = 27; + + /** + * Failed sending because the user denied or canceled the dialog displayed for a premium + * shortcode sms or rate-limited sms. + */ + public static final int RESULT_UNEXPECTED_EVENT_STOP_SENDING = 28; + + /** + * Failed sending during an emergency call + */ + public static final int RESULT_SMS_BLOCKED_DURING_EMERGENCY = 29; + + /** + * Failed to send an sms retry + */ + public static final int RESULT_SMS_SEND_RETRY_FAILED = 30; + + /** + * Set by BroadcastReceiver to indicate a remote exception while handling a message. + */ + public static final int RESULT_REMOTE_EXCEPTION = 31; + + /** + * Set by BroadcastReceiver to indicate there's no default sms app. + */ + public static final int RESULT_NO_DEFAULT_SMS_APP = 32; + + // Radio Error results + + /** + * The radio did not start or is resetting. + */ + public static final int RESULT_RIL_RADIO_NOT_AVAILABLE = 100; + + /** + * The radio failed to send the sms and needs to retry. + */ + public static final int RESULT_RIL_SMS_SEND_FAIL_RETRY = 101; + + /** + * The sms request was rejected by the network. + */ + public static final int RESULT_RIL_NETWORK_REJECT = 102; + + /** + * The radio returned an unexpected request for the current state. + */ + public static final int RESULT_RIL_INVALID_STATE = 103; + + /** + * The radio received invalid arguments in the request. + */ + public static final int RESULT_RIL_INVALID_ARGUMENTS = 104; + + /** + * The radio didn't have sufficient memory to process the request. + */ + public static final int RESULT_RIL_NO_MEMORY = 105; + + /** + * The radio denied the operation due to overly-frequent requests. + */ + public static final int RESULT_RIL_REQUEST_RATE_LIMITED = 106; + + /** + * The radio returned an error indicating invalid sms format. + */ + public static final int RESULT_RIL_INVALID_SMS_FORMAT = 107; + + /** + * The radio encountered a platform or system error. + */ + public static final int RESULT_RIL_SYSTEM_ERR = 108; + + /** + * The SMS message was not encoded properly. + */ + public static final int RESULT_RIL_ENCODING_ERR = 109; + + /** + * The specified SMSC address was invalid. + */ + public static final int RESULT_RIL_INVALID_SMSC_ADDRESS = 110; + + /** + * The vendor RIL received an unexpected or incorrect response. + */ + public static final int RESULT_RIL_MODEM_ERR = 111; + + /** + * The radio received an error from the network. + */ + public static final int RESULT_RIL_NETWORK_ERR = 112; + + /** + * The modem encountered an unexpected error scenario while handling the request. + */ + public static final int RESULT_RIL_INTERNAL_ERR = 113; + + /** + * The request was not supported by the radio. + */ + public static final int RESULT_RIL_REQUEST_NOT_SUPPORTED = 114; + + /** + * The radio cannot process the request in the current modem state. + */ + public static final int RESULT_RIL_INVALID_MODEM_STATE = 115; + + /** + * The network is not ready to perform the request. + */ + public static final int RESULT_RIL_NETWORK_NOT_READY = 116; + + /** + * The radio reports the request is not allowed. + */ + public static final int RESULT_RIL_OPERATION_NOT_ALLOWED = 117; + + /** + * There are not sufficient resources to process the request. + */ + public static final int RESULT_RIL_NO_RESOURCES = 118; + + /** + * The request has been cancelled. + */ + public static final int RESULT_RIL_CANCELLED = 119; + + /** + * The radio failed to set the location where the CDMA subscription + * can be retrieved because the SIM or RUIM is absent. + */ + public static final int RESULT_RIL_SIM_ABSENT = 120; /** * Send an MMS message @@ -2203,17 +2339,8 @@ public final class SmsManager { if (contentUri == null) { throw new IllegalArgumentException("Uri contentUri null"); } - try { - final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms == null) { - return; - } - - iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri, + MmsManager.getInstance().sendMultimediaMessage(getSubscriptionId(), contentUri, locationUrl, configOverrides, sentIntent); - } catch (RemoteException e) { - // Ignore it - } } /** @@ -2246,16 +2373,8 @@ public final class SmsManager { if (contentUri == null) { throw new IllegalArgumentException("Uri contentUri null"); } - try { - final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms == null) { - return; - } - iMms.downloadMessage(getSubscriptionId(), ActivityThread.currentPackageName(), - locationUrl, contentUri, configOverrides, downloadedIntent); - } catch (RemoteException e) { - // Ignore it - } + MmsManager.getInstance().downloadMultimediaMessage(getSubscriptionId(), locationUrl, + contentUri, configOverrides, downloadedIntent); } // MMS send/download failure result codes @@ -2273,434 +2392,17 @@ public final class SmsManager { /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */ public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; - /** - * Import a text message into system's SMS store - * - * Only default SMS apps can import SMS - * - * @param address the destination(source) address of the sent(received) message - * @param type the type of the message - * @param text the message text - * @param timestampMillis the message timestamp in milliseconds - * @param seen if the message is seen - * @param read if the message is read - * @return the message URI, null if failed - * @hide - */ - public Uri importTextMessage(String address, int type, String text, long timestampMillis, - boolean seen, boolean read) { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.importTextMessage(ActivityThread.currentPackageName(), - address, type, text, timestampMillis, seen, read); - } - } catch (RemoteException ex) { - // ignore it - } - return null; - } - /** Represents the received SMS message for importing {@hide} */ public static final int SMS_TYPE_INCOMING = 0; /** Represents the sent SMS message for importing {@hide} */ public static final int SMS_TYPE_OUTGOING = 1; - /** - * Import a multimedia message into system's MMS store. Only the following PDU type is - * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind - * - * Only default SMS apps can import MMS - * - * @param contentUri the content uri from which to read the PDU of the message to import - * @param messageId the optional message id. Use null if not specifying - * @param timestampSecs the optional message timestamp. Use -1 if not specifying - * @param seen if the message is seen - * @param read if the message is read - * @return the message URI, null if failed - * @throws IllegalArgumentException if pdu is empty - * {@hide} - */ - public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, - boolean seen, boolean read) { - if (contentUri == null) { - throw new IllegalArgumentException("Uri contentUri null"); - } - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), - contentUri, messageId, timestampSecs, seen, read); - } - } catch (RemoteException ex) { - // ignore it - } - return null; - } - - /** - * Delete a system stored SMS or MMS message - * - * Only default SMS apps can delete system stored SMS and MMS messages - * - * @param messageUri the URI of the stored message - * @return true if deletion is successful, false otherwise - * @throws IllegalArgumentException if messageUri is empty - * {@hide} - */ - public boolean deleteStoredMessage(Uri messageUri) { - if (messageUri == null) { - throw new IllegalArgumentException("Empty message URI"); - } - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); - } - } catch (RemoteException ex) { - // ignore it - } - return false; - } - - /** - * Delete a system stored SMS or MMS thread - * - * Only default SMS apps can delete system stored SMS and MMS conversations - * - * @param conversationId the ID of the message conversation - * @return true if deletion is successful, false otherwise - * {@hide} - */ - public boolean deleteStoredConversation(long conversationId) { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.deleteStoredConversation( - ActivityThread.currentPackageName(), conversationId); - } - } catch (RemoteException ex) { - // ignore it - } - return false; - } - - /** - * Update the status properties of a system stored SMS or MMS message, e.g. - * the read status of a message, etc. - * - * @param messageUri the URI of the stored message - * @param statusValues a list of status properties in key-value pairs to update - * @return true if update is successful, false otherwise - * @throws IllegalArgumentException if messageUri is empty - * {@hide} - */ - public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { - if (messageUri == null) { - throw new IllegalArgumentException("Empty message URI"); - } - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), - messageUri, statusValues); - } - } catch (RemoteException ex) { - // ignore it - } - return false; - } - /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ public static final String MESSAGE_STATUS_SEEN = "seen"; /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ public static final String MESSAGE_STATUS_READ = "read"; /** - * Archive or unarchive a stored conversation - * - * @param conversationId the ID of the message conversation - * @param archived true to archive the conversation, false to unarchive - * @return true if update is successful, false otherwise - * {@hide} - */ - public boolean archiveStoredConversation(long conversationId, boolean archived) { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), - conversationId, archived); - } - } catch (RemoteException ex) { - // ignore it - } - return false; - } - - /** - * Add a text message draft to system SMS store - * - * Only default SMS apps can add SMS draft - * - * @param address the destination address of message - * @param text the body of the message to send - * @return the URI of the stored draft message - * {@hide} - */ - public Uri addTextMessageDraft(String address, String text) { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); - } - } catch (RemoteException ex) { - // ignore it - } - return null; - } - - /** - * Add a multimedia message draft to system MMS store - * - * Only default SMS apps can add MMS draft - * - * @param contentUri the content uri from which to read the PDU data of the draft MMS - * @return the URI of the stored draft message - * @throws IllegalArgumentException if pdu is empty - * {@hide} - */ - public Uri addMultimediaMessageDraft(Uri contentUri) { - if (contentUri == null) { - throw new IllegalArgumentException("Uri contentUri null"); - } - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), - contentUri); - } - } catch (RemoteException ex) { - // ignore it - } - return null; - } - - /** - * Send a system stored text message. - * - * You can only send a failed text message or a draft text message. - * - * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this - * manager on a multi-SIM device, this operation may fail sending the SMS message because no - * suitable default subscription could be found. In this case, if {@code sentIntent} is - * non-null, then the {@link PendingIntent} will be sent with an error code - * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the - * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions - * where this operation may fail. - * </p> - * - * @param messageUri the URI of the stored message - * @param scAddress is the service center address or null to use the current default SMSC - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is successfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK</code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * - * @throws IllegalArgumentException if messageUri is empty - * {@hide} - */ - public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, - PendingIntent deliveryIntent) { - if (messageUri == null) { - throw new IllegalArgumentException("Empty message URI"); - } - final Context context = ActivityThread.currentApplication().getApplicationContext(); - resolveSubscriptionForOperation(new SubscriptionResolverResult() { - @Override - public void onSuccess(int subId) { - try { - ISms iSms = getISmsServiceOrThrow(); - iSms.sendStoredText(subId, ActivityThread.currentPackageName(), messageUri, - scAddress, sentIntent, deliveryIntent); - } catch (RemoteException e) { - Log.e(TAG, "sendStoredTextMessage: Couldn't send SMS - Exception: " - + e.getMessage()); - notifySmsGenericError(sentIntent); - } - } - @Override - public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntent); - } - }); - } - - /** - * Send a system stored multi-part text message. - * - * You can only send a failed text message or a draft text message. - * The provided <code>PendingIntent</code> lists should match the part number of the - * divided text of the stored message by using <code>divideMessage</code> - * - * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this - * manager on a multi-SIM device, this operation may fail sending the SMS message because no - * suitable default subscription could be found. In this case, if {@code sentIntent} is - * non-null, then the {@link PendingIntent} will be sent with an error code - * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the - * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions - * where this operation may fail. - * </p> - * - * @param messageUri the URI of the stored message - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param sentIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been sent. - * The result code will be <code>Activity.RESULT_OK</code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been delivered - * to the recipient. The raw pdu of the status report is in the - * extended data ("pdu"). - * - * @throws IllegalArgumentException if messageUri is empty - * {@hide} - */ - public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, - ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { - if (messageUri == null) { - throw new IllegalArgumentException("Empty message URI"); - } - final Context context = ActivityThread.currentApplication().getApplicationContext(); - resolveSubscriptionForOperation(new SubscriptionResolverResult() { - @Override - public void onSuccess(int subId) { - try { - ISms iSms = getISmsServiceOrThrow(); - iSms.sendStoredMultipartText(subId, ActivityThread.currentPackageName(), - messageUri, scAddress, sentIntents, deliveryIntents); - } catch (RemoteException e) { - Log.e(TAG, "sendStoredTextMessage: Couldn't send SMS - Exception: " - + e.getMessage()); - notifySmsGenericError(sentIntents); - } - } - @Override - public void onFailure() { - notifySmsErrorNoDefaultSet(context, sentIntents); - } - }); - } - - /** - * Send a system stored MMS message - * - * This is used for sending a previously sent, but failed-to-send, message or - * for sending a text message that has been stored as a draft. - * - * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the operation being completed on the subscription associated - * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the - * operation is performed on the correct subscription. - * </p> - * - * @param messageUri the URI of the stored message - * @param configOverrides the carrier-specific messaging configuration values to override for - * sending the message. - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is successfully sent, or failed - * @throws IllegalArgumentException if messageUri is empty - * {@hide} - */ - public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, - PendingIntent sentIntent) { - if (messageUri == null) { - throw new IllegalArgumentException("Empty message URI"); - } - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - iMms.sendStoredMessage( - getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, - configOverrides, sentIntent); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** - * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system - * - * When this flag is on, all SMS/MMS sent/received are stored by system automatically - * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system - * automatically - * - * This flag can only be changed by default SMS apps - * - * @param enabled Whether to enable message auto persisting - * {@hide} - */ - public void setAutoPersisting(boolean enabled) { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** - * Get the value of the flag to automatically write sent/received SMS/MMS messages into system - * - * When this flag is on, all SMS/MMS sent/received are stored by system automatically - * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system - * automatically - * - * @return the current value of the auto persist flag - * {@hide} - */ - public boolean getAutoPersisting() { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.getAutoPersisting(); - } - } catch (RemoteException ex) { - // ignore it - } - return false; - } - - /** * Get carrier-dependent configuration values. * * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier @@ -2716,15 +2418,7 @@ public final class SmsManager { * @return bundle key/values pairs of configuration values */ public Bundle getCarrierConfigValues() { - try { - IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); - if (iMms != null) { - return iMms.getCarrierConfigValues(getSubscriptionId()); - } - } catch (RemoteException ex) { - // ignore it - } - return null; + return MmsManager.getInstance().getCarrierConfigValues(getSubscriptionId()); } /** @@ -2810,38 +2504,38 @@ public final class SmsManager { } /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * The prefixes is a list of prefix {@code String} separated by this delimiter. * @hide */ public static final String REGEX_PREFIX_DELIMITER = ","; /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * The success status to be added into the intent to be sent to the calling package. * @hide */ public static final int RESULT_STATUS_SUCCESS = 0; /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * The timeout status to be added into the intent to be sent to the calling package. * @hide */ public static final int RESULT_STATUS_TIMEOUT = 1; /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * Intent extra key of the retrieved SMS message as a {@code String}. * @hide */ public static final String EXTRA_SMS_MESSAGE = "android.telephony.extra.SMS_MESSAGE"; /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * Intent extra key of SMS retriever status, which indicates whether the request for the * coming SMS message is SUCCESS or TIMEOUT * @hide */ public static final String EXTRA_STATUS = "android.telephony.extra.STATUS"; /** - * @see #createAppSpecificSmsTokenWithPackageInfo(). + * @see #createAppSpecificSmsTokenWithPackageInfo(String, PendingIntent). * [Optional] Intent extra key of the retrieved Sim card subscription Id if any. {@code int} * @hide */ @@ -2891,74 +2585,6 @@ public final class SmsManager { } } - /** - * Filters a bundle to only contain MMS config variables. - * - * This is for use with bundles returned by {@link CarrierConfigManager} which contain MMS - * config and unrelated config. It is assumed that all MMS_CONFIG_* keys are present in the - * supplied bundle. - * - * @param config a Bundle that contains MMS config variables and possibly more. - * @return a new Bundle that only contains the MMS_CONFIG_* keys defined above. - * @hide - */ - public static Bundle getMmsConfig(BaseBundle config) { - Bundle filtered = new Bundle(); - filtered.putBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID, - config.getBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID)); - filtered.putBoolean(MMS_CONFIG_MMS_ENABLED, config.getBoolean(MMS_CONFIG_MMS_ENABLED)); - filtered.putBoolean(MMS_CONFIG_GROUP_MMS_ENABLED, - config.getBoolean(MMS_CONFIG_GROUP_MMS_ENABLED)); - filtered.putBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED, - config.getBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED)); - filtered.putBoolean(MMS_CONFIG_ALIAS_ENABLED, config.getBoolean(MMS_CONFIG_ALIAS_ENABLED)); - filtered.putBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO, - config.getBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO)); - filtered.putBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED, - config.getBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED)); - filtered.putBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED, - config.getBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED)); - filtered.putBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, - config.getBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION)); - filtered.putBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES, - config.getBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES)); - filtered.putBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED, - config.getBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED)); - filtered.putBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED, - config.getBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED)); - filtered.putBoolean(MMS_CONFIG_CLOSE_CONNECTION, - config.getBoolean(MMS_CONFIG_CLOSE_CONNECTION)); - filtered.putInt(MMS_CONFIG_MAX_MESSAGE_SIZE, config.getInt(MMS_CONFIG_MAX_MESSAGE_SIZE)); - filtered.putInt(MMS_CONFIG_MAX_IMAGE_WIDTH, config.getInt(MMS_CONFIG_MAX_IMAGE_WIDTH)); - filtered.putInt(MMS_CONFIG_MAX_IMAGE_HEIGHT, config.getInt(MMS_CONFIG_MAX_IMAGE_HEIGHT)); - filtered.putInt(MMS_CONFIG_RECIPIENT_LIMIT, config.getInt(MMS_CONFIG_RECIPIENT_LIMIT)); - filtered.putInt(MMS_CONFIG_ALIAS_MIN_CHARS, config.getInt(MMS_CONFIG_ALIAS_MIN_CHARS)); - filtered.putInt(MMS_CONFIG_ALIAS_MAX_CHARS, config.getInt(MMS_CONFIG_ALIAS_MAX_CHARS)); - filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, - config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD)); - filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD, - config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD)); - filtered.putInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE, - config.getInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE)); - filtered.putInt(MMS_CONFIG_SUBJECT_MAX_LENGTH, - config.getInt(MMS_CONFIG_SUBJECT_MAX_LENGTH)); - filtered.putInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT, - config.getInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT)); - filtered.putString(MMS_CONFIG_UA_PROF_TAG_NAME, - config.getString(MMS_CONFIG_UA_PROF_TAG_NAME)); - filtered.putString(MMS_CONFIG_USER_AGENT, config.getString(MMS_CONFIG_USER_AGENT)); - filtered.putString(MMS_CONFIG_UA_PROF_URL, config.getString(MMS_CONFIG_UA_PROF_URL)); - filtered.putString(MMS_CONFIG_HTTP_PARAMS, config.getString(MMS_CONFIG_HTTP_PARAMS)); - filtered.putString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER, - config.getString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER)); - filtered.putString(MMS_CONFIG_NAI_SUFFIX, config.getString(MMS_CONFIG_NAI_SUFFIX)); - filtered.putBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS, - config.getBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS)); - filtered.putBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER, - config.getBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER)); - return filtered; - } - /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"SMS_CATEGORY_"}, @@ -3049,4 +2675,74 @@ public final class SmsManager { } return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE; } + + /** + * Gets the SMSC address from (U)SIM. + * + * <p class="note"><strong>Note:</strong> Using this method requires that your app is the + * default SMS application, or READ_PRIVILEGED_PHONE_STATE permission, or has the carrier + * privileges.</p> + * + * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation + * dialog. If this method is called on a device that has multiple active subscriptions, this + * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined + * default subscription is defined, the subscription ID associated with this method will be + * INVALID, which will result in the operation being completed on the subscription associated + * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation + * is performed on the correct subscription. + * </p> + * + * @return the SMSC address string, null if failed. + */ + @SuppressAutoDoc // for carrier privileges and default SMS application. + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @Nullable + public String getSmscAddress() { + String smsc = null; + + try { + ISms iSms = getISmsService(); + if (iSms != null) { + smsc = iSms.getSmscAddressFromIccEfForSubscriber( + getSubscriptionId(), ActivityThread.currentPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return smsc; + } + + /** + * Sets the SMSC address on (U)SIM. + * + * <p class="note"><strong>Note:</strong> Using this method requires that your app is the + * default SMS application, or has {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * permission, or has the carrier privileges.</p> + * + * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation + * dialog. If this method is called on a device that has multiple active subscriptions, this + * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined + * default subscription is defined, the subscription ID associated with this method will be + * INVALID, which will result in the operation being completed on the subscription associated + * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation + * is performed on the correct subscription. + * </p> + * + * @param smsc the SMSC address string. + * @return true for success, false otherwise. + */ + @SuppressAutoDoc // for carrier privileges and default SMS application. + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public boolean setSmscAddress(@NonNull String smsc) { + try { + ISms iSms = getISmsService(); + if (iSms != null) { + return iSms.setSmscAddressOnIccEfForSubscriber( + smsc, getSubscriptionId(), ActivityThread.currentPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return false; + } } diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index 36e81232100c..58f285851375 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -551,7 +551,6 @@ public class SubscriptionInfo implements Parcelable { * * @param context Context of the application to check. * @return whether the app is authorized to manage this subscription per its metadata. - * @throws UnsupportedOperationException if this subscription is not embedded. * @hide * @deprecated - Do not use. */ @@ -567,15 +566,11 @@ public class SubscriptionInfo implements Parcelable { * @param context Any context. * @param packageName Package name of the app to check. * @return whether the app is authorized to manage this subscription per its metadata. - * @throws UnsupportedOperationException if this subscription is not embedded. * @hide * @deprecated - Do not use. */ @Deprecated public boolean canManageSubscription(Context context, String packageName) { - if (!isEmbedded()) { - throw new UnsupportedOperationException("Not an embedded subscription"); - } List<UiccAccessRule> allAccessRules = getAllAccessRules(); if (allAccessRules == null) { return false; @@ -585,7 +580,8 @@ public class SubscriptionInfo implements Parcelable { try { packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); } catch (PackageManager.NameNotFoundException e) { - throw new IllegalArgumentException("Unknown package: " + packageName, e); + Log.d("SubscriptionInfo", "canManageSubscription: Unknown package: " + packageName, e); + return false; } for (UiccAccessRule rule : allAccessRules) { if (rule.getCarrierPrivilegeStatus(packageInfo) @@ -606,9 +602,6 @@ public class SubscriptionInfo implements Parcelable { */ @SystemApi public @Nullable List<UiccAccessRule> getAccessRules() { - if (!isEmbedded()) { - throw new UnsupportedOperationException("Not an embedded subscription"); - } if (mNativeAccessRules == null) return null; return Arrays.asList(mNativeAccessRules); } @@ -619,11 +612,10 @@ public class SubscriptionInfo implements Parcelable { * @hide */ public @Nullable List<UiccAccessRule> getAllAccessRules() { - if (!isEmbedded()) { - throw new UnsupportedOperationException("Not an embedded subscription"); - } List<UiccAccessRule> merged = new ArrayList<>(); - if (mNativeAccessRules != null) merged.addAll(getAccessRules()); + if (mNativeAccessRules != null) { + merged.addAll(getAccessRules()); + } if (mCarrierConfigAccessRules != null) { merged.addAll(Arrays.asList(mCarrierConfigAccessRules)); } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 4e93efde54f1..9d1b7a918327 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -31,6 +31,7 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.BroadcastOptions; import android.app.PendingIntent; @@ -48,21 +49,21 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.Annotation.NetworkType; import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; import android.util.DisplayMetrics; import android.util.Log; -import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISub; -import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Preconditions; @@ -157,6 +158,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc"); /** @@ -176,6 +178,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath( CONTENT_URI, "advanced_calling"); @@ -194,6 +197,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode"); /** @@ -211,6 +215,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath( CONTENT_URI, "wfc_roaming_mode"); @@ -230,6 +235,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath( CONTENT_URI, "vt_enabled"); @@ -248,6 +254,7 @@ public class SubscriptionManager { */ @NonNull @SystemApi + @TestApi public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath( CONTENT_URI, "wfc_roaming_enabled"); @@ -895,6 +902,11 @@ public class SubscriptionManager { */ public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; + /** + * Integer extra to specify SIM slot index. + */ + public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; + private final Context mContext; private volatile INetworkPolicyManager mNetworkPolicy; @@ -918,20 +930,24 @@ public class SubscriptionManager { OnSubscriptionsChangedListenerHandler(Looper looper) { super(looper); } - - @Override - public void handleMessage(Message msg) { - if (DBG) { - log("handleMessage: invoke the overriden onSubscriptionsChanged()"); - } - OnSubscriptionsChangedListener.this.onSubscriptionsChanged(); - } } - private final Handler mHandler; + /** + * Posted executor callback on the handler associated with a given looper. + * The looper can be the calling thread's looper or the looper passed from the + * constructor {@link #OnSubscriptionsChangedListener(Looper)}. + */ + private final HandlerExecutor mExecutor; + + /** + * @hide + */ + public HandlerExecutor getHandlerExecutor() { + return mExecutor; + } public OnSubscriptionsChangedListener() { - mHandler = new OnSubscriptionsChangedListenerHandler(); + mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler()); } /** @@ -940,7 +956,7 @@ public class SubscriptionManager { * @hide */ public OnSubscriptionsChangedListener(Looper looper) { - mHandler = new OnSubscriptionsChangedListenerHandler(looper); + mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper)); } /** @@ -952,18 +968,6 @@ public class SubscriptionManager { if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); } - /** - * The callback methods need to be called on the handler thread where - * this object was created. If the binder did that for us it'd be nice. - */ - IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { - @Override - public void onSubscriptionsChanged() { - if (DBG) log("callback: received, sendEmptyMessage(0) to handler"); - mHandler.sendEmptyMessage(0); - } - }; - private void log(String s) { Rlog.d(LOG_TAG, s); } @@ -1005,21 +1009,19 @@ public class SubscriptionManager { * onSubscriptionsChanged overridden. */ public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + if (listener == null) return; String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { logd("register OnSubscriptionsChangedListener pkgName=" + pkgName + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available. Where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.addOnSubscriptionsChangedListener(pkgName, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available. Where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.addOnSubscriptionsChangedListener(listener, + listener.mExecutor); } } @@ -1031,21 +1033,18 @@ public class SubscriptionManager { * @param listener that is to be unregistered. */ public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + if (listener == null) return; String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener); } } @@ -1064,7 +1063,6 @@ public class SubscriptionManager { * for #onOpportunisticSubscriptionsChanged to be invoked. */ public static class OnOpportunisticSubscriptionsChangedListener { - private Executor mExecutor; /** * Callback invoked when there is any change to any SubscriptionInfo. Typically * this method would invoke {@link #getActiveSubscriptionInfoList} @@ -1073,27 +1071,6 @@ public class SubscriptionManager { if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN"); } - private void setExecutor(Executor executor) { - mExecutor = executor; - } - - /** - * The callback methods need to be called on the handler thread where - * this object was created. If the binder did that for us it'd be nice. - */ - IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { - @Override - public void onSubscriptionsChanged() { - final long identity = Binder.clearCallingIdentity(); - try { - if (DBG) log("onOpportunisticSubscriptionsChanged callback received."); - mExecutor.execute(() -> onOpportunisticSubscriptionsChanged()); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - }; - private void log(String s) { Rlog.d(LOG_TAG, s); } @@ -1120,18 +1097,13 @@ public class SubscriptionManager { + " listener=" + listener); } - listener.setExecutor(executor); - - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available. Where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener( + listener, executor); } } @@ -1151,16 +1123,10 @@ public class SubscriptionManager { logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" + pkgForDebug + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener); } } @@ -1862,13 +1828,27 @@ public class SubscriptionManager { return subId; } - /** @hide */ - public void setDefaultVoiceSubId(int subId) { - if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId); + /** + * Sets the system's default voice subscription id. + * + * On a data-only device, this is a no-op. + * + * May throw a {@link RuntimeException} if the provided subscription id is equal to + * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} + * + * @param subscriptionId A valid subscription ID to set as the system default, or + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void setDefaultVoiceSubscriptionId(int subscriptionId) { + if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - iSub.setDefaultVoiceSubId(subId); + iSub.setDefaultVoiceSubId(subscriptionId); } } catch (RemoteException ex) { // ignore it @@ -1876,6 +1856,15 @@ public class SubscriptionManager { } /** + * Same as {@link #setDefaultVoiceSubscriptionId(int)}, but preserved for backwards + * compatibility. + * @hide + */ + public void setDefaultVoiceSubId(int subId) { + setDefaultVoiceSubscriptionId(subId); + } + + /** * Return the SubscriptionInfo for default voice subscription. * * Will return null on data only devices, or on error. @@ -2095,13 +2084,13 @@ public class SubscriptionManager { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static boolean isValidSlotIndex(int slotIndex) { - return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSupportedModemCount(); + return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getActiveModemCount(); } /** @hide */ @UnsupportedAppUsage public static boolean isValidPhoneId(int phoneId) { - return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getSupportedModemCount(); + return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getActiveModemCount(); } /** @hide */ @@ -2122,6 +2111,7 @@ public class SubscriptionManager { if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId); intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId); + intent.putExtra(EXTRA_SLOT_INDEX, phoneId); intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); } @@ -2593,7 +2583,6 @@ public class SubscriptionManager { * * @param info The subscription to check. * @return whether the app is authorized to manage this subscription per its metadata. - * @throws IllegalArgumentException if this subscription is not embedded. */ public boolean canManageSubscription(SubscriptionInfo info) { return canManageSubscription(info, mContext.getPackageName()); @@ -2609,14 +2598,10 @@ public class SubscriptionManager { * @param info The subscription to check. * @param packageName Package name of the app to check. * @return whether the app is authorized to manage this subscription per its access rules. - * @throws IllegalArgumentException if this subscription is not embedded. * @hide */ public boolean canManageSubscription(SubscriptionInfo info, String packageName) { - if (!info.isEmbedded()) { - throw new IllegalArgumentException("Not an embedded subscription"); - } - if (info.getAllAccessRules() == null) { + if (info == null || info.getAllAccessRules() == null) { return false; } PackageManager packageManager = mContext.getPackageManager(); @@ -2624,7 +2609,8 @@ public class SubscriptionManager { try { packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); } catch (PackageManager.NameNotFoundException e) { - throw new IllegalArgumentException("Unknown package: " + packageName, e); + logd("Unknown package: " + packageName); + return false; } for (UiccAccessRule rule : info.getAllAccessRules()) { if (rule.getCarrierPrivilegeStatus(packageInfo) @@ -3017,7 +3003,7 @@ public class SubscriptionManager { // to the caller. boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext) .hasCarrierPrivileges(info.getSubscriptionId()) - || (info.isEmbedded() && canManageSubscription(info)); + || canManageSubscription(info); return hasCarrierPrivilegePermission; } @@ -3195,13 +3181,14 @@ public class SubscriptionManager { } /** - * Get active data subscription id. - * See {@link PhoneStateListener#onActiveDataSubscriptionIdChanged(int)} for the details. + * Get active data subscription id. Active data subscription refers to the subscription + * currently chosen to provide cellular internet connection to the user. This may be + * different from getDefaultDataSubscriptionId(). Eg. Opportunistics data * - * @return Active data subscription id + * See {@link PhoneStateListener#onActiveDataSubscriptionIdChanged(int)} for the details. * - * //TODO: Refactor this API in b/134702460 - * @hide + * @return Active data subscription id if any is chosen, or + * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not. */ public static int getActiveDataSubscriptionId() { try { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index bec0a975108a..55212cd969f0 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -38,6 +38,7 @@ import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; import android.app.ActivityThread; import android.app.PendingIntent; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; @@ -63,8 +64,13 @@ import android.telecom.InCallService; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; +import android.telephony.Annotation.ApnType; +import android.telephony.Annotation.CallState; +import android.telephony.Annotation.DataState; +import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.RadioPowerState; +import android.telephony.Annotation.SimActivationState; import android.telephony.VisualVoicemailService.VisualVoicemailTask; -import android.telephony.data.ApnSetting; import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories; import android.telephony.ims.ImsMmTelManager; @@ -92,6 +98,7 @@ import com.android.internal.telephony.IUpdateAvailableNetworksCallback; import com.android.internal.telephony.OperatorInfo; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.SmsApplication; import com.android.internal.telephony.TelephonyProperties; import dalvik.system.VMRuntime; @@ -254,17 +261,6 @@ public class TelephonyManager { */ public static final int UNINITIALIZED_CARD_ID = -2; - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"SRVCC_STATE_"}, - value = { - SRVCC_STATE_HANDOVER_NONE, - SRVCC_STATE_HANDOVER_STARTED, - SRVCC_STATE_HANDOVER_COMPLETED, - SRVCC_STATE_HANDOVER_FAILED, - SRVCC_STATE_HANDOVER_CANCELED}) - public @interface SrvccState {} - private final Context mContext; private final int mSubId; @UnsupportedAppUsage @@ -277,6 +273,8 @@ public class TelephonyManager { * TSTS - Triple SIM Triple Standby **/ /** @hide */ + @UnsupportedAppUsage(implicitMember = + "values()[Landroid/telephony/TelephonyManager$MultiSimVariants;") public enum MultiSimVariants { @UnsupportedAppUsage DSDS, @@ -435,6 +433,25 @@ public class TelephonyManager { getActiveModemCount()); } + /** + * Gets the maximum number of SIMs that can be active, based on the device's multisim + * configuration. + * @return 1 for single-SIM, DSDS, and TSTS devices. 2 for DSDA devices. + * @hide + */ + @SystemApi + public int getMaxNumberOfSimultaneouslyActiveSims() { + switch (getMultiSimConfiguration()) { + case UNKNOWN: + case DSDS: + case TSTS: + return 1; + case DSDA: + return 2; + } + return 1; + } + /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static TelephonyManager from(Context context) { @@ -460,7 +477,7 @@ public class TelephonyManager { */ @Nullable public TelephonyManager createForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) { - int subId = getSubIdForPhoneAccountHandle(phoneAccountHandle); + int subId = getSubscriptionId(phoneAccountHandle); if (!SubscriptionManager.isValidSubscriptionId(subId)) { return null; } @@ -1616,12 +1633,11 @@ public class TelephonyManager { * Returns the software version number for the device, for example, * the IMEI/SV for GSM phones. Return null if the software version is * not available. - * - * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * <p> + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}. */ - @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + @Nullable public String getDeviceSoftwareVersion() { return getDeviceSoftwareVersion(getSlotIndex()); } @@ -1630,12 +1646,16 @@ public class TelephonyManager { * Returns the software version number for the device, for example, * the IMEI/SV for GSM phones. Return null if the software version is * not available. + * <p> + * Requires Permission: READ_PRIVILEGED_PHONE_STATE. * * @param slotIndex of which deviceID is returned + * + * @hide */ - /** {@hide} */ - @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @Nullable public String getDeviceSoftwareVersion(int slotIndex) { ITelephony telephony = getITelephony(); if (telephony == null) return null; @@ -2499,41 +2519,37 @@ public class TelephonyManager { * @return the lowercase 2 character ISO-3166 country code, or empty string if not available. */ public String getNetworkCountryIso() { - return getNetworkCountryIsoForPhone(getPhoneId()); + return getNetworkCountryIso(getPhoneId()); } /** - * Returns the ISO country code equivalent of the MCC (Mobile Country Code) of the current + * Returns the ISO-3166 country code equivalent of the MCC (Mobile Country Code) of the current * registered operator or the cell nearby, if available. * <p> + * The ISO-3166 country code is provided in lowercase 2 character format. + * <p> + * Note: In multi-sim, this returns a shared emergency network country iso from other + * subscription if the subscription used to create the TelephonyManager doesn't camp on + * a network due to some reason (e.g. pin/puk locked), or sim is absent in the corresponding + * slot. * Note: Result may be unreliable on CDMA networks (use {@link #getPhoneType()} to determine * if on a CDMA network). - * - * @param subId for which Network CountryIso is returned - * @hide - */ - @UnsupportedAppUsage - public String getNetworkCountryIso(int subId) { - return getNetworkCountryIsoForPhone(getPhoneId(subId)); - } - - /** - * Returns the ISO country code equivalent of the current registered - * operator's MCC (Mobile Country Code) of a subscription. * <p> - * Availability: Only when user is registered to a network. Result may be - * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if - * on a CDMA network). * - * @param phoneId for which Network CountryIso is returned + * @param slotIndex the SIM slot index to get network country ISO. + * + * @return the lowercase 2 character ISO-3166 country code, or empty string if not available. + * + * {@hide} */ - /** {@hide} */ - @UnsupportedAppUsage - public String getNetworkCountryIsoForPhone(int phoneId) { + @SystemApi + @TestApi + @NonNull + public String getNetworkCountryIso(int slotIndex) { try { ITelephony telephony = getITelephony(); if (telephony == null) return ""; - return telephony.getNetworkCountryIsoForPhone(phoneId); + return telephony.getNetworkCountryIsoForPhone(slotIndex); } catch (RemoteException ex) { return ""; } @@ -2592,33 +2608,6 @@ public class TelephonyManager { /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */ public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_NR; - /** @hide */ - @IntDef({ - NETWORK_TYPE_UNKNOWN, - NETWORK_TYPE_GPRS, - NETWORK_TYPE_EDGE, - NETWORK_TYPE_UMTS, - NETWORK_TYPE_CDMA, - NETWORK_TYPE_EVDO_0, - NETWORK_TYPE_EVDO_A, - NETWORK_TYPE_1xRTT, - NETWORK_TYPE_HSDPA, - NETWORK_TYPE_HSUPA, - NETWORK_TYPE_HSPA, - NETWORK_TYPE_IDEN, - NETWORK_TYPE_EVDO_B, - NETWORK_TYPE_LTE, - NETWORK_TYPE_EHRPD, - NETWORK_TYPE_HSPAP, - NETWORK_TYPE_GSM, - NETWORK_TYPE_TD_SCDMA, - NETWORK_TYPE_IWLAN, - NETWORK_TYPE_LTE_CA, - NETWORK_TYPE_NR, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface NetworkType{} - /** * Return the current data network type. * @@ -2795,6 +2784,8 @@ public class TelephonyManager { /** Class of broadly defined "4G" networks. {@hide} */ @UnsupportedAppUsage public static final int NETWORK_CLASS_4_G = 3; + /** Class of broadly defined "5G" networks. {@hide} */ + public static final int NETWORK_CLASS_5_G = 4; /** * Return general class of network type, such as "3G" or "4G". In cases @@ -2827,6 +2818,8 @@ public class TelephonyManager { case NETWORK_TYPE_IWLAN: case NETWORK_TYPE_LTE_CA: return NETWORK_CLASS_4_G; + case NETWORK_TYPE_NR: + return NETWORK_CLASS_5_G; default: return NETWORK_CLASS_UNKNOWN; } @@ -4109,6 +4102,7 @@ public class TelephonyManager { * @hide * nobody seems to call this. */ + @UnsupportedAppUsage @TestApi @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag() { @@ -4563,6 +4557,17 @@ public class TelephonyManager { } /** + * Sim activation type: voice + * @hide + */ + public static final int SIM_ACTIVATION_TYPE_VOICE = 0; + /** + * Sim activation type: data + * @hide + */ + public static final int SIM_ACTIVATION_TYPE_DATA = 1; + + /** * Initial SIM activation state, unknown. Not set by any carrier apps. * @hide */ @@ -4605,17 +4610,6 @@ public class TelephonyManager { @SystemApi public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; - /** @hide */ - @IntDef({ - SIM_ACTIVATION_STATE_UNKNOWN, - SIM_ACTIVATION_STATE_ACTIVATING, - SIM_ACTIVATION_STATE_ACTIVATED, - SIM_ACTIVATION_STATE_DEACTIVATED, - SIM_ACTIVATION_STATE_RESTRICTED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface SimActivationState{} - /** * Sets the voice activation state * @@ -5000,15 +4994,6 @@ public class TelephonyManager { */ public static final int CALL_STATE_OFFHOOK = 2; - /** @hide */ - @IntDef(prefix = { "CALL_STATE_" }, value = { - CALL_STATE_IDLE, - CALL_STATE_RINGING, - CALL_STATE_OFFHOOK - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CallState{} - /** * Returns the state of all calls on the device. * <p> @@ -5089,6 +5074,17 @@ public class TelephonyManager { */ public static final int DATA_ACTIVITY_DORMANT = 0x00000004; + /** @hide */ + @IntDef(prefix = {"DATA_"}, value = { + DATA_ACTIVITY_NONE, + DATA_ACTIVITY_IN, + DATA_ACTIVITY_OUT, + DATA_ACTIVITY_INOUT, + DATA_ACTIVITY_DORMANT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DataActivityType{} + /** * Returns a constant indicating the type of activity on a data connection * (cellular). @@ -5524,19 +5520,20 @@ public class TelephonyManager { telephony.requestCellInfoUpdate( getSubId(), new ICellInfoCallback.Stub() { + @Override public void onCellInfo(List<CellInfo> cellInfo) { Binder.withCleanCallingIdentity(() -> executor.execute(() -> callback.onCellInfo(cellInfo))); } - public void onError(int errorCode, android.os.ParcelableException detail) { + @Override + public void onError(int errorCode, String exceptionName, String message) { Binder.withCleanCallingIdentity(() -> executor.execute(() -> callback.onError( errorCode, - detail == null ? null : detail.getCause()))); + createThrowableByClassName(exceptionName, message)))); } }, getOpPackageName()); - } catch (RemoteException ex) { } } @@ -5565,22 +5562,36 @@ public class TelephonyManager { telephony.requestCellInfoUpdateWithWorkSource( getSubId(), new ICellInfoCallback.Stub() { + @Override public void onCellInfo(List<CellInfo> cellInfo) { Binder.withCleanCallingIdentity(() -> executor.execute(() -> callback.onCellInfo(cellInfo))); } - public void onError(int errorCode, android.os.ParcelableException detail) { + @Override + public void onError(int errorCode, String exceptionName, String message) { Binder.withCleanCallingIdentity(() -> executor.execute(() -> callback.onError( errorCode, - detail == null ? null : detail.getCause()))); + createThrowableByClassName(exceptionName, message)))); } }, getOpPackageName(), workSource); } catch (RemoteException ex) { } } + private static Throwable createThrowableByClassName(String className, String message) { + if (className == null) { + return null; + } + try { + Class<?> c = Class.forName(className); + return (Throwable) c.getConstructor(String.class).newInstance(message); + } catch (ReflectiveOperationException | ClassCastException e) { + } + return new RuntimeException(className + ": " + message); + } + /** * Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged * PhoneStateListener.onCellInfoChanged} will be invoked. @@ -7654,12 +7665,16 @@ public class TelephonyManager { /** * Check whether DUN APN is required for tethering. + * <p> + * Requires Permission: READ_PRIVILEGED_PHONE_STATE. * * @return {@code true} if DUN APN is required for tethering. * @hide */ - public boolean getTetherApnRequired() { - return getTetherApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId())); + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public boolean isTetherApnRequired() { + return isTetherApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId())); } /** @@ -7669,11 +7684,11 @@ public class TelephonyManager { * @return {@code true} if DUN APN is required for tethering. * @hide */ - public boolean getTetherApnRequired(int subId) { + public boolean isTetherApnRequired(int subId) { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.getTetherApnRequiredForSubscriber(subId); + return telephony.isTetherApnRequiredForSubscriber(subId); } catch (RemoteException ex) { Rlog.e(TAG, "hasMatchedTetherApnSetting RemoteException", ex); } catch (NullPointerException ex) { @@ -7927,6 +7942,7 @@ public class TelephonyManager { /** @hide */ @SystemApi + @TestApi public List<String> getCarrierPackageNamesForIntent(Intent intent) { return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId()); } @@ -8340,15 +8356,6 @@ public class TelephonyManager { return false; } - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"RADIO_POWER_"}, - value = {RADIO_POWER_OFF, - RADIO_POWER_ON, - RADIO_POWER_UNAVAILABLE, - }) - public @interface RadioPowerState {} - /** * Radio explicitly powered off (e.g, airplane mode). * @hide @@ -9313,6 +9320,21 @@ public class TelephonyManager { } /** + * Gets the default Respond Via Message application + * @param context context from the calling app + * @param updateIfNeeded update the default app if there is no valid default app configured. + * @return component name of the app and class to direct Respond Via Message intent to, or + * {@code null} if the functionality is not supported. + * @hide + */ + @SystemApi + @TestApi + public static @Nullable ComponentName getDefaultRespondViaMessageApplication( + @NonNull Context context, boolean updateIfNeeded) { + return SmsApplication.getDefaultRespondViaMessageApplication(context, updateIfNeeded); + } + + /** * Set the alphabetic name of current registered operator. * @param name the alphabetic name of current registered operator. * @hide @@ -9414,7 +9436,7 @@ public class TelephonyManager { * @hide */ @UnsupportedAppUsage - public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) { + public int getSubIdForPhoneAccount(@Nullable PhoneAccount phoneAccount) { int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID; try { ITelephony service = getITelephony(); @@ -9448,16 +9470,28 @@ public class TelephonyManager { return returnValue; } - private int getSubIdForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) { + /** + * Returns the subscription ID for the given phone account handle. + * + * @param phoneAccountHandle the phone account handle for outgoing calls + * @return subscription ID for the given phone account handle; or + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} + * if not available; or throw a SecurityException if the caller doesn't have the + * permission. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public int getSubscriptionId(@NonNull PhoneAccountHandle phoneAccountHandle) { int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID; try { - ITelecomService service = getTelecomService(); + ITelephony service = getITelephony(); if (service != null) { - retval = getSubIdForPhoneAccount(service.getPhoneAccount(phoneAccountHandle)); + retval = service.getSubIdForPhoneAccountHandle( + phoneAccountHandle, mContext.getOpPackageName()); } - } catch (RemoteException e) { + } catch (RemoteException ex) { + Log.e(TAG, "getSubscriptionId RemoteException", ex); + ex.rethrowAsRuntimeException(); } - return retval; } @@ -9470,8 +9504,29 @@ public class TelephonyManager { try { Log.d(TAG, "factoryReset: subId=" + subId); ITelephony telephony = getITelephony(); - if (telephony != null) + if (telephony != null) { telephony.factoryReset(subId); + } + } catch (RemoteException e) { + } + } + + + /** + * Resets Telephony and IMS settings back to factory defaults only for the subscription + * associated with this instance. + * @see #createForSubscriptionId(int) + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL) + public void resetSettings() { + try { + Log.d(TAG, "resetSettings: subId=" + getSubId()); + ITelephony telephony = getITelephony(); + if (telephony != null) { + telephony.factoryReset(getSubId()); + } } catch (RemoteException e) { } } @@ -10556,6 +10611,7 @@ public class TelephonyManager { * * @hide */ + @UnsupportedAppUsage @TestApi public int getCarrierIdListVersion() { try { @@ -10824,6 +10880,16 @@ public class TelephonyManager { } /** + * Broadcast intent action for Ota emergency number database installation complete. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = + "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED"; + + /** * Returns whether {@link TelephonyManager#ACTION_EMERGENCY_ASSISTANCE emergency assistance} is * available on the device. * <p> @@ -11434,6 +11500,7 @@ public class TelephonyManager { * * @hide */ + @UnsupportedAppUsage @TestApi public Pair<Integer, Integer> getRadioHalVersion() { try { @@ -11464,11 +11531,14 @@ public class TelephonyManager { * 3) APN type is whitelisted. E.g. MMS is whitelisted if * {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on. * + * @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}. * @return whether data is enabled for a apn type. * * @hide */ - public boolean isDataEnabledForApn(@ApnSetting.ApnType int apnType) { + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isDataEnabledForApn(@ApnType int apnType) { String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; try { ITelephony service = getITelephony(); @@ -11489,7 +11559,7 @@ public class TelephonyManager { * * @hide */ - public boolean isApnMetered(@ApnSetting.ApnType int apnType) { + public boolean isApnMetered(@ApnType int apnType) { try { ITelephony service = getITelephony(); if (service != null) { diff --git a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl new file mode 100644 index 000000000000..a648a0e81073 --- /dev/null +++ b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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.cdma; + +parcelable CdmaSmsCbProgramData; + diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index e65e032c0cd4..60774e7f1e7f 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -26,6 +26,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.provider.Telephony; import android.provider.Telephony.Carriers; +import android.telephony.Annotation.ApnType; +import android.telephony.Annotation.NetworkType; import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.TelephonyManager; @@ -109,23 +111,6 @@ public class ApnSetting implements Parcelable { /** APN type for MCX (Mission Critical Service) where X can be PTT/Video/Data */ public static final int TYPE_MCX = ApnTypes.MCX; - /** @hide */ - @IntDef(flag = true, prefix = { "TYPE_" }, value = { - TYPE_DEFAULT, - TYPE_MMS, - TYPE_SUPL, - TYPE_DUN, - TYPE_HIPRI, - TYPE_FOTA, - TYPE_IMS, - TYPE_CBS, - TYPE_IA, - TYPE_EMERGENCY, - TYPE_MCX - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ApnType {} - // Possible values for authentication types. /** No authentication type. */ public static final int AUTH_TYPE_NONE = 0; @@ -1430,7 +1415,7 @@ public class ApnSetting implements Parcelable { * * @hide */ - public boolean canSupportNetworkType(@TelephonyManager.NetworkType int networkType) { + public boolean canSupportNetworkType(@NetworkType int networkType) { // Do a special checking for GSM. In reality, GSM is a voice only network type and can never // be used for data. We allow it here because in some DSDS corner cases, on the non-DDS // sub, modem reports data rat unknown. In that case if voice is GSM and this APN supports @@ -1959,8 +1944,9 @@ public class ApnSetting implements Parcelable { * {@link ApnSetting} built from this builder otherwise. */ public ApnSetting build() { - if ((mApnTypeBitmask & TYPE_ALL) == 0 || TextUtils.isEmpty(mApnName) - || TextUtils.isEmpty(mEntryName)) { + if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI | + TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX)) == 0 + || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) { return null; } return new ApnSetting(this); diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 9170e88ce832..49625bbecf4f 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -24,8 +24,8 @@ import android.annotation.SystemApi; import android.net.LinkAddress; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.DataFailureCause; import android.telephony.DataFailCause; -import android.telephony.DataFailCause.FailCause; import android.telephony.data.ApnSetting.ProtocolType; import com.android.internal.annotations.VisibleForTesting; @@ -67,7 +67,7 @@ public final class DataCallResponse implements Parcelable { /** Indicates the data connection is active with physical link up. */ public static final int LINK_STATUS_ACTIVE = 2; - private final @FailCause int mCause; + private final @DataFailureCause int mCause; private final int mSuggestedRetryTime; private final int mId; private final @LinkStatus int mLinkStatus; @@ -103,7 +103,7 @@ public final class DataCallResponse implements Parcelable { * * @removed Use the {@link Builder()} instead. */ - public DataCallResponse(@FailCause int cause, int suggestedRetryTime, int id, + public DataCallResponse(@DataFailureCause int cause, int suggestedRetryTime, int id, @LinkStatus int linkStatus, @ProtocolType int protocolType, @Nullable String interfaceName, @Nullable List<LinkAddress> addresses, @@ -150,7 +150,7 @@ public final class DataCallResponse implements Parcelable { /** * @return Data call fail cause. {@link DataFailCause#NONE} indicates no error. */ - @FailCause + @DataFailureCause public int getCause() { return mCause; } /** @@ -314,7 +314,7 @@ public final class DataCallResponse implements Parcelable { * </code></pre> */ public static final class Builder { - private @FailCause int mCause; + private @DataFailureCause int mCause; private int mSuggestedRetryTime; @@ -348,7 +348,7 @@ public final class DataCallResponse implements Parcelable { * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. * @return The same instance of the builder. */ - public @NonNull Builder setCause(@FailCause int cause) { + public @NonNull Builder setCause(@DataFailureCause int cause) { mCause = cause; return this; } diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java index 0d79ec98fcbb..30c209b28a4d 100644 --- a/telephony/java/android/telephony/data/DataProfile.java +++ b/telephony/java/android/telephony/data/DataProfile.java @@ -25,8 +25,8 @@ import android.annotation.SystemApi; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.ApnType; import android.telephony.TelephonyManager.NetworkTypeBitMask; -import android.telephony.data.ApnSetting.ApnType; import android.telephony.data.ApnSetting.AuthType; import android.text.TextUtils; diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java index 0e1751d50949..e793979a61c9 100644 --- a/telephony/java/android/telephony/data/QualifiedNetworksService.java +++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java @@ -27,8 +27,8 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.telephony.AccessNetworkConstants.AccessNetworkType; +import android.telephony.Annotation.ApnType; import android.telephony.Rlog; -import android.telephony.data.ApnSetting.ApnType; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; @@ -133,7 +133,7 @@ public abstract class QualifiedNetworksService extends Service { * service. * * @param apnTypes APN types of the qualified networks. This must be a bitmask combination - * of {@link ApnSetting.ApnType}. + * of {@link ApnType}. * @param qualifiedNetworkTypes List of network types which are qualified for data * connection setup for {@link @apnType} in the preferred order. Each element in the list * is a {@link AccessNetworkType}. An empty list indicates no networks are qualified diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 0025c7acb18c..cb66a9650f2f 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -189,6 +189,29 @@ public class EuiccManager { "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED"; /** + * Intent action sent by a carrier app to launch the eSIM activation flow provided by the LPA UI + * (LUI). The carrier app must send this intent with one of the following: + * + * <p>{@link #EXTRA_USE_QR_SCANNER} not set or set to false: The LPA should try to get an + * activation code from the carrier app by binding to the carrier app service implementing + * {@link android.service.euicc.EuiccService#ACTION_BIND_CARRIER_PROVISIONING_SERVICE}. + * <p>{@link #EXTRA_USE_QR_SCANNER} set to true: The LPA should launch a QR scanner for the user + * to scan an eSIM profile QR code. + * + * <p>Upon completion, the LPA should return one of the following results to the carrier app: + * + * <p>{@code Activity.RESULT_OK}: The LPA has succeeded in downloading the new eSIM profile. + * <p>{@code Activity.RESULT_CANCELED}: The carrier app should treat this as if the user pressed + * the back button. + * <p>Anything else: The carrier app should treat this as an error. + * + * <p>LPA needs to check if caller's package name is allowed to perform this action. + **/ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_START_EUICC_ACTIVATION = + "android.telephony.euicc.action.START_EUICC_ACTIVATION"; + + /** * Result code for an operation indicating that the operation succeeded. */ public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; @@ -342,10 +365,20 @@ public class EuiccManager { * * @hide */ - // TODO: Make this a @SystemApi. + @SystemApi public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID"; + + /** + * Key for an extra set on actions {@link #ACTION_START_EUICC_ACTIVATION} providing a boolean + * value of whether to start eSIM activation with QR scanner. + * + * <p>Expected type of the extra data: boolean + **/ + public static final String EXTRA_USE_QR_SCANNER = + "android.telephony.euicc.extra.USE_QR_SCANNER"; + /** * Optional meta-data attribute for a carrier app providing an icon to use to represent the * carrier. If not provided, the app's launcher icon will be used as a fallback. @@ -830,7 +863,7 @@ public class EuiccManager { * @param callbackIntent a PendingIntent to launch when the operation completes. * * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase - * and use {@link #eraseSubscriptionsWithOptions(int, PendingIntent)} instead + * and use {@link #eraseSubscriptions(int, PendingIntent)} instead * * @hide */ @@ -862,7 +895,7 @@ public class EuiccManager { */ @SystemApi @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) - public void eraseSubscriptionsWithOptions( + public void eraseSubscriptions( @ResetOption int options, @NonNull PendingIntent callbackIntent) { if (!isEnabled()) { sendUnavailableError(callbackIntent); diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java index 79cdfef96300..9f09d7a93a82 100644 --- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java +++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public final class ImsCallForwardInfo implements Parcelable { /** diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 77ee20512d11..b0ff5dc351e2 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.os.Parcel; @@ -45,6 +46,7 @@ import java.util.List; * @hide */ @SystemApi +@TestApi public final class ImsCallProfile implements Parcelable { private static final String TAG = "ImsCallProfile"; @@ -309,6 +311,37 @@ public final class ImsCallProfile implements Parcelable { public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE; /** + * The VERSTAT for an incoming call's phone number. + */ + private @VerificationStatus int mCallerNumberVerificationStatus; + + /** + * Indicates that the network could not perform verification. + */ + public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; + + /** + * Indicates that verification by the network passed. This indicates there is a high likelihood + * that the call originated from a valid source. + */ + public static final int VERIFICATION_STATUS_PASSED = 1; + + /** + * Indicates that verification by the network failed. This indicates there is a high likelihood + * that the call did not originate from a valid source. + */ + public static final int VERIFICATION_STATUS_FAILED = 2; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "VERIFICATION_STATUS_", value = { + VERIFICATION_STATUS_NOT_VERIFIED, + VERIFICATION_STATUS_PASSED, + VERIFICATION_STATUS_FAILED + }) + public @interface VerificationStatus {} + + /** * The emergency service categories, only valid if {@link #getServiceType} returns * {@link #SERVICE_TYPE_EMERGENCY} * @@ -539,6 +572,29 @@ public final class ImsCallProfile implements Parcelable { mMediaProfile = profile.mMediaProfile; } + /** + * Sets the verification status for the phone number of an incoming call as identified in + * ATIS-1000082. + * <p> + * The ImsService should parse the verstat information from the SIP INVITE headers for the call + * to determine this information. It is typically found in the P-Asserted-Identity OR From + * header fields. + * @param callerNumberVerificationStatus the new verification status. + */ + public void setCallerNumberVerificationStatus( + @VerificationStatus int callerNumberVerificationStatus) { + mCallerNumberVerificationStatus = callerNumberVerificationStatus; + } + + /** + * Gets the verification status for the phone number of an incoming call as identified in + * ATIS-1000082. + * @return the verification status. + */ + public @VerificationStatus int getCallerNumberVerificationStatus() { + return mCallerNumberVerificationStatus; + } + @NonNull @Override public String toString() { @@ -551,7 +607,8 @@ public final class ImsCallProfile implements Parcelable { + ", emergencyCallRouting=" + mEmergencyCallRouting + ", emergencyCallTesting=" + mEmergencyCallTesting + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency - + ", mRestrictCause=" + mRestrictCause + " }"; + + ", mRestrictCause=" + mRestrictCause + + ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus + " }"; } @Override @@ -572,6 +629,7 @@ public final class ImsCallProfile implements Parcelable { out.writeBoolean(mEmergencyCallTesting); out.writeBoolean(mHasKnownUserIntentEmergency); out.writeInt(mRestrictCause); + out.writeInt(mCallerNumberVerificationStatus); } private void readFromParcel(Parcel in) { @@ -585,6 +643,7 @@ public final class ImsCallProfile implements Parcelable { mEmergencyCallTesting = in.readBoolean(); mHasKnownUserIntentEmergency = in.readBoolean(); mRestrictCause = in.readInt(); + mCallerNumberVerificationStatus = in.readInt(); } public static final @android.annotation.NonNull Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() { diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java index a09844d6c0e2..e11886f2bea5 100644 --- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java +++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.RemoteException; import android.telephony.CallQuality; import android.telephony.ims.aidl.IImsCallSessionListener; @@ -36,6 +37,7 @@ import com.android.ims.internal.IImsCallSession; // TODO: APIs in here do not conform to API guidelines yet. This can be changed if // ImsCallSessionListenerConverter is also changed. @SystemApi +@TestApi public class ImsCallSessionListener { private final IImsCallSessionListener mListener; diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java index 6f062f4185f2..8d2049b97138 100644 --- a/telephony/java/android/telephony/ims/ImsConferenceState.java +++ b/telephony/java/android/telephony/ims/ImsConferenceState.java @@ -18,12 +18,14 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.telecom.Call; import android.telecom.Connection; -import android.telecom.Log; +import android.telephony.Rlog; +import android.util.Log; import java.util.HashMap; import java.util.Iterator; @@ -36,7 +38,9 @@ import java.util.Set; * @hide */ @SystemApi +@TestApi public final class ImsConferenceState implements Parcelable { + private static final String TAG = "ImsConferenceState"; /** * conference-info : user */ @@ -192,7 +196,7 @@ public final class ImsConferenceState implements Parcelable { sb.append("<"); while (iterator.hasNext()) { Entry<String, Bundle> entry = iterator.next(); - sb.append(Log.pii(entry.getKey())); + sb.append(Rlog.pii(TAG, entry.getKey())); sb.append(": "); Bundle participantData = entry.getValue(); @@ -200,7 +204,7 @@ public final class ImsConferenceState implements Parcelable { sb.append(key); sb.append("="); if (ENDPOINT.equals(key) || USER.equals(key)) { - sb.append(Log.pii(participantData.get(key))); + sb.append(Rlog.pii(TAG, participantData.get(key))); } else { sb.append(participantData.get(key)); } diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java index 6187e67a6acb..39af2e770882 100644 --- a/telephony/java/android/telephony/ims/ImsException.java +++ b/telephony/java/android/telephony/ims/ImsException.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.pm.PackageManager; import android.telephony.SubscriptionManager; import android.text.TextUtils; @@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public final class ImsException extends Exception { /** diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java index eb2ebcad2c1d..dcb9c9d5ec27 100644 --- a/telephony/java/android/telephony/ims/ImsExternalCallState.java +++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java @@ -20,10 +20,10 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; -import android.telecom.Log; import android.telephony.Rlog; import java.lang.annotation.Retention; @@ -34,6 +34,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public final class ImsExternalCallState implements Parcelable { private static final String TAG = "ImsExternalCallState"; @@ -217,8 +218,8 @@ public final class ImsExternalCallState implements Parcelable { @Override public String toString() { return "ImsExternalCallState { mCallId = " + mCallId + - ", mAddress = " + Log.pii(mAddress) + - ", mLocalAddress = " + Log.pii(mLocalAddress) + + ", mAddress = " + Rlog.pii(TAG, mAddress) + + ", mLocalAddress = " + Rlog.pii(TAG, mLocalAddress) + ", mIsPullable = " + mIsPullable + ", mCallState = " + mCallState + ", mCallType = " + mCallType + diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 2fad8479178e..5fd0af564d34 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -24,31 +24,28 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.Context; -import android.content.pm.IPackageManager; -import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.telephony.AccessNetworkConstants; +import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.ims.aidl.IImsCapabilityCallback; -import android.telephony.ims.aidl.IImsRegistrationCallback; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; -import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.ITelephony; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated @@ -62,9 +59,8 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi -public class ImsMmTelManager { - - private static final String TAG = "ImsMmTelManager"; +@TestApi +public class ImsMmTelManager implements RegistrationManager { /** * @hide @@ -97,94 +93,18 @@ public class ImsMmTelManager { * Callback class for receiving IMS network Registration callback events. * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) * @see #unregisterImsRegistrationCallback(RegistrationCallback) + * @deprecated Use {@link RegistrationManager.RegistrationCallback} instead. */ - public static class RegistrationCallback { - - private static class RegistrationBinder extends IImsRegistrationCallback.Stub { - - // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN - // and WWAN are more accurate constants. - private static final Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP = - new HashMap<Integer, Integer>() {{ - // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE - // case, since it is defined. - put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1); - put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, - AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, - AccessNetworkConstants.TRANSPORT_TYPE_WLAN); - }}; - - private final RegistrationCallback mLocalCallback; - private Executor mExecutor; - - RegistrationBinder(RegistrationCallback localCallback) { - mLocalCallback = localCallback; - } - - @Override - public void onRegistered(int imsRadioTech) { - if (mLocalCallback == null) return; - - Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> - mLocalCallback.onRegistered(getAccessType(imsRadioTech)))); - } - - @Override - public void onRegistering(int imsRadioTech) { - if (mLocalCallback == null) return; - - Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> - mLocalCallback.onRegistering(getAccessType(imsRadioTech)))); - } - - @Override - public void onDeregistered(ImsReasonInfo info) { - if (mLocalCallback == null) return; - - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onUnregistered(info))); - } - - @Override - public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { - if (mLocalCallback == null) return; - - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( - getAccessType(imsRadioTech), info))); - } - - @Override - public void onSubscriberAssociatedUriChanged(Uri[] uris) { - if (mLocalCallback == null) return; - - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> - mLocalCallback.onSubscriberAssociatedUriChanged(uris))); - } - - private void setExecutor(Executor executor) { - mExecutor = executor; - } - - private static int getAccessType(int regType) { - if (!IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) { - Log.w("ImsMmTelManager", "RegistrationBinder - invalid regType returned: " - + regType); - return -1; - } - return IMS_REG_TO_ACCESS_TYPE_MAP.get(regType); - } - } - - private final RegistrationBinder mBinder = new RegistrationBinder(this); + // Do not add to this class, add to RegistrationManager.RegistrationCallback instead. + @Deprecated + public static class RegistrationCallback extends RegistrationManager.RegistrationCallback { /** * Notifies the framework when the IMS Provider is registered to the IMS network. * * @param imsTransportType the radio access technology. */ + @Override public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { } @@ -193,6 +113,7 @@ public class ImsMmTelManager { * * @param imsTransportType the radio access technology. */ + @Override public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { } @@ -201,6 +122,7 @@ public class ImsMmTelManager { * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. */ + @Override public void onUnregistered(@Nullable ImsReasonInfo info) { } @@ -210,33 +132,11 @@ public class ImsMmTelManager { * @param imsTransportType The transport type that has failed to handover registration to. * @param info A {@link ImsReasonInfo} that identifies the reason for failure. */ + @Override public void onTechnologyChangeFailed( @AccessNetworkConstants.TransportType int imsTransportType, @Nullable ImsReasonInfo info) { } - - /** - * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when - * it changes. Per RFC3455, an associated URI is a URI that the service provider has - * allocated to a user for their own usage. A user's phone number is typically one of the - * associated URIs. - * @param uris new array of subscriber {@link Uri}s that are associated with this IMS - * subscription. - * @hide - */ - public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) { - } - - /**@hide*/ - public final IImsRegistrationCallback getBinder() { - return mBinder; - } - - /**@hide*/ - //Only exposed as public for compatibility with deprecated ImsManager APIs. - public void setExecutor(Executor executor) { - mBinder.setExecutor(executor); - } } /** @@ -311,7 +211,7 @@ public class ImsMmTelManager { } } - private int mSubId; + private final int mSubId; /** * Create an instance of {@link ImsMmTelManager} for the subscription id specified. @@ -356,7 +256,10 @@ public class ImsMmTelManager { * the {@link ImsService} associated with the subscription is not available. This can happen if * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed * reason. + * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor, + * RegistrationManager.RegistrationCallback)} instead. */ + @Deprecated @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, @NonNull RegistrationCallback c) throws ImsException { @@ -366,10 +269,6 @@ public class ImsMmTelManager { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } - if (!isImsAvailableOnDevice()) { - throw new ImsException("IMS not available on device.", - ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); - } c.setExecutor(executor); try { getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder()); @@ -378,13 +277,34 @@ public class ImsMmTelManager { // Rethrow as runtime error to keep API compatible. throw new IllegalArgumentException(e.getMessage()); } else { - throw new RuntimeException(e.getMessage()); + throw new ImsException(e.getMessage(), e.errorCode); } } catch (RemoteException | IllegalStateException e) { throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } } + /**{@inheritDoc}*/ + @Override + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull RegistrationManager.RegistrationCallback c) throws ImsException { + if (c == null) { + throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + c.setExecutor(executor); + try { + getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder()); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); + } catch (RemoteException | IllegalStateException e) { + throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + /** * Removes an existing {@link RegistrationCallback}. * @@ -395,7 +315,10 @@ public class ImsMmTelManager { * @param c The {@link RegistrationCallback} to be removed. * @see SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) + * @deprecated Use {@link #unregisterImsRegistrationCallback( + * RegistrationManager.RegistrationCallback)}. */ + @Deprecated @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { if (c == null) { @@ -408,6 +331,69 @@ public class ImsMmTelManager { } } + /**{@inheritDoc}*/ + @Override + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void unregisterImsRegistrationCallback( + @NonNull RegistrationManager.RegistrationCallback c) { + if (c == null) { + throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); + } + try { + getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /**{@inheritDoc}*/ + @Override + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, + @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) { + if (stateCallback == null) { + throw new IllegalArgumentException("Must include a non-null callback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + try { + getITelephony().getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> stateCallback.accept(result)); + } + }); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /**{@inheritDoc}*/ + @Override + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, + @NonNull @AccessNetworkConstants.TransportType + Consumer<Integer> transportTypeCallback) { + if (transportTypeCallback == null) { + throw new IllegalArgumentException("Must include a non-null callback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + try { + getITelephony().getImsMmTelRegistrationTransportType(mSubId, + new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> transportTypeCallback.accept(result)); + } + }); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + /** * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service * availability updates for the subscription specified in @@ -416,7 +402,7 @@ public class ImsMmTelManager { * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call - * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. + * {@link #unregisterMmTelCapabilityCallback(CapabilityCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the * current capabilities. @@ -441,10 +427,6 @@ public class ImsMmTelManager { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } - if (!isImsAvailableOnDevice()) { - throw new ImsException("IMS not available on device.", - ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); - } c.setExecutor(executor); try { getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder()); @@ -453,7 +435,7 @@ public class ImsMmTelManager { // Rethrow as runtime error to keep API compatible. throw new IllegalArgumentException(e.getMessage()); } else { - throw new RuntimeException(e.getMessage()); + throw new ImsException(e.getMessage(), e.errorCode); } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -618,6 +600,46 @@ public class ImsMmTelManager { } /** + * Query whether or not the requested MmTel capability is supported by the carrier on the + * specified network transport. + * <p> + * This is a configuration option and does not change. The only time this may change is if a + * new IMS configuration is loaded when there is a + * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription. + * @param capability The capability that is being queried for support on the carrier network. + * @param transportType The transport type of the capability to check support for. + * @param executor The executor that the callback will be called with. + * @param callback A consumer containing a Boolean result specifying whether or not the + * capability is supported on this carrier network for the transport specified. + * @throws ImsException if the subscription is no longer valid or the IMS service is not + * available. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, + @AccessNetworkConstants.TransportType int transportType, + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback) throws ImsException { + if (callback == null) { + throw new IllegalArgumentException("Must include a non-null Consumer."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + try { + getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> callback.accept(result == 1)); + } + }, capability, transportType); + } catch (ServiceSpecificException sse) { + throw new ImsException(sse.getMessage(), sse.errorCode); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** * The user's setting for whether or not they have enabled the "Video Calling" setting. * * @throws IllegalArgumentException if the subscription associated with this operation is not @@ -940,7 +962,7 @@ public class ImsMmTelManager { * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - boolean isTtyOverVolteEnabled() { + public boolean isTtyOverVolteEnabled() { try { return getITelephony().isTtyOverVolteEnabled(mSubId); } catch (ServiceSpecificException e) { @@ -955,20 +977,39 @@ public class ImsMmTelManager { } } - private static boolean isImsAvailableOnDevice() { - IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); - if (pm == null) { - // For some reason package manger is not available.. This will fail internally anyways, - // so do not throw error and allow. - return true; + /** + * Get the status of the MmTel Feature registered on this subscription. + * @param executor The executor that will be used to call the callback. + * @param callback A callback containing an Integer describing the current state of the + * MmTel feature, Which will be one of the following: + * {@link ImsFeature#STATE_UNAVAILABLE}, + * {@link ImsFeature#STATE_INITIALIZING}, + * {@link ImsFeature#STATE_READY}. Will be called using the executor + * specified when the service state has been retrieved from the IMS service. + * @throws ImsException if the IMS service associated with this subscription is not available or + * the IMS service is not available. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void getFeatureState(@NonNull @CallbackExecutor Executor executor, + @NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException { + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + if (callback == null) { + throw new IllegalArgumentException("Must include a non-null Consumer."); } try { - return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0); + getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> callback.accept(result)); + } + }); + } catch (ServiceSpecificException sse) { + throw new ImsException(sse.getMessage(), sse.errorCode); } catch (RemoteException e) { - // For some reason package manger is not available.. This will fail internally anyways, - // so do not throw error and allow. + e.rethrowAsRuntimeException(); } - return true; } private static ITelephony getITelephony() { diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 3c343dd19a86..21707b0d7cfd 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -22,21 +22,28 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.content.Context; import android.os.Binder; -import android.telephony.SubscriptionManager; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.telephony.AccessNetworkConstants; import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.RcsFeature; +import android.util.Log; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * Manager for interfacing with the framework RCS services, including the User Capability Exchange * (UCE) service, as well as managing user settings. * - * Use {@link #createForSubscriptionId(Context, int)} to create an instance of this manager. + * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager. * @hide */ -public class ImsRcsManager { +public class ImsRcsManager implements RegistrationManager { + private static final String TAG = "ImsRcsManager"; /** * Receives RCS availability status updates from the ImsService. @@ -110,32 +117,83 @@ public class ImsRcsManager { private final int mSubId; private final Context mContext; + /** + * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class. + * @hide + */ + public ImsRcsManager(Context context, int subId) { + mSubId = subId; + mContext = context; + } /** - * Create an instance of ImsRcsManager for the subscription id specified. - * - * @param context The context to create this ImsRcsManager instance within. - * @param subscriptionId The ID of the subscription that this ImsRcsManager will use. - * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList() - * @throws IllegalArgumentException if the subscription is invalid. + * @return A {@link RcsUceAdapter} used for User Capability Exchange (UCE) operations for + * this subscription. * @hide */ - public static ImsRcsManager createForSubscriptionId(Context context, int subscriptionId) { - if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { - throw new IllegalArgumentException("Invalid subscription ID"); + @NonNull + public RcsUceAdapter getUceAdapter() { + return new RcsUceAdapter(mSubId); + } + + /**{@inheritDoc}*/ + @Override + public void registerImsRegistrationCallback( + @NonNull @CallbackExecutor Executor executor, + @NonNull RegistrationCallback c) + throws ImsException { + if (c == null) { + throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + c.setExecutor(executor); + throw new UnsupportedOperationException("registerImsRegistrationCallback is not" + + "supported."); + } - return new ImsRcsManager(context, subscriptionId); + /**{@inheritDoc}*/ + @Override + public void unregisterImsRegistrationCallback( + @NonNull RegistrationManager.RegistrationCallback c) { + if (c == null) { + throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); + } + throw new UnsupportedOperationException("unregisterImsRegistrationCallback is not" + + "supported."); } - /** - * Use {@link #createForSubscriptionId(Context, int)} to create an instance of this class. - */ - private ImsRcsManager(Context context, int subId) { - mContext = context; - mSubId = subId; + /**{@inheritDoc}*/ + @Override + public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, + @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) { + if (stateCallback == null) { + throw new IllegalArgumentException("Must include a non-null stateCallback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + throw new UnsupportedOperationException("getRegistrationState is not" + + "supported."); + } + + /**{@inheritDoc}*/ + @Override + public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, + @NonNull @AccessNetworkConstants.TransportType + Consumer<Integer> transportTypeCallback) { + if (transportTypeCallback == null) { + throw new IllegalArgumentException("Must include a non-null transportTypeCallback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + throw new UnsupportedOperationException("getRegistrationTransportType is not" + + "supported."); } + /** * Registers an {@link AvailabilityCallback} with the system, which will provide RCS * availability updates for the subscription specified. @@ -165,9 +223,22 @@ public class ImsRcsManager { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "Register availability callback: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + c.setExecutor(executor); - throw new UnsupportedOperationException("registerRcsAvailabilityCallback is not" - + "supported."); + try { + imsRcsController.registerRcsAvailabilityCallback(c.getBinder()); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } /** @@ -178,14 +249,31 @@ public class ImsRcsManager { * inactive subscription, it will result in a no-op. * @param c The RCS {@link AvailabilityCallback} to be removed. * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) + * @throws ImsException if the IMS service is not available when calling this method + * {@link ImsRcsController#unregisterRcsAvailabilityCallback()}. + * See {@link ImsException#getCode()} for more information on the error codes. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c) { + public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c) + throws ImsException { if (c == null) { throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); } - throw new UnsupportedOperationException("unregisterRcsAvailabilityCallback is not" - + "supported."); + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "Unregister availability callback: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + imsRcsController.unregisterRcsAvailabilityCallback(c.getBinder()); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } /** @@ -200,10 +288,27 @@ public class ImsRcsManager { * rather the subscription is capable of this service over IMS. * @see #isAvailable(int) * @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL + * @throws ImsException if the IMS service is not available when calling this method + * {@link ImsRcsController#isCapable(int, int)}. + * See {@link ImsException#getCode()} for more information on the error codes. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) { - throw new UnsupportedOperationException("isCapable is not supported."); + public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) + throws ImsException { + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "isCapable: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + return imsRcsController.isCapable(mSubId, capability); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#isCapable", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } /** @@ -217,18 +322,31 @@ public class ImsRcsManager { * false otherwise. If the capability is available, IMS is registered and the service is * currently available over IMS. * @see #isCapable(int) + * @throws ImsException if the IMS service is not available when calling this method + * {@link ImsRcsController#isAvailable(int, int)}. + * See {@link ImsException#getCode()} for more information on the error codes. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) { - throw new UnsupportedOperationException("isAvailable is not supported."); + public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) + throws ImsException { + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "isAvailable: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + return imsRcsController.isAvailable(mSubId, capability); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#isAvailable", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } - /** - * @return A new {@link RcsUceAdapter} used for User Capability Exchange (UCE) operations for - * this subscription. - */ - @NonNull - public RcsUceAdapter getUceAdapter() { - return new RcsUceAdapter(mSubId); + private IImsRcsController getIImsRcsController() { + IBinder binder = ServiceManager.getService(Context.TELEPHONY_IMS_SERVICE); + return IImsRcsController.Stub.asInterface(binder); } } diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java index 1e0d9a786acc..9f7ec2291c20 100644 --- a/telephony/java/android/telephony/ims/ImsReasonInfo.java +++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public final class ImsReasonInfo implements Parcelable { /** diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index e6777c17203a..62bc2ae44573 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -17,6 +17,7 @@ package android.telephony.ims; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Service; import android.content.Intent; import android.os.IBinder; @@ -90,6 +91,7 @@ import com.android.internal.annotations.VisibleForTesting; * @hide */ @SystemApi +@TestApi public class ImsService extends Service { private static final String LOG_TAG = "ImsService"; diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java index ec2ff6c58a40..6b728599c7d3 100644 --- a/telephony/java/android/telephony/ims/ImsSsData.java +++ b/telephony/java/android/telephony/ims/ImsSsData.java @@ -19,6 +19,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Rlog; @@ -35,6 +36,7 @@ import java.util.List; * {@hide} */ @SystemApi +@TestApi public final class ImsSsData implements Parcelable { private static final String TAG = ImsSsData.class.getCanonicalName(); diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java index be34f9db3e54..77bd98411037 100644 --- a/telephony/java/android/telephony/ims/ImsSsInfo.java +++ b/telephony/java/android/telephony/ims/ImsSsInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -37,6 +38,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public final class ImsSsInfo implements Parcelable { /**@hide*/ @@ -336,4 +338,31 @@ public final class ImsSsInfo implements Parcelable { public @ClirInterrogationStatus int getClirInterrogationStatus() { return mClirInterrogationStatus; } + + /** + * Parts of telephony still use the old {m,n} 3GPP definition, so convert to that format. + * @hide + */ + public int[] getCompatArray(@ImsSsData.ServiceType int type) { + int[] result = new int[2]; + // Convert ImsSsInfo into a form that telephony can read (as per 3GPP 27.007) + // CLIR (section 7.7) + if (type == ImsSsData.SS_CLIR) { + // Assume there will only be one ImsSsInfo. + // contains {"n","m"} parameters + result[0] = getClirOutgoingState(); + result[1] = getClirInterrogationStatus(); + return result; + } + // COLR 7.31 + if (type == ImsSsData.SS_COLR) { + result[0] = getProvisionStatus(); + } + // Facility Lock CLCK 7.4 (for call barring), CLIP 7.6, COLP 7.8, as well as any + // other result, just return the status for the "n" parameter and provisioning status for + // "m" as the default. + result[0] = getStatus(); + result[1] = getProvisionStatus(); + return result; + } } diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java index c1f059e1cc89..b7ab0a09a1cb 100644 --- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java +++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -29,6 +30,7 @@ import android.os.Parcelable; * @hide */ @SystemApi +@TestApi public final class ImsStreamMediaProfile implements Parcelable { private static final String TAG = "ImsStreamMediaProfile"; diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java index 16303685d0a3..f67f68e2e425 100644 --- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java +++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java @@ -19,6 +19,7 @@ package android.telephony.ims; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -31,6 +32,7 @@ import java.util.Arrays; * @hide */ @SystemApi +@TestApi public final class ImsSuppServiceNotification implements Parcelable { private static final String TAG = "ImsSuppServiceNotification"; diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java index d50a0f738b25..bc12404461c7 100644 --- a/telephony/java/android/telephony/ims/ImsUtListener.java +++ b/telephony/java/android/telephony/ims/ImsUtListener.java @@ -16,22 +16,55 @@ package android.telephony.ims; +import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.RemoteException; +import android.telephony.ims.stub.ImsUtImplBase; import android.util.Log; import com.android.ims.internal.IImsUtListener; /** - * Base implementation of the IMS UT listener interface, which implements stubs. - * Override these methods to implement functionality. + * Listener interface used to receive network responses back from UT supplementary service queries + * made by the framework. * @hide */ // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you // will break other implementations of ImsUt maintained by other ImsServices. @SystemApi +@TestApi public class ImsUtListener { + + /** + * The {@link Bundle} key for a Calling Line Identification Restriction (CLIR) response. The + * value will be an int[] with two values: + * int[0] contains the 'n' parameter from TS 27.007 7.7, which is the + * outgoing CLIR state. See {@link ImsSsInfo#CLIR_OUTGOING_DEFAULT}, + * {@link ImsSsInfo#CLIR_OUTGOING_INVOCATION}, and {@link ImsSsInfo#CLIR_OUTGOING_SUPPRESSION}; + * int[1] contains the 'm' parameter from TS 27.007 7.7, which is the CLIR interrogation status. + * See {@link ImsSsInfo#CLIR_STATUS_NOT_PROVISIONED}, + * {@link ImsSsInfo#CLIR_STATUS_PROVISIONED_PERMANENT}, {@link ImsSsInfo#CLIR_STATUS_UNKNOWN}, + * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_RESTRICTED}, and + * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_ALLOWED}. + * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)} + * instead. + */ + @Deprecated + public static final String BUNDLE_KEY_CLIR = "queryClir"; + + /** + * The {@link Bundle} key for a Calling Line Identification Presentation (CLIP), Connected Line + * Identification Presentation (COLP), or Connected Line Identification Restriction (COLR) + * response. The value will be an instance of {@link ImsSsInfo}, which contains the response to + * the query. + * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)} + * instead. + */ + @Deprecated + public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; + private IImsUtListener mServiceInterface; private static final String LOG_TAG = "ImsUtListener"; @@ -51,14 +84,54 @@ public class ImsUtListener { } } - public void onUtConfigurationQueried(int id, Bundle ssInfo) { + /** + * Notify the framework of a UT configuration response to a {@link ImsUtImplBase#queryClir()}, + * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or + * {@link ImsUtImplBase#queryColr()} query for the transaction ID specified. If the query fails, + * {@link #onUtConfigurationQueryFailed(int, ImsReasonInfo)} should be called. + * @param id The ID associated with this UT configuration transaction from the framework. + * @param configuration A {@link Bundle} containing the result of querying the UT configuration. + * Must contain {@link #BUNDLE_KEY_CLIR} if it is a response to + * {@link ImsUtImplBase#queryClir()} or + * {@link #BUNDLE_KEY_SSINFO} if it is a response to + * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or + * {@link ImsUtImplBase#queryColr()}. + * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)} + * instead. + */ + @Deprecated + public void onUtConfigurationQueried(int id, Bundle configuration) { try { - mServiceInterface.utConfigurationQueried(null, id, ssInfo); + mServiceInterface.utConfigurationQueried(null, id, configuration); } catch (RemoteException e) { Log.w(LOG_TAG, "utConfigurationQueried: remote exception"); } } + /** + * Notify the framework of a UT configuration response to a {@link ImsUtImplBase#queryClir()}, + * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or + * {@link ImsUtImplBase#queryColr()} query for the transaction ID specified. If the query fails, + * the framework should be notified via + * {@link #onUtConfigurationQueryFailed(int, ImsReasonInfo)}. + * @param id The ID associated with this UT configuration transaction from the framework. + * @param configuration An {@link ImsSsInfo} instance containing the configuration for the + * line identification supplementary service queried. + */ + public void onLineIdentificationSupplementaryServiceResponse(int id, + @NonNull ImsSsInfo configuration) { + try { + mServiceInterface.lineIdentificationSupplementaryServiceResponse(id, configuration); + } catch (RemoteException e) { + Log.w(LOG_TAG, "onLineIdentificationSupplementaryServicesResponse: remote exception"); + } + } + + /** + * Notify the Framework of the line identification query failure. + * @param id The ID associated with the UT query transaction. + * @param error The query failure reason. + */ public void onUtConfigurationQueryFailed(int id, ImsReasonInfo error) { try { mServiceInterface.utConfigurationQueryFailed(null, id, error); diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java index 17724018ee57..270e693c8825 100644 --- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java +++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java @@ -17,6 +17,7 @@ package android.telephony.ims; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.net.Uri; import android.os.Handler; @@ -36,6 +37,7 @@ import com.android.internal.os.SomeArgs; * @hide */ @SystemApi +@TestApi public abstract class ImsVideoCallProvider { private static final int MSG_SET_CALLBACK = 1; private static final int MSG_SET_CAMERA = 2; diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index effdf48067c3..e16085e30465 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.StringDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.WorkerThread; import android.content.Context; import android.content.pm.IPackageManager; @@ -59,6 +60,7 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi +@TestApi public class ProvisioningManager { /**@hide*/ diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index a6a7a84c2c65..b47bcb9b119b 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -23,6 +23,13 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.content.Context; import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.telephony.ims.aidl.IImsRcsController; +import android.telephony.ims.aidl.IRcsUceControllerCallback; +import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -36,6 +43,7 @@ import java.util.concurrent.Executor; * @hide */ public class RcsUceAdapter { + private static final String TAG = "RcsUceAdapter"; /** * An unknown error has caused the request to fail. @@ -188,7 +196,6 @@ public class RcsUceAdapter { /** * Not to be instantiated directly, use - * {@link ImsRcsManager#createForSubscriptionId(Context, int)} and * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class. */ RcsUceAdapter(int subId) { @@ -218,7 +225,45 @@ public class RcsUceAdapter { public void requestCapabilities(@CallbackExecutor Executor executor, @NonNull List<Uri> contactNumbers, @NonNull CapabilitiesCallback c) throws ImsException { - throw new UnsupportedOperationException("isUceSettingEnabled is not supported."); + if (c == null) { + throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + if (contactNumbers == null) { + throw new IllegalArgumentException("Must include non-null contact number list."); + } + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "requestCapabilities: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { + @Override + public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { + Binder.withCleanCallingIdentity(() -> + executor.execute(() -> + c.onCapabilitiesReceived(contactCapabilities))); + } + @Override + public void onError(int errorCode) { + Binder.withCleanCallingIdentity(() -> + executor.execute(() -> + c.onError(errorCode))); + } + }; + + try { + imsRcsController.requestCapabilities(mSubId, contactNumbers, internalCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } /** @@ -233,7 +278,20 @@ public class RcsUceAdapter { */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @PublishState int getUcePublishState() throws ImsException { - throw new UnsupportedOperationException("getPublishState is not supported."); + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "getUcePublishState: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + return imsRcsController.getUcePublishState(mSubId); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#getUcePublishState", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } /** @@ -252,9 +310,22 @@ public class RcsUceAdapter { */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isUceSettingEnabled() throws ImsException { - // TODO: add SubscriptionController column for this property. - throw new UnsupportedOperationException("isUceSettingEnabled is not supported."); + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "isUceSettingEnabled: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + return imsRcsController.isUceSettingEnabled(mSubId); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } } + /** * Change the user’s setting for whether or not UCE is enabled for the associated subscription. * @param isEnabled the user's setting for whether or not they wish for Presence and User @@ -270,7 +341,24 @@ public class RcsUceAdapter { */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean isEnabled) throws ImsException { - // TODO: add SubscriptionController column for this property. - throw new UnsupportedOperationException("setUceSettingEnabled is not supported."); + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "setUceSettingEnabled: IImsRcsController is null"); + throw new ImsException("Can not find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + try { + imsRcsController.setUceSettingEnabled(mSubId, isEnabled); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#setUceSettingEnabled", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + private IImsRcsController getIImsRcsController() { + IBinder binder = ServiceManager.getService(Context.TELEPHONY_IMS_SERVICE); + return IImsRcsController.Stub.asInterface(binder); } } diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java new file mode 100644 index 000000000000..99bb259602e5 --- /dev/null +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2019 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.ims; + +import android.Manifest; +import android.annotation.CallbackExecutor; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.net.Uri; +import android.os.Binder; +import android.telephony.AccessNetworkConstants; +import android.telephony.ims.aidl.IImsRegistrationCallback; +import android.telephony.ims.feature.ImsFeature; +import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * Manages IMS Service registration state for associated {@link ImsFeature}s. + * @hide + */ +@SystemApi +@TestApi +public interface RegistrationManager { + + /** + * @hide + */ + // Defines the underlying radio technology type that we have registered for IMS over. + @IntDef(prefix = "REGISTRATION_STATE_", + value = { + REGISTRATION_STATE_NOT_REGISTERED, + REGISTRATION_STATE_REGISTERING, + REGISTRATION_STATE_REGISTERED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ImsRegistrationState {} + + /** + * The IMS service is currently not registered to the carrier network. + */ + int REGISTRATION_STATE_NOT_REGISTERED = 0; + + /** + * The IMS service is currently in the process of registering to the carrier network. + */ + int REGISTRATION_STATE_REGISTERING = 1; + + /** + * The IMS service is currently registered to the carrier network. + */ + int REGISTRATION_STATE_REGISTERED = 2; + + + /**@hide*/ + // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN + // and WWAN are more accurate constants. + Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP = + new HashMap<Integer, Integer>() {{ + // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE + // case, since it is defined. + put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1); + put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + }}; + + /** + * Callback class for receiving IMS network Registration callback events. + * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) + * @see #unregisterImsRegistrationCallback(RegistrationCallback) + */ + class RegistrationCallback { + + private static class RegistrationBinder extends IImsRegistrationCallback.Stub { + + private final RegistrationCallback mLocalCallback; + private Executor mExecutor; + + RegistrationBinder(RegistrationCallback localCallback) { + mLocalCallback = localCallback; + } + + @Override + public void onRegistered(int imsRadioTech) { + if (mLocalCallback == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> + mLocalCallback.onRegistered(getAccessType(imsRadioTech)))); + } + + @Override + public void onRegistering(int imsRadioTech) { + if (mLocalCallback == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> + mLocalCallback.onRegistering(getAccessType(imsRadioTech)))); + } + + @Override + public void onDeregistered(ImsReasonInfo info) { + if (mLocalCallback == null) return; + + Binder.withCleanCallingIdentity(() -> + mExecutor.execute(() -> mLocalCallback.onUnregistered(info))); + } + + @Override + public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { + if (mLocalCallback == null) return; + + Binder.withCleanCallingIdentity(() -> + mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( + getAccessType(imsRadioTech), info))); + } + + @Override + public void onSubscriberAssociatedUriChanged(Uri[] uris) { + if (mLocalCallback == null) return; + + Binder.withCleanCallingIdentity(() -> + mExecutor.execute(() -> + mLocalCallback.onSubscriberAssociatedUriChanged(uris))); + } + + private void setExecutor(Executor executor) { + mExecutor = executor; + } + + private static int getAccessType(int regType) { + if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) { + Log.w("RegistrationManager", "RegistrationBinder - invalid regType returned: " + + regType); + return -1; + } + return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regType); + } + } + + private final RegistrationBinder mBinder = new RegistrationBinder(this); + + /** + * Notifies the framework when the IMS Provider is registered to the IMS network. + * + * @param imsTransportType the radio access technology. + */ + public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { + } + + /** + * Notifies the framework when the IMS Provider is trying to register the IMS network. + * + * @param imsTransportType the radio access technology. + */ + public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { + } + + /** + * Notifies the framework when the IMS Provider is deregistered from the IMS network. + * + * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. + */ + public void onUnregistered(@Nullable ImsReasonInfo info) { + } + + /** + * A failure has occurred when trying to handover registration to another technology type. + * + * @param imsTransportType The transport type that has failed to handover registration to. + * @param info A {@link ImsReasonInfo} that identifies the reason for failure. + */ + public void onTechnologyChangeFailed( + @AccessNetworkConstants.TransportType int imsTransportType, + @Nullable ImsReasonInfo info) { + } + + /** + * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when + * it changes. Per RFC3455, an associated URI is a URI that the service provider has + * allocated to a user for their own usage. A user's phone number is typically one of the + * associated URIs. + * @param uris new array of subscriber {@link Uri}s that are associated with this IMS + * subscription. + * @hide + */ + public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) { + } + + /**@hide*/ + public final IImsRegistrationCallback getBinder() { + return mBinder; + } + + /**@hide*/ + //Only exposed as public for compatibility with deprecated ImsManager APIs. + public void setExecutor(Executor executor) { + mBinder.setExecutor(executor); + } + } + + /** + * Registers a {@link RegistrationCallback} with the system. Use + * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed + * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. + * + * When the callback is registered, it will initiate the callback c to be called with the + * current registration state. + * + * @param executor The executor the callback events should be run on. + * @param c The {@link RegistrationCallback} to be added. + * @see #unregisterImsRegistrationCallback(RegistrationCallback) + * @throws ImsException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed + * reason. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull RegistrationCallback c) throws ImsException; + + /** + * Removes an existing {@link RegistrationCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. + * + * @param c The {@link RegistrationCallback} to be removed. + * @see SubscriptionManager.OnSubscriptionsChangedListener + * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c); + + /** + * Gets the registration state of the IMS service. + * @param executor The {@link Executor} that will be used to call the IMS registration state + * callback. + * @param stateCallback A callback called on the supplied {@link Executor} that will contain the + * registration state of the IMS service, which will be one of the + * following: {@link #REGISTRATION_STATE_NOT_REGISTERED}, + * {@link #REGISTRATION_STATE_REGISTERING}, or + * {@link #REGISTRATION_STATE_REGISTERED}. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + void getRegistrationState(@NonNull @CallbackExecutor Executor executor, + @NonNull @ImsRegistrationState Consumer<Integer> stateCallback); + + /** + * Gets the Transport Type associated with the current IMS registration. + * @param executor The {@link Executor} that will be used to call the transportTypeCallback. + * @param transportTypeCallback The transport type associated with the current IMS registration, + * which will be one of following: + * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}, + * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or + * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + void getRegistrationTransportType( + @NonNull @CallbackExecutor Executor executor, + @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback); +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl new file mode 100644 index 000000000000..b379bd0cd748 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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.ims.aidl; + +import android.net.Uri; +import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IRcsUceControllerCallback; + +/** + * Interface used to interact with the Telephony IMS. + * + * {@hide} + */ +interface IImsRcsController { + void registerRcsAvailabilityCallback(IImsCapabilityCallback c); + void unregisterRcsAvailabilityCallback(IImsCapabilityCallback c); + boolean isCapable(int subId, int capability); + boolean isAvailable(int subId, int capability); + + // ImsUceAdapter specific + void requestCapabilities(int subId, in List<Uri> contactNumbers, IRcsUceControllerCallback c); + int getUcePublishState(int subId); + boolean isUceSettingEnabled(int subId); + void setUceSettingEnabled(int subId, boolean isEnabled); +} diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl new file mode 100644 index 000000000000..5975930d5cfa --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 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.ims.aidl; + +import android.telephony.ims.RcsContactUceCapability; + +/** + * Provides interface for RCS UCE when receive a change. + * + * {@hide} + */ +oneway interface IRcsUceControllerCallback { + void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities); + void onError(int errorCode); +} diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java index 2750e51fc3d4..97a8517afea9 100644 --- a/telephony/java/android/telephony/ims/compat/ImsService.java +++ b/telephony/java/android/telephony/ims/compat/ImsService.java @@ -113,6 +113,10 @@ public class ImsService extends Service { } }; + @UnsupportedAppUsage + public ImsService() { + } + /** * @hide */ diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java index 40ea208e4578..3fd356a510e6 100644 --- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java +++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java @@ -16,12 +16,16 @@ package android.telephony.ims.compat.feature; +import android.annotation.UnsupportedAppUsage; import android.app.PendingIntent; import android.os.Message; import android.os.RemoteException; - -import android.annotation.UnsupportedAppUsage; import android.telephony.ims.ImsCallProfile; +import android.telephony.ims.ImsCallSession; +import android.telephony.ims.stub.ImsEcbmImplBase; +import android.telephony.ims.stub.ImsMultiEndpointImplBase; +import android.telephony.ims.stub.ImsUtImplBase; + import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsCallSessionListener; import com.android.ims.internal.IImsConfig; @@ -30,11 +34,6 @@ import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsUt; -import android.telephony.ims.ImsCallSession; -import android.telephony.ims.compat.stub.ImsCallSessionImplBase; -import android.telephony.ims.stub.ImsEcbmImplBase; -import android.telephony.ims.stub.ImsMultiEndpointImplBase; -import android.telephony.ims.stub.ImsUtImplBase; /** * Base implementation for MMTel. @@ -49,6 +48,10 @@ public class MMTelFeature extends ImsFeature { // Lock for feature synchronization private final Object mLock = new Object(); + @UnsupportedAppUsage + public MMTelFeature() { + } + private final IImsMMTelFeature mImsMMTelBinder = new IImsMMTelFeature.Stub() { @Override diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java index 38566fe6d811..d77f78ea9e88 100644 --- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java @@ -16,6 +16,7 @@ package android.telephony.ims.compat.stub; +import android.annotation.UnsupportedAppUsage; import android.os.Message; import android.os.RemoteException; import android.telephony.CallQuality; @@ -41,6 +42,10 @@ import com.android.ims.internal.IImsVideoCallProvider; public class ImsCallSessionImplBase extends IImsCallSession.Stub { + @UnsupportedAppUsage + public ImsCallSessionImplBase() { + } + @Override // convert to old implementation of listener public final void setListener(IImsCallSessionListener listener) diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java index 976c2be1a3fe..e2024742c058 100644 --- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java +++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java @@ -16,14 +16,14 @@ package android.telephony.ims.compat.stub; +import android.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.os.RemoteException; - -import android.annotation.UnsupportedAppUsage; import android.telephony.ims.ImsCallForwardInfo; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsSsData; import android.telephony.ims.ImsSsInfo; + import com.android.ims.internal.IImsUt; import com.android.ims.internal.IImsUtListener; @@ -40,6 +40,10 @@ import com.android.ims.internal.IImsUtListener; public class ImsUtListenerImplBase extends IImsUtListener.Stub { + @UnsupportedAppUsage + public ImsUtListenerImplBase() { + } + /** * Notifies the result of the supplementary service configuration udpate. */ @@ -65,6 +69,13 @@ public class ImsUtListenerImplBase extends IImsUtListener.Stub { } /** + * Notifies the result of a line identification supplementary service query. + */ + @Override + public void lineIdentificationSupplementaryServiceResponse(int id, ImsSsInfo config) { + } + + /** * Notifies the status of the call barring supplementary service. */ @Override diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 87a5094a95f3..1918bcb00733 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -18,6 +18,7 @@ package android.telephony.ims.feature; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.ims.stub.ImsRegistrationImplBase; @@ -33,6 +34,7 @@ import java.util.Set; * {@hide} */ @SystemApi +@TestApi public final class CapabilityChangeRequest implements Parcelable { /** diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 356288047e15..72390d070337 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -19,6 +19,7 @@ package android.telephony.ims.feature; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.Context; import android.os.IInterface; import android.os.RemoteCallbackList; @@ -43,6 +44,7 @@ import java.util.Map; * @hide */ @SystemApi +@TestApi public abstract class ImsFeature { private static final String LOG_TAG = "ImsFeature"; @@ -212,6 +214,7 @@ public abstract class ImsFeature { // Not Actually deprecated, but we need to remove it from the @SystemApi surface. @Deprecated @SystemApi // SystemApi only because it was leaked through type usage in a previous release. + @TestApi public static class Capabilities { /** @deprecated Use getters and accessors instead. */ // Not actually deprecated, but we need to remove it from the @SystemApi surface eventually. diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index ceb470491dc5..56c87710244c 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.Message; import android.os.RemoteException; @@ -54,6 +55,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public class MmTelFeature extends ImsFeature { private static final String LOG_TAG = "MmTelFeature"; @@ -362,6 +364,25 @@ public class MmTelFeature extends ImsFeature { @Retention(RetentionPolicy.SOURCE) public @interface ProcessCallResult {} + /** + * If the flag is present and true, it indicates that the incoming call is for USSD. + * <p> + * This is an optional boolean flag. + */ + public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; + + /** + * If this flag is present and true, this call is marked as an unknown dialing call instead + * of an incoming call. An example of such a call is a call that is originated by sending + * commands (like AT commands) directly to the modem without Android involvement or dialing + * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in + * certain situations. + * <p> + * This is an optional boolean flag. + */ + public static final String EXTRA_IS_UNKNOWN_CALL = + "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + private IImsMmTelListener mListener; /** @@ -410,6 +431,8 @@ public class MmTelFeature extends ImsFeature { /** * Notify the framework of an incoming call. * @param c The {@link ImsCallSessionImplBase} of the new incoming call. + * @param extras A bundle containing extra parameters related to the call. See + * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above. */ public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c, @NonNull Bundle extras) { diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 1feb3415b260..e96d082ca953 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; @@ -49,6 +50,7 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi +@TestApi public class RcsFeature extends ImsFeature { private static final String LOG_TAG = "RcsFeature"; diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java index da6a7a60c3b3..f4367da4a4dc 100644 --- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java @@ -17,19 +17,19 @@ package android.telephony.ims.stub; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Message; import android.os.RemoteException; -import android.telephony.ims.ImsCallSessionListener; -import android.telephony.ims.aidl.IImsCallSessionListener; - import android.telephony.ims.ImsCallProfile; +import android.telephony.ims.ImsCallSession; +import android.telephony.ims.ImsCallSessionListener; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsStreamMediaProfile; -import android.telephony.ims.ImsCallSession; -import com.android.ims.internal.IImsCallSession; -import com.android.ims.internal.IImsVideoCallProvider; import android.telephony.ims.ImsVideoCallProvider; +import android.telephony.ims.aidl.IImsCallSessionListener; +import com.android.ims.internal.IImsCallSession; +import com.android.ims.internal.IImsVideoCallProvider; /** * Base implementation of IImsCallSession, which implements stub versions of the methods available. * @@ -38,6 +38,7 @@ import android.telephony.ims.ImsVideoCallProvider; * @hide */ @SystemApi +@TestApi // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you // will break other implementations of ImsCallSession maintained by other ImsServices. public class ImsCallSessionImplBase implements AutoCloseable { diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 3e135cc9f048..4c0de7f9c1b7 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -18,6 +18,7 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.Context; import android.os.PersistableBundle; import android.os.RemoteCallbackList; @@ -48,6 +49,7 @@ import java.util.HashMap; * @hide */ @SystemApi +@TestApi public class ImsConfigImplBase { private static final String TAG = "ImsConfigImplBase"; diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java index 06c35eaec6dd..4a3a2eaf4225 100644 --- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java @@ -17,6 +17,7 @@ package android.telephony.ims.stub; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.RemoteException; import android.util.Log; @@ -33,6 +34,7 @@ import com.android.ims.internal.IImsEcbmListener; * @hide */ @SystemApi +@TestApi public class ImsEcbmImplBase { private static final String TAG = "ImsEcbmImplBase"; diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java index cd9ebbf38e35..4e7307e2fa0c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java +++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java @@ -19,6 +19,7 @@ package android.telephony.ims.stub; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.ims.feature.ImsFeature; @@ -35,6 +36,7 @@ import java.util.Set; * @hide */ @SystemApi +@TestApi public final class ImsFeatureConfiguration implements Parcelable { public static final class FeatureSlotPair { diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java index ce2d89a8d809..0ae5bba5d722 100644 --- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java @@ -17,10 +17,11 @@ package android.telephony.ims.stub; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.RemoteException; +import android.telephony.ims.ImsExternalCallState; import android.util.Log; -import android.telephony.ims.ImsExternalCallState; import com.android.ims.internal.IImsExternalCallStateListener; import com.android.ims.internal.IImsMultiEndpoint; @@ -37,6 +38,7 @@ import java.util.List; * @hide */ @SystemApi +@TestApi public class ImsMultiEndpointImplBase { private static final String TAG = "MultiEndpointImplBase"; diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index a08e0313bb5b..c0f16e5f9fbc 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -18,10 +18,12 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.net.Uri; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.RegistrationManager; import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsRegistrationCallback; import android.util.Log; @@ -37,6 +39,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public class ImsRegistrationImplBase { private static final String LOG_TAG = "ImsRegistrationImplBase"; @@ -72,9 +75,6 @@ public class ImsRegistrationImplBase { // with NOT_REGISTERED in the case where the ImsService has not updated the registration state // yet. private static final int REGISTRATION_STATE_UNKNOWN = -1; - private static final int REGISTRATION_STATE_NOT_REGISTERED = 0; - private static final int REGISTRATION_STATE_REGISTERING = 1; - private static final int REGISTRATION_STATE_REGISTERED = 2; private final IImsRegistration mBinder = new IImsRegistration.Stub() { @@ -128,7 +128,7 @@ public class ImsRegistrationImplBase { * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}. */ public final void onRegistered(@ImsRegistrationTech int imsRadioTech) { - updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERED); + updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERED); mCallbacks.broadcast((c) -> { try { c.onRegistered(imsRadioTech); @@ -146,7 +146,7 @@ public class ImsRegistrationImplBase { * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}. */ public final void onRegistering(@ImsRegistrationTech int imsRadioTech) { - updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERING); + updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERING); mCallbacks.broadcast((c) -> { try { c.onRegistering(imsRadioTech); @@ -230,7 +230,8 @@ public class ImsRegistrationImplBase { private void updateToDisconnectedState(ImsReasonInfo info) { synchronized (mLock) { - updateToState(REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED); + updateToState(REGISTRATION_TECH_NONE, + RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED); if (info != null) { mLastDisconnectCause = info; } else { @@ -264,15 +265,15 @@ public class ImsRegistrationImplBase { disconnectInfo = mLastDisconnectCause; } switch (state) { - case REGISTRATION_STATE_NOT_REGISTERED: { + case RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED: { c.onDeregistered(disconnectInfo); break; } - case REGISTRATION_STATE_REGISTERING: { + case RegistrationManager.REGISTRATION_STATE_REGISTERING: { c.onRegistering(getConnectionType()); break; } - case REGISTRATION_STATE_REGISTERED: { + case RegistrationManager.REGISTRATION_STATE_REGISTERED: { c.onRegistered(getConnectionType()); break; } diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java index 36ece958d501..ce9a73a21657 100644 --- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java @@ -19,6 +19,7 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.RemoteException; import android.telephony.SmsManager; import android.telephony.SmsMessage; @@ -37,6 +38,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi +@TestApi public class ImsSmsImplBase { private static final String LOG_TAG = "SmsImplBase"; diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java index fcd7faf73bb8..feac3c2ebfde 100644 --- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java @@ -17,6 +17,7 @@ package android.telephony.ims.stub; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.RemoteException; import android.telephony.ims.ImsUtListener; @@ -33,6 +34,7 @@ import com.android.ims.internal.IImsUtListener; // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you // will break other implementations of ImsUt maintained by other ImsServices. @SystemApi +@TestApi public class ImsUtImplBase { private IImsUt.Stub mServiceImpl = new IImsUt.Stub() { diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java index c9d440551631..e80087d8924e 100644 --- a/telephony/java/com/android/ims/ImsUtInterface.java +++ b/telephony/java/com/android/ims/ImsUtInterface.java @@ -21,6 +21,8 @@ import android.os.Message; import android.telephony.ims.ImsCallForwardInfo; import android.telephony.ims.ImsSsInfo; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * Provides APIs for the supplementary service settings using IMS (Ut interface). * It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol) @@ -121,6 +123,7 @@ public interface ImsUtInterface { * Retrieves the configuration of the call forward. * The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}. */ + @UnsupportedAppUsage public void queryCallForward(int condition, String number, Message result); /** diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl index fcb9fb1f8773..9a12ceee5212 100644 --- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl +++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl @@ -44,6 +44,7 @@ oneway interface IImsUtListener { @UnsupportedAppUsage void utConfigurationQueryFailed(in IImsUt ut, int id, in ImsReasonInfo error); + void lineIdentificationSupplementaryServiceResponse(int id, in ImsSsInfo config); /** * Notifies the status of the call barring supplementary service. */ diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index cde6db4888fa..e1113eba006f 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -17,6 +17,8 @@ package com.android.internal.telephony; import com.android.internal.util.Protocol; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * @hide */ @@ -37,20 +39,34 @@ public class DctConstants { * RETRYING or CONNECTING: CONNECTING * CONNECTED : CONNECTED or DISCONNECTING */ + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/telephony/DctConstants$State;") public enum State { + @UnsupportedAppUsage IDLE, + @UnsupportedAppUsage CONNECTING, + @UnsupportedAppUsage RETRYING, + @UnsupportedAppUsage CONNECTED, + @UnsupportedAppUsage DISCONNECTING, + @UnsupportedAppUsage FAILED, } + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/telephony/DctConstants$Activity;") public enum Activity { NONE, + @UnsupportedAppUsage DATAIN, + @UnsupportedAppUsage DATAOUT, + @UnsupportedAppUsage DATAINANDOUT, + @UnsupportedAppUsage DORMANT } diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java index a75096f2c082..79d366037f08 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java @@ -16,19 +16,17 @@ package com.android.internal.telephony; +import android.annotation.UnsupportedAppUsage; import android.content.res.Resources; +import android.os.Build; +import android.telephony.Rlog; import android.text.TextUtils; import android.util.SparseIntArray; -import android.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.telephony.Rlog; +import com.android.internal.R; import java.nio.ByteBuffer; import java.nio.charset.Charset; -import com.android.internal.telephony.SmsConstants; -import com.android.internal.R; - import java.util.ArrayList; import java.util.List; @@ -42,8 +40,6 @@ import java.util.List; public class GsmAlphabet { private static final String TAG = "GSM"; - private GsmAlphabet() { } - /** * This escapes extended characters, and when present indicates that the * following character should be looked up in the "extended" table. @@ -83,6 +79,11 @@ public class GsmAlphabet { * data. */ public static class TextEncodingDetails { + + @UnsupportedAppUsage + public TextEncodingDetails() { + } + /** *The number of SMS's required to encode the text. */ diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index 7441c26a8061..c1d700a2d190 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -586,4 +586,23 @@ interface ISms { * @param destAddress the destination address to test for possible short code */ int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso); + + /** + * Gets the SMSC address from (U)SIM. + * + * @param subId the subscription Id. + * @param callingPackage the package name of the calling app. + * @return the SMSC address string, null if failed. + */ + String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage); + + /** + * Sets the SMSC address on (U)SIM. + * + * @param smsc the SMSC address string. + * @param subId the subscription Id. + * @param callingPackage the package name of the calling app. + * @return true for success, false otherwise. + */ + boolean setSmscAddressOnIccEfForSubscriber(String smsc, int subId, String callingPackage); } diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java index aa1f94f2355a..ff816f24667e 100644 --- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java +++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java @@ -208,4 +208,15 @@ public class ISmsImplBase extends ISms.Stub { int subid, String callingApk, String destAddress, String countryIso) { throw new UnsupportedOperationException(); } + + @Override + public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setSmscAddressOnIccEfForSubscriber( + String smsc, int subId, String callingPackage) { + throw new UnsupportedOperationException(); + } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index d899a596c222..b502ee711107 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -319,6 +319,7 @@ interface ITelephony { /** * Replaced by getDataActivityForSubId. */ + @UnsupportedAppUsage(maxTargetSdk = 28) int getDataActivity(); /** @@ -336,6 +337,7 @@ interface ITelephony { /** * Replaced by getDataStateForSubId. */ + @UnsupportedAppUsage(maxTargetSdk = 28) int getDataState(); /** @@ -817,7 +819,7 @@ interface ITelephony { * @return {@code true} if DUN APN is required for tethering. * @hide */ - boolean getTetherApnRequiredForSubscriber(int subId); + boolean isTetherApnRequiredForSubscriber(int subId); /** * Enables framework IMS and triggers IMS Registration. @@ -864,6 +866,11 @@ interface ITelephony { String getImsService(int slotId, boolean isCarrierImsService); /** + * Get the MmTelFeature state attached to this subscription id. + */ + void getImsMmTelFeatureState(int subId, IIntegerConsumer callback); + + /** * Set the network selection mode to automatic. * * @param subId the id of the subscription to update. @@ -1304,6 +1311,12 @@ interface ITelephony { int getSubIdForPhoneAccount(in PhoneAccount phoneAccount); /** + * Returns the subscription ID associated with the specified PhoneAccountHandle. + */ + int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle, + String callingPackage); + + /** * Returns the PhoneAccountHandle associated with a subscription ID. */ PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId); @@ -1774,21 +1787,6 @@ interface ITelephony { boolean isInEmergencySmsMode(); /** - * Get a list of SMS apps on a user. - */ - String[] getSmsApps(int userId); - - /** - * Get the default SMS app on a given user. - */ - String getDefaultSmsApp(int userId); - - /** - * Set the default SMS app to a given package on a given user. - */ - void setDefaultSmsApp(int userId, String packageName); - - /** * Return the modem radio power state for slot index. * */ @@ -1806,6 +1804,16 @@ interface ITelephony { void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c); /** + * Get the IMS service registration state for the MmTelFeature associated with this sub id. + */ + void getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer); + + /** + * Get the transport type for the IMS service registration state. + */ + void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer); + + /** * Adds an IMS MmTel capabilities callback for the subscription specified. */ void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c); @@ -1826,6 +1834,12 @@ interface ITelephony { boolean isAvailable(int subId, int capability, int regTech); /** + * Return whether or not the MmTel capability is supported for the requested transport type. + */ + void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability, + int transportType); + + /** * Returns true if the user's setting for 4G LTE is enabled, for the subscription specified. */ boolean isAdvancedCallingSettingEnabled(int subId); diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java index d57f9afa01e9..6ff27b1152c8 100644 --- a/telephony/java/com/android/internal/telephony/IccCardConstants.java +++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java @@ -17,6 +17,8 @@ package com.android.internal.telephony; import android.telephony.TelephonyManager; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * {@hide} */ @@ -65,15 +67,26 @@ public class IccCardConstants { * * The ordinal values much match {@link TelephonyManager#SIM_STATE_UNKNOWN} ... */ + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/telephony/IccCardConstants$State;") public enum State { + @UnsupportedAppUsage UNKNOWN, /** ordinal(0) == {@See TelephonyManager#SIM_STATE_UNKNOWN} */ + @UnsupportedAppUsage ABSENT, /** ordinal(1) == {@See TelephonyManager#SIM_STATE_ABSENT} */ + @UnsupportedAppUsage PIN_REQUIRED, /** ordinal(2) == {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} */ + @UnsupportedAppUsage PUK_REQUIRED, /** ordinal(3) == {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} */ + @UnsupportedAppUsage NETWORK_LOCKED, /** ordinal(4) == {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} */ + @UnsupportedAppUsage READY, /** ordinal(5) == {@See TelephonyManager#SIM_STATE_READY} */ + @UnsupportedAppUsage NOT_READY, /** ordinal(6) == {@See TelephonyManager#SIM_STATE_NOT_READY} */ + @UnsupportedAppUsage PERM_DISABLED, /** ordinal(7) == {@See TelephonyManager#SIM_STATE_PERM_DISABLED} */ + @UnsupportedAppUsage CARD_IO_ERROR, /** ordinal(8) == {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} */ CARD_RESTRICTED,/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */ LOADED; /** ordinal(9) == {@See TelephonyManager#SIM_STATE_LOADED} */ diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index f8621c95d0b0..e4397cdf1254 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -15,6 +15,8 @@ */ package com.android.internal.telephony; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * @hide */ @@ -31,8 +33,15 @@ public class PhoneConstants { * ringing or waiting.</li> * </ul> */ + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/telephony/PhoneConstants$State;") public enum State { - IDLE, RINGING, OFFHOOK; + @UnsupportedAppUsage + IDLE, + @UnsupportedAppUsage + RINGING, + @UnsupportedAppUsage + OFFHOOK; }; /** @@ -46,8 +55,17 @@ public class PhoneConstants { * in 2G network</li> * </ul> */ + @UnsupportedAppUsage(implicitMember = + "values()[Lcom/android/internal/telephony/PhoneConstants$DataState;") public enum DataState { - CONNECTED, CONNECTING, DISCONNECTED, SUSPENDED; + @UnsupportedAppUsage + CONNECTED, + @UnsupportedAppUsage + CONNECTING, + @UnsupportedAppUsage + DISCONNECTED, + @UnsupportedAppUsage + SUSPENDED; }; public static final String STATE_KEY = "state"; @@ -69,15 +87,15 @@ public class PhoneConstants { public static final int LTE_ON_CDMA_TRUE = RILConstants.LTE_ON_CDMA_TRUE; // Number presentation type for caller id display (From internal/Connection.java) + @UnsupportedAppUsage public static final int PRESENTATION_ALLOWED = 1; // normal + @UnsupportedAppUsage public static final int PRESENTATION_RESTRICTED = 2; // block by user + @UnsupportedAppUsage public static final int PRESENTATION_UNKNOWN = 3; // no specified or unknown by network + @UnsupportedAppUsage public static final int PRESENTATION_PAYPHONE = 4; // show pay phone info - // Sim activation type - public static final int SIM_ACTIVATION_TYPE_VOICE = 0; - public static final int SIM_ACTIVATION_TYPE_DATA = 1; - public static final String PHONE_NAME_KEY = "phoneName"; public static final String DATA_NETWORK_TYPE_KEY = "networkType"; public static final String DATA_FAILURE_CAUSE_KEY = "failCause"; diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 5205973669ac..03ea9208d064 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -18,6 +18,8 @@ package com.android.internal.telephony; import android.telephony.TelephonyManager; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * {@hide} */ @@ -230,6 +232,7 @@ public interface RILConstants { /** NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA */ int NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 33; + @UnsupportedAppUsage int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0, "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF))); diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java index 49c737fc3440..2cdf2f63e02f 100644 --- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java +++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java @@ -16,27 +16,28 @@ package com.android.internal.telephony; -import android.telephony.Rlog; -import android.os.Build; -import android.util.SparseIntArray; import android.content.res.Resources; import android.content.res.XmlResourceParser; -import android.telephony.SmsManager; -import android.telephony.TelephonyManager; +import android.os.Build; +import android.telephony.Rlog; +import android.util.SparseIntArray; -import com.android.internal.util.XmlUtils; import com.android.internal.telephony.cdma.sms.UserData; +import com.android.internal.util.XmlUtils; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; +import dalvik.annotation.compat.UnsupportedAppUsage; public class Sms7BitEncodingTranslator { private static final String TAG = "Sms7BitEncodingTranslator"; + @UnsupportedAppUsage private static final boolean DBG = Build.IS_DEBUGGABLE ; private static boolean mIs7BitTranslationTableLoaded = false; private static SparseIntArray mTranslationTable = null; + @UnsupportedAppUsage private static SparseIntArray mTranslationTableCommon = null; + @UnsupportedAppUsage private static SparseIntArray mTranslationTableGSM = null; + @UnsupportedAppUsage private static SparseIntArray mTranslationTableCDMA = null; // Parser variables diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java index 9fe1718df6b6..dd77b0179487 100644 --- a/telephony/java/com/android/internal/telephony/SmsHeader.java +++ b/telephony/java/com/android/internal/telephony/SmsHeader.java @@ -16,13 +16,12 @@ package com.android.internal.telephony; -import com.android.internal.telephony.SmsConstants; +import android.annotation.UnsupportedAppUsage; + import com.android.internal.util.HexDump; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; - -import android.annotation.UnsupportedAppUsage; import java.util.ArrayList; /** @@ -74,6 +73,10 @@ public class SmsHeader { public static class PortAddrs { @UnsupportedAppUsage + public PortAddrs() { + } + + @UnsupportedAppUsage public int destPort; @UnsupportedAppUsage public int origPort; @@ -82,6 +85,10 @@ public class SmsHeader { public static class ConcatRef { @UnsupportedAppUsage + public ConcatRef() { + } + + @UnsupportedAppUsage public int refNumber; @UnsupportedAppUsage public int seqNumber; diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java index ffdc4b676f90..d29ef3560883 100644 --- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java +++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java @@ -16,23 +16,27 @@ package com.android.internal.telephony; -import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; -import com.android.internal.telephony.SmsConstants; -import com.android.internal.telephony.SmsHeader; -import java.text.BreakIterator; -import java.util.Arrays; - import android.annotation.UnsupportedAppUsage; import android.os.Build; import android.provider.Telephony; import android.telephony.SmsMessage; import android.text.Emoji; +import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; + +import java.text.BreakIterator; +import java.util.Arrays; + /** * Base class declaring the specific methods and members for SmsMessage. * {@hide} */ public abstract class SmsMessageBase { + + @UnsupportedAppUsage + public SmsMessageBase() { + } + /** {@hide} The address of the SMSC. May be null */ @UnsupportedAppUsage protected String mScAddress; diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index bf5c0a18cc96..4e42c20d28db 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import dalvik.annotation.compat.UnsupportedAppUsage; + /** * Contains a list of string constants used to get or set telephone properties * in the system. You can use {@link android.os.SystemProperties os.SystemProperties} @@ -101,6 +103,7 @@ public interface TelephonyProperties * provider of the SIM. 5 or 6 decimal digits. * Availability: SIM state must be "READY" */ + @UnsupportedAppUsage static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric"; /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 2a1642140222..b357fa43008f 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -19,17 +19,17 @@ package com.android.internal.telephony.cdma; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING; import android.content.res.Resources; -import android.os.Parcel; import android.os.SystemProperties; import android.telephony.PhoneNumberUtils; +import android.telephony.Rlog; import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; import android.telephony.cdma.CdmaSmsCbProgramData; -import android.telephony.Rlog; import android.text.TextUtils; import android.util.Log; import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; +import com.android.internal.telephony.Sms7BitEncodingTranslator; import com.android.internal.telephony.SmsAddress; import com.android.internal.telephony.SmsConstants; import com.android.internal.telephony.SmsHeader; @@ -43,7 +43,8 @@ import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.HexDump; -import com.android.internal.telephony.Sms7BitEncodingTranslator; + +import dalvik.annotation.compat.UnsupportedAppUsage; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; @@ -109,7 +110,9 @@ public class SmsMessage extends SmsMessageBase { private static final int PRIORITY_URGENT = 0x2; private static final int PRIORITY_EMERGENCY = 0x3; + @UnsupportedAppUsage private SmsEnvelope mEnvelope; + @UnsupportedAppUsage private BearerData mBearerData; /** @hide */ @@ -119,15 +122,20 @@ public class SmsMessage extends SmsMessageBase { createPdu(); } + @UnsupportedAppUsage public SmsMessage() {} public static class SubmitPdu extends SubmitPduBase { + @UnsupportedAppUsage + public SubmitPdu() { + } } /** * Create an SmsMessage from a raw PDU. * Note: In CDMA the PDU is just a byte representation of the received Sms. */ + @UnsupportedAppUsage public static SmsMessage createFromPdu(byte[] pdu) { SmsMessage msg = new SmsMessage(); @@ -153,6 +161,7 @@ public class SmsMessage extends SmsMessageBase { * * @hide */ + @UnsupportedAppUsage public static SmsMessage createFromEfRecord(int index, byte[] data) { try { SmsMessage msg = new SmsMessage(); @@ -219,6 +228,7 @@ public class SmsMessage extends SmsMessageBase { * Returns null on encode error. * @hide */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader) { return getSubmitPdu(scAddr, destAddr, message, statusReportRequested, smsHeader, -1); @@ -239,6 +249,7 @@ public class SmsMessage extends SmsMessageBase { * Returns null on encode error. * @hide */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority) { @@ -269,6 +280,7 @@ public class SmsMessage extends SmsMessageBase { * address, if applicable, and the encoded message. * Returns null on encode error. */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] data, boolean statusReportRequested) { @@ -306,6 +318,7 @@ public class SmsMessage extends SmsMessageBase { * address, if applicable, and the encoded message. * Returns null on encode error. */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String destAddr, UserData userData, boolean statusReportRequested) { return privateGetSubmitPdu(destAddr, statusReportRequested, userData); @@ -322,6 +335,7 @@ public class SmsMessage extends SmsMessageBase { * address, if applicable, and the encoded message. * Returns null on encode error. */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String destAddr, UserData userData, boolean statusReportRequested, int priority) { return privateGetSubmitPdu(destAddr, statusReportRequested, userData, priority); @@ -393,6 +407,7 @@ public class SmsMessage extends SmsMessageBase { } /** Return true iff the bearer data message type is DELIVERY_ACK. */ + @UnsupportedAppUsage @Override public boolean isStatusReportMessage() { return (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK); @@ -415,6 +430,7 @@ public class SmsMessage extends SmsMessageBase { * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg * @return TextEncodingDetails */ + @UnsupportedAppUsage public static TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly, boolean isEntireMsg) { CharSequence newMsgBody = null; @@ -437,6 +453,7 @@ public class SmsMessage extends SmsMessageBase { * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN}, * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP} */ + @UnsupportedAppUsage public int getTeleService() { return mEnvelope.teleService; } @@ -448,6 +465,7 @@ public class SmsMessage extends SmsMessageBase { * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_BROADCAST}, * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_ACKNOWLEDGE}, */ + @UnsupportedAppUsage public int getMessageType() { // NOTE: mEnvelope.messageType is not set correctly for cell broadcasts with some RILs. // Use the service category parameter to detect CMAS and other cell broadcast messages. @@ -763,6 +781,7 @@ public class SmsMessage extends SmsMessageBase { /** * Parses a SMS message from its BearerData stream. */ + @UnsupportedAppUsage public void parseSms() { // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6 // It contains only an 8-bit number with the number of messages waiting @@ -881,6 +900,20 @@ public class SmsMessage extends SmsMessageBase { } /** + * @return the bearer data byte array + */ + public byte[] getEnvelopeBearerData() { + return mEnvelope.bearerData; + } + + /** + * @return the 16-bit CDMA SCPT service category + */ + public @CdmaSmsCbProgramData.Category int getEnvelopeServiceCategory() { + return mEnvelope.serviceCategory; + } + + /** * {@inheritDoc} */ @Override @@ -900,6 +933,7 @@ public class SmsMessage extends SmsMessageBase { * binder-call, and hence should be thread-safe, it has been * synchronized. */ + @UnsupportedAppUsage public synchronized static int getNextMessageId() { // Testing and dialog with partners has indicated that // msgId==0 is (sometimes?) treated specially by lower levels. @@ -924,6 +958,7 @@ public class SmsMessage extends SmsMessageBase { * Creates BearerData and Envelope from parameters for a Submit SMS. * @return byte stream for SubmitPdu. */ + @UnsupportedAppUsage private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, UserData userData) { return privateGetSubmitPdu(destAddrStr, statusReportRequested, userData, -1); @@ -1109,6 +1144,7 @@ public class SmsMessage extends SmsMessageBase { /** This function shall be called to get the number of voicemails. * @hide */ + @UnsupportedAppUsage public int getNumOfVoicemails() { return mBearerData.numberOfMessages; } @@ -1120,6 +1156,7 @@ public class SmsMessage extends SmsMessageBase { * @return byte array uniquely identifying the message. * @hide */ + @UnsupportedAppUsage public byte[] getIncomingSmsFingerprint() { ByteArrayOutputStream output = new ByteArrayOutputStream(); diff --git a/telephony/java/com/android/internal/telephony/cdma/UserData.java b/telephony/java/com/android/internal/telephony/cdma/UserData.java index f87956098e5c..d960f05f3114 100644 --- a/telephony/java/com/android/internal/telephony/cdma/UserData.java +++ b/telephony/java/com/android/internal/telephony/cdma/UserData.java @@ -21,8 +21,14 @@ import android.util.SparseIntArray; import com.android.internal.telephony.SmsHeader; import com.android.internal.util.HexDump; +import dalvik.annotation.compat.UnsupportedAppUsage; + public class UserData { + @UnsupportedAppUsage + public UserData() { + } + /** * User data encoding types. * (See 3GPP2 C.R1001-F, v1.0, table 9.1-1) @@ -92,6 +98,7 @@ public class UserData { public static final int PRINTABLE_ASCII_MIN_INDEX = 0x20; public static final int ASCII_NL_INDEX = 0x0A; public static final int ASCII_CR_INDEX = 0x0D; + @UnsupportedAppUsage public static final SparseIntArray charToAscii = new SparseIntArray(); static { for (int i = 0; i < ASCII_MAP.length; i++) { @@ -131,12 +138,15 @@ public class UserData { /** * Contains the data header of the user data */ + @UnsupportedAppUsage public SmsHeader userDataHeader; /** * Contains the data encoding type for the SMS message */ + @UnsupportedAppUsage public int msgEncoding; + @UnsupportedAppUsage public boolean msgEncodingSet = false; public int msgType; @@ -146,13 +156,16 @@ public class UserData { */ public int paddingBits; + @UnsupportedAppUsage public int numFields; /** * Contains the user data of a SMS message * (See 3GPP2 C.S0015-B, v2, 4.5.2) */ + @UnsupportedAppUsage public byte[] payload; + @UnsupportedAppUsage public String payloadStr; @Override diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java index dab14369d79c..e9378e7ba690 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -17,10 +17,10 @@ package com.android.internal.telephony.cdma.sms; import android.content.res.Resources; +import android.telephony.Rlog; import android.telephony.SmsCbCmasInfo; import android.telephony.cdma.CdmaSmsCbProgramData; import android.telephony.cdma.CdmaSmsCbProgramResults; -import android.telephony.Rlog; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; @@ -31,6 +31,8 @@ import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; @@ -42,6 +44,10 @@ import java.util.ArrayList; public final class BearerData { private final static String LOG_TAG = "BearerData"; + @UnsupportedAppUsage + public BearerData() { + } + /** * Bearer Data Subparameter Identifiers * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1) @@ -95,6 +101,7 @@ public final class BearerData { * (Special rules apply for WAP-messages.) * (See 3GPP2 C.S0015-B, v2, 4.5.1) */ + @UnsupportedAppUsage public int messageId; /** @@ -106,7 +113,9 @@ public final class BearerData { public static final int PRIORITY_URGENT = 0x2; public static final int PRIORITY_EMERGENCY = 0x3; + @UnsupportedAppUsage public boolean priorityIndicatorSet = false; + @UnsupportedAppUsage public int priority = PRIORITY_NORMAL; /** @@ -144,6 +153,7 @@ public final class BearerData { public static final int DISPLAY_MODE_USER = 0x2; public boolean displayModeSet = false; + @UnsupportedAppUsage public int displayMode = DISPLAY_MODE_DEFAULT; /** @@ -207,6 +217,7 @@ public final class BearerData { * presence of a UDH in the structured data, any existing setting * will be overwritten. */ + @UnsupportedAppUsage public boolean hasUserDataHeader; /** @@ -214,6 +225,7 @@ public final class BearerData { * (e.g. padding bits, user data, user data header, etc) * (See 3GPP2 C.S.0015-B, v2, 4.5.2) */ + @UnsupportedAppUsage public UserData userData; /** @@ -244,6 +256,7 @@ public final class BearerData { private ZoneId mZoneId; + @UnsupportedAppUsage public TimeStamp() { mZoneId = ZoneId.systemDefault(); // 3GPP2 timestamps use the local timezone } @@ -295,6 +308,7 @@ public final class BearerData { } } + @UnsupportedAppUsage public TimeStamp msgCenterTimeStamp; public TimeStamp validityPeriodAbsolute; public TimeStamp deferredDeliveryTimeAbsolute; @@ -383,6 +397,7 @@ public final class BearerData { private static class CodingException extends Exception { + @UnsupportedAppUsage public CodingException(String s) { super(s); } @@ -476,6 +491,7 @@ public final class BearerData { outStream.skip(3); } + @UnsupportedAppUsage private static int countAsciiSeptets(CharSequence msg, boolean force) { int msgLen = msg.length(); if (force) return msgLen; @@ -518,6 +534,7 @@ public final class BearerData { return ted; } + @UnsupportedAppUsage private static byte[] encode7bitAscii(String msg, boolean force) throws CodingException { @@ -949,6 +966,7 @@ public final class BearerData { * * @return byte array of raw encoded SMS bearer data. */ + @UnsupportedAppUsage public static byte[] encode(BearerData bData) { bData.hasUserDataHeader = ((bData.userData != null) && (bData.userData.userDataHeader != null)); @@ -1200,6 +1218,7 @@ public final class BearerData { } } + @UnsupportedAppUsage private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader) throws CodingException { @@ -1845,6 +1864,7 @@ public final class BearerData { * @return the number of bits to read from the stream * @throws CodingException if the specified encoding is not supported */ + @UnsupportedAppUsage private static int getBitsForNumFields(int msgEncoding, int numFields) throws CodingException { switch (msgEncoding) { diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java index d27a75815980..b268ee82529b 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java @@ -20,9 +20,10 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.SmsAddress; -import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.util.HexDump; +import dalvik.annotation.compat.UnsupportedAppUsage; + public class CdmaSmsAddress extends SmsAddress { /** @@ -33,6 +34,7 @@ public class CdmaSmsAddress extends SmsAddress { static public final int DIGIT_MODE_4BIT_DTMF = 0x00; static public final int DIGIT_MODE_8BIT_CHAR = 0x01; + @UnsupportedAppUsage public int digitMode; /** @@ -43,6 +45,7 @@ public class CdmaSmsAddress extends SmsAddress { static public final int NUMBER_MODE_NOT_DATA_NETWORK = 0x00; static public final int NUMBER_MODE_DATA_NETWORK = 0x01; + @UnsupportedAppUsage public int numberMode; /** @@ -70,6 +73,7 @@ public class CdmaSmsAddress extends SmsAddress { * This field shall be set to the number of address digits * (See 3GPP2 C.S0015-B, v2, 3.4.3.3) */ + @UnsupportedAppUsage public int numberOfDigits; /** @@ -83,6 +87,7 @@ public class CdmaSmsAddress extends SmsAddress { //static protected final int NUMBERING_PLAN_TELEX = 0x4; //static protected final int NUMBERING_PLAN_PRIVATE = 0x9; + @UnsupportedAppUsage public int numberPlan; /** @@ -90,7 +95,7 @@ public class CdmaSmsAddress extends SmsAddress { * are stored in the parent class address and origBytes fields, * respectively. */ - + @UnsupportedAppUsage public CdmaSmsAddress(){ } @@ -194,6 +199,7 @@ public class CdmaSmsAddress extends SmsAddress { * common punctuation. For alpha addresses, the string is cleaned * up by removing whitespace. */ + @UnsupportedAppUsage public static CdmaSmsAddress parse(String address) { CdmaSmsAddress addr = new CdmaSmsAddress(); addr.address = address; diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java index 4a49fbf93af9..be1eab1d4523 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java @@ -19,7 +19,7 @@ package com.android.internal.telephony.cdma.sms; import android.telephony.cdma.CdmaSmsCbProgramData; -import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress; +import dalvik.annotation.compat.UnsupportedAppUsage; public final class SmsEnvelope { /** @@ -58,17 +58,17 @@ public final class SmsEnvelope { // CMAS alert service category assignments, see 3GPP2 C.R1001 table 9.3.3-1 public static final int SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT = - CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT; + CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT; // = 4096 public static final int SERVICE_CATEGORY_CMAS_EXTREME_THREAT = - CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT; + CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT; // = 4097 public static final int SERVICE_CATEGORY_CMAS_SEVERE_THREAT = - CdmaSmsCbProgramData.CATEGORY_CMAS_SEVERE_THREAT; + CdmaSmsCbProgramData.CATEGORY_CMAS_SEVERE_THREAT; // = 4098 public static final int SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = - CdmaSmsCbProgramData.CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY; + CdmaSmsCbProgramData.CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY; // = 4099 public static final int SERVICE_CATEGORY_CMAS_TEST_MESSAGE = - CdmaSmsCbProgramData.CATEGORY_CMAS_TEST_MESSAGE; + CdmaSmsCbProgramData.CATEGORY_CMAS_TEST_MESSAGE; // = 4100 public static final int SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE = - CdmaSmsCbProgramData.CATEGORY_CMAS_LAST_RESERVED_VALUE; + CdmaSmsCbProgramData.CATEGORY_CMAS_LAST_RESERVED_VALUE; // = 4351 /** * Provides the type of a SMS message like point to point, broadcast or acknowledge @@ -80,6 +80,7 @@ public final class SmsEnvelope { * or receiving the message. * (See 3GPP2 C.S0015-B, v2, 3.4.3.1) */ + @UnsupportedAppUsage public int teleService = TELESERVICE_NOT_SET; /** @@ -87,6 +88,7 @@ public final class SmsEnvelope { * by the SMS message. * (See 3GPP2 C.S0015-B, v2, 3.4.3.2) */ + @UnsupportedAppUsage public int serviceCategory; /** @@ -137,8 +139,10 @@ public final class SmsEnvelope { * encoded bearer data * (See 3GPP2 C.S0015-B, v2, 3.4.3.7) */ + @UnsupportedAppUsage public byte[] bearerData; + @UnsupportedAppUsage public SmsEnvelope() { // nothing to see here } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java index bd8c83e63055..19e0b2d1ba35 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java @@ -18,10 +18,13 @@ package com.android.internal.telephony.gsm; import android.telephony.PhoneNumberUtils; -import java.text.ParseException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsAddress; +import dalvik.annotation.compat.UnsupportedAppUsage; + +import java.text.ParseException; + public class GsmSmsAddress extends SmsAddress { static final int OFFSET_ADDRESS_LENGTH = 0; @@ -39,6 +42,7 @@ public class GsmSmsAddress extends SmsAddress { * @throws ParseException */ + @UnsupportedAppUsage public GsmSmsAddress(byte[] data, int offset, int length) throws ParseException { origBytes = new byte[length]; System.arraycopy(data, offset, origBytes, 0, length); @@ -136,6 +140,7 @@ public class GsmSmsAddress extends SmsAddress { * address indicating a "set" of "indicator 1" of type "voice message * waiting" */ + @UnsupportedAppUsage public boolean isCphsVoiceMessageSet() { // 0x11 means "set" "voice message waiting" "indicator 1" return isCphsVoiceMessageIndicatorAddress() @@ -148,6 +153,7 @@ public class GsmSmsAddress extends SmsAddress { * address indicating a "clear" of "indicator 1" of type "voice message * waiting" */ + @UnsupportedAppUsage public boolean isCphsVoiceMessageClear() { // 0x10 means "clear" "voice message waiting" "indicator 1" return isCphsVoiceMessageIndicatorAddress() diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java index c3d490a6d5cf..5766287d6691 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java @@ -25,17 +25,17 @@ import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; +import android.telephony.CbGeoUtils; +import android.telephony.CbGeoUtils.Circle; +import android.telephony.CbGeoUtils.Geometry; +import android.telephony.CbGeoUtils.LatLng; +import android.telephony.CbGeoUtils.Polygon; import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; import android.util.Pair; import android.util.Slog; import com.android.internal.R; -import com.android.internal.telephony.CbGeoUtils; -import com.android.internal.telephony.CbGeoUtils.Circle; -import com.android.internal.telephony.CbGeoUtils.Geometry; -import com.android.internal.telephony.CbGeoUtils.LatLng; -import com.android.internal.telephony.CbGeoUtils.Polygon; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsConstants; import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java index 465840f3bc7f..11bc5de08c66 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java @@ -21,6 +21,8 @@ import android.telephony.SmsCbEtwsInfo; import com.android.internal.telephony.SmsConstants; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.util.Arrays; import java.util.Locale; @@ -31,7 +33,7 @@ import java.util.Locale; * All relevant header information is now sent as a Parcelable * {@link android.telephony.SmsCbMessage} object in the "message" extra of the * {@link android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION} or - * {@link android.provider.Telephony.Sms.Intents#SMS_EMERGENCY_CB_RECEIVED_ACTION} intent. + * {@link android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED} intent. * The raw PDU is no longer sent to SMS CB applications. */ public class SmsCbHeader { @@ -110,6 +112,7 @@ public class SmsCbHeader { private final int mSerialNumber; /** The Message Identifier in 3GPP is the same as the Service Category in CDMA. */ + @UnsupportedAppUsage private final int mMessageIdentifier; private final int mDataCodingScheme; @@ -128,6 +131,7 @@ public class SmsCbHeader { /** CMAS warning notification info. */ private final SmsCbCmasInfo mCmasInfo; + @UnsupportedAppUsage public SmsCbHeader(byte[] pdu) throws IllegalArgumentException { if (pdu == null || pdu.length < PDU_HEADER_LENGTH) { throw new IllegalArgumentException("Illegal PDU"); @@ -225,14 +229,17 @@ public class SmsCbHeader { } } + @UnsupportedAppUsage int getGeographicalScope() { return mGeographicalScope; } + @UnsupportedAppUsage int getSerialNumber() { return mSerialNumber; } + @UnsupportedAppUsage int getServiceCategory() { return mMessageIdentifier; } @@ -245,10 +252,12 @@ public class SmsCbHeader { return mDataCodingSchemeStructedData; } + @UnsupportedAppUsage int getPageIndex() { return mPageIndex; } + @UnsupportedAppUsage int getNumberOfPages() { return mNrOfPages; } diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 17e3bacb21d3..e7b385c5444b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -16,18 +16,29 @@ package com.android.internal.telephony.gsm; +import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT; +import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT; +import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT; +import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601; +import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN; +import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES; +import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS; +import static com.android.internal.telephony.SmsConstants.MessageClass; + +import android.content.res.Resources; import android.telephony.PhoneNumberUtils; import android.telephony.Rlog; -import android.content.res.Resources; import android.text.TextUtils; import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; -import com.android.internal.telephony.uicc.IccUtils; +import com.android.internal.telephony.Sms7BitEncodingTranslator; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; -import com.android.internal.telephony.Sms7BitEncodingTranslator; +import com.android.internal.telephony.uicc.IccUtils; + +import dalvik.annotation.compat.UnsupportedAppUsage; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; @@ -35,16 +46,6 @@ import java.text.ParseException; import java.time.LocalDateTime; import java.time.ZoneOffset; -import static com.android.internal.telephony.SmsConstants.MessageClass; -import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN; -import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT; -import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT; -import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT; -import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601; -import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS; -import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES; -import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER; - /** * A Short Message Service message. * @@ -99,12 +100,20 @@ public class SmsMessage extends SmsMessageBase { private static final int INVALID_VALIDITY_PERIOD = -1; + @UnsupportedAppUsage + public SmsMessage() { + } + public static class SubmitPdu extends SubmitPduBase { + @UnsupportedAppUsage + public SubmitPdu() { + } } /** * Create an SmsMessage from a raw PDU. */ + @UnsupportedAppUsage public static SmsMessage createFromPdu(byte[] pdu) { try { SmsMessage msg = new SmsMessage(); @@ -169,6 +178,7 @@ public class SmsMessage extends SmsMessageBase { * * @hide */ + @UnsupportedAppUsage public static SmsMessage createFromEfRecord(int index, byte[] data) { try { SmsMessage msg = new SmsMessage(); @@ -259,6 +269,7 @@ public class SmsMessage extends SmsMessageBase { * Returns null on encode error. * @hide */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested, byte[] header) { @@ -281,6 +292,7 @@ public class SmsMessage extends SmsMessageBase { * Returns null on encode error. * @hide */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested, byte[] header, int encoding, @@ -304,6 +316,7 @@ public class SmsMessage extends SmsMessageBase { * Returns null on encode error. * @hide */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested, byte[] header, int encoding, @@ -444,6 +457,7 @@ public class SmsMessage extends SmsMessageBase { * @throws UnsupportedEncodingException * @throws EncodeException if String is too large to encode */ + @UnsupportedAppUsage private static byte[] encodeUCS2(String message, byte[] header) throws UnsupportedEncodingException, EncodeException { byte[] userData, textPart; @@ -478,6 +492,7 @@ public class SmsMessage extends SmsMessageBase { * address, if applicable, and the encoded message. * Returns null on encode error. */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested) { @@ -496,6 +511,7 @@ public class SmsMessage extends SmsMessageBase { * address, if applicable, and the encoded message. * Returns null on encode error. */ + @UnsupportedAppUsage public static SubmitPdu getSubmitPdu(String scAddress, String destinationAddress, String message, boolean statusReportRequested, int validityPeriod) { @@ -576,6 +592,7 @@ public class SmsMessage extends SmsMessageBase { * @param ret <code>SubmitPdu</code> containing the encoded SC * address, if applicable, and the encoded message. Returns null on encode error. */ + @UnsupportedAppUsage private static ByteArrayOutputStream getSubmitPduHead( String scAddress, String destinationAddress, byte mtiByte, boolean statusReportRequested, SubmitPdu ret) { @@ -622,12 +639,16 @@ public class SmsMessage extends SmsMessageBase { } private static class PduParser { + @UnsupportedAppUsage byte mPdu[]; + @UnsupportedAppUsage int mCur; SmsHeader mUserDataHeader; byte[] mUserData; + @UnsupportedAppUsage int mUserDataSeptetPadding; + @UnsupportedAppUsage PduParser(byte[] pdu) { mPdu = pdu; mCur = 0; @@ -667,6 +688,7 @@ public class SmsMessage extends SmsMessageBase { /** * returns non-sign-extended byte value */ + @UnsupportedAppUsage int getByte() { return mPdu[mCur++] & 0xff; } @@ -808,6 +830,7 @@ public class SmsMessage extends SmsMessageBase { * * @return the user data payload, not including the headers */ + @UnsupportedAppUsage byte[] getUserData() { return mUserData; } @@ -864,6 +887,7 @@ public class SmsMessage extends SmsMessageBase { * @param byteCount the number of bytes in the user data payload * @return a String with the decoded characters */ + @UnsupportedAppUsage String getUserDataUCS2(int byteCount) { String ret; @@ -912,6 +936,7 @@ public class SmsMessage extends SmsMessageBase { * @param use7bitOnly ignore (but still count) illegal characters if true * @return TextEncodingDetails */ + @UnsupportedAppUsage public static TextEncodingDetails calculateLength(CharSequence msgBody, boolean use7bitOnly) { CharSequence newMsgBody = null; @@ -959,6 +984,7 @@ public class SmsMessage extends SmsMessageBase { } /** {@inheritDoc} */ + @UnsupportedAppUsage @Override public boolean isMWIClearMessage() { if (mIsMwi && !mMwiSense) { @@ -970,6 +996,7 @@ public class SmsMessage extends SmsMessageBase { } /** {@inheritDoc} */ + @UnsupportedAppUsage @Override public boolean isMWISetMessage() { if (mIsMwi && mMwiSense) { @@ -981,6 +1008,7 @@ public class SmsMessage extends SmsMessageBase { } /** {@inheritDoc} */ + @UnsupportedAppUsage @Override public boolean isMwiDontStore() { if (mIsMwi && mMwiDontStore) { @@ -1000,12 +1028,14 @@ public class SmsMessage extends SmsMessageBase { } /** {@inheritDoc} */ + @UnsupportedAppUsage @Override public int getStatus() { return mStatus; } /** {@inheritDoc} */ + @UnsupportedAppUsage @Override public boolean isStatusReportMessage() { return mIsStatusReportMessage; diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java index 96e215cf6f45..f2d46244d60e 100644 --- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java @@ -25,6 +25,8 @@ import android.telephony.Rlog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.GsmAlphabet; +import dalvik.annotation.compat.UnsupportedAppUsage; + import java.io.UnsupportedEncodingException; import java.util.List; @@ -53,6 +55,7 @@ public class IccUtils { * * Stops on invalid BCD value, returning string so far */ + @UnsupportedAppUsage public static String bcdToString(byte[] data, int offset, int length) { StringBuilder ret = new StringBuilder(length*2); @@ -180,6 +183,7 @@ public class IccUtils { /** * Decode cdma byte into String. */ + @UnsupportedAppUsage public static String cdmaBcdToString(byte[] data, int offset, int length) { StringBuilder ret = new StringBuilder(length); @@ -215,6 +219,7 @@ public class IccUtils { * assume the digit is set to 0 but shall store the entire field * exactly as received" */ + @UnsupportedAppUsage public static int gsmBcdByteToInt(byte b) { int ret = 0; @@ -237,6 +242,7 @@ public class IccUtils { * is in the least significant nibble and the most significant * is in the most significant nibble. */ + @UnsupportedAppUsage public static int cdmaBcdByteToInt(byte b) { int ret = 0; @@ -288,6 +294,7 @@ public class IccUtils { * contain a 16 bit number which defines the complete 16 bit * base pointer to a "half page" in the UCS2 code space... */ + @UnsupportedAppUsage public static String adnStringFieldToString(byte[] data, int offset, int length) { if (length == 0) { @@ -379,6 +386,7 @@ public class IccUtils { return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim()); } + @UnsupportedAppUsage public static int hexCharToInt(char c) { if (c >= '0' && c <= '9') return (c - '0'); @@ -398,6 +406,7 @@ public class IccUtils { * * @throws RuntimeException on invalid format */ + @UnsupportedAppUsage public static byte[] hexStringToBytes(String s) { byte[] ret; @@ -424,6 +433,7 @@ public class IccUtils { * * @return hex string representation of bytes array */ + @UnsupportedAppUsage public static String bytesToHexString(byte[] bytes) { if (bytes == null) return null; @@ -451,6 +461,7 @@ public class IccUtils { * "offset" points to "octet 3", the coding scheme byte * empty string returned on decode error */ + @UnsupportedAppUsage public static String networkNameToString(byte[] data, int offset, int length) { String ret; @@ -501,6 +512,7 @@ public class IccUtils { * @param length The length of image body * @return The bitmap */ + @UnsupportedAppUsage public static Bitmap parseToBnW(byte[] data, int length){ int valueIndex = 0; int width = data[valueIndex++] & 0xFF; @@ -543,6 +555,7 @@ public class IccUtils { * @param transparency with or without transparency * @return The color bitmap */ + @UnsupportedAppUsage public static Bitmap parseToRGB(byte[] data, int length, boolean transparency) { int valueIndex = 0; diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 81b1e49ffed1..aa4174ad40f4 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -19,9 +19,18 @@ java_sdk_library { name: "android.test.mock", - srcs: ["src/**/*.java"], - api_srcs: [":framework-all-sources"], - libs: ["framework-all"], + srcs: [ + "src/**/*.java", + // Note: Below are NOT APIs of this library. We only take APIs under + // the android.test.mock package. They however provide private APIs that + // android.test.mock APIs references to. + ":framework-core-sources-for-test-mock", + ":framework_native_aidl", + ], + libs: [ + "framework-all", + "app-compat-annotations", + ], api_packages: [ "android.test.mock", diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index a95b6f11e98a..727684eca7ea 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -463,6 +463,13 @@ public class MockContext extends Context { } @Override + public void sendOrderedBroadcast(Intent intent, String receiverPermission, + String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler, + int initialCode, String initialData, Bundle initialExtras) { + throw new UnsupportedOperationException(); + } + + @Override public void sendStickyBroadcast(Intent intent) { throw new UnsupportedOperationException(); } diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java index 81937e6b7005..59f0162bc901 100644 --- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java +++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java @@ -73,46 +73,65 @@ public class BootImageProfileTest implements IDeviceTest { res = mTestDevice.executeShellCommand("truncate -s 0 " + SYSTEM_SERVER_PROFILE).trim(); assertTrue(res, res.length() == 0); // Wait up to 20 seconds for the profile to be saved. - for (int i = 0; i < 20; ++i) { + final int numIterations = 20; + for (int i = 1; i <= numIterations; ++i) { // Force save the profile since we truncated it. if (forceSaveProfile("system_server")) { // Might fail if system server is not yet running. String s = mTestDevice.executeShellCommand( "wc -c <" + SYSTEM_SERVER_PROFILE).trim(); - if (!"0".equals(s)) { - break; + if ("0".equals(s)) { + Thread.sleep(1000); + continue; } } + + // In case the profile is partially saved, wait an extra second. Thread.sleep(1000); - } - // In case the profile is partially saved, wait an extra second. - Thread.sleep(1000); - // Validate that the profile is non empty. - res = mTestDevice.executeShellCommand("profman --dump-only --profile-file=" - + SYSTEM_SERVER_PROFILE); - boolean sawFramework = false; - boolean sawServices = false; - for (String line : res.split("\n")) { - if (line.contains("framework.jar")) { - sawFramework = true; - } else if (line.contains("services.jar")) { - sawServices = true; + + // Validate that the profile is non empty. + res = mTestDevice.executeShellCommand("profman --dump-only --profile-file=" + + SYSTEM_SERVER_PROFILE); + boolean sawFramework = false; + boolean sawServices = false; + for (String line : res.split("\n")) { + if (line.contains("framework.jar")) { + sawFramework = true; + } else if (line.contains("services.jar")) { + sawServices = true; + } + } + if (i == numIterations) { + // Only assert for last iteration since there are race conditions where the package + // manager might not be started whewn the profile saves. + assertTrue("Did not see framework.jar in " + res, sawFramework); + assertTrue("Did not see services.jar in " + res, sawServices); } - } - assertTrue("Did not see framework.jar in " + res, sawFramework); - assertTrue("Did not see services.jar in " + res, sawServices); + // Test the profile contents contain common methods for core-oj that would normally be + // AOT compiled. Also test that services.jar has PackageManagerService.<init> since the + // package manager service should always be created during boot. + res = mTestDevice.executeShellCommand( + "profman --dump-classes-and-methods --profile-file=" + + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar" + + " --apk=/system/framework/services.jar"); + boolean sawObjectInit = false; + boolean sawPmInit = false; + for (String line : res.split("\n")) { + if (line.contains("Ljava/lang/Object;-><init>()V")) { + sawObjectInit = true; + } else if (line.contains("Lcom/android/server/pm/PackageManagerService;-><init>")) { + sawPmInit = true; + } + } + if (i == numIterations) { + assertTrue("Did not see Object.<init> in " + res, sawObjectInit); + assertTrue("Did not see PackageManagerService.<init> in " + res, sawPmInit); + } - // Test the profile contents contain common methods for core-oj that would normally be AOT - // compiled. - res = mTestDevice.executeShellCommand("profman --dump-classes-and-methods --profile-file=" - + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar"); - boolean sawObjectInit = false; - for (String line : res.split("\n")) { - if (line.contains("Ljava/lang/Object;-><init>()V")) { - sawObjectInit = true; + if (sawFramework && sawServices && sawObjectInit && sawPmInit) { + break; // Asserts passed, exit. } } - assertTrue("Did not see Object.<init> in " + res, sawObjectInit); } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java index fd31aa531107..e033d0ab9578 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java @@ -78,6 +78,7 @@ class CommonTransitions { return TransitionRunner.newBuilder() .withTag("OpenAppWarm_" + testApp.getLauncherName() + rotationToString(beginRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBeforeAll(() -> setRotation(device, beginRotation)) .runBeforeAll(testApp::open) @@ -94,6 +95,7 @@ class CommonTransitions { device) { return TransitionRunner.newBuilder() .withTag("closeAppWithBackKey_" + testApp.getLauncherName()) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(testApp::open) .runBefore(device::waitForIdle) @@ -108,6 +110,7 @@ class CommonTransitions { device) { return TransitionRunner.newBuilder() .withTag("closeAppWithHomeKey_" + testApp.getLauncherName()) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(testApp::open) .runBefore(device::waitForIdle) @@ -123,6 +126,7 @@ class CommonTransitions { return TransitionRunner.newBuilder() .withTag("OpenAppCold_" + testApp.getLauncherName() + rotationToString(beginRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(device::pressHome) .runBeforeAll(() -> setRotation(device, beginRotation)) @@ -140,6 +144,7 @@ class CommonTransitions { .withTag("changeAppRotation_" + testApp.getLauncherName() + rotationToString(beginRotation) + "_" + rotationToString(endRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBeforeAll(testApp::open) .runBefore(() -> setRotation(device, beginRotation)) @@ -156,6 +161,7 @@ class CommonTransitions { rotationToString(beginRotation) + "_" + rotationToString(endRotation); return TransitionRunner.newBuilder() .withTag(testTag) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBeforeAll(() -> { context.startActivity(intent); @@ -173,6 +179,7 @@ class CommonTransitions { static TransitionBuilder appToSplitScreen(IAppHelper testApp, UiDevice device) { return TransitionRunner.newBuilder() .withTag("appToSplitScreen_" + testApp.getLauncherName()) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(testApp::open) .runBefore(device::waitForIdle) @@ -186,6 +193,7 @@ class CommonTransitions { static TransitionBuilder splitScreenToLauncher(IAppHelper testApp, UiDevice device) { return TransitionRunner.newBuilder() .withTag("splitScreenToLauncher_" + testApp.getLauncherName()) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(testApp::open) .runBefore(device::waitForIdle) @@ -200,6 +208,7 @@ class CommonTransitions { return TransitionRunner.newBuilder() .withTag("editTextSetFocus_" + testApp.getLauncherName() + rotationToString(beginRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(device::pressHome) .runBefore(() -> setRotation(device, beginRotation)) @@ -218,6 +227,7 @@ class CommonTransitions { + rotationToString(beginRotation); return TransitionRunner.newBuilder() .withTag(testTag) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBeforeAll(() -> setRotation(device, beginRotation)) .runBeforeAll(() -> clearRecents(device)) @@ -246,6 +256,7 @@ class CommonTransitions { return TransitionRunner.newBuilder() .withTag("editTextLoseFocusToHome_" + testApp.getLauncherName() + rotationToString(beginRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(device::pressHome) .runBefore(() -> setRotation(device, beginRotation)) @@ -262,6 +273,7 @@ class CommonTransitions { return TransitionRunner.newBuilder() .withTag("editTextLoseFocusToApp_" + testApp.getLauncherName() + rotationToString(beginRotation)) + .recordAllRuns() .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen) .runBefore(device::pressHome) .runBefore(() -> setRotation(device, beginRotation)) diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp new file mode 100644 index 000000000000..5e9ef8efc402 --- /dev/null +++ b/tests/PlatformCompatGating/Android.bp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2019 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. +// + +android_test { + name: "PlatformCompatGating", + // Only compile source java files in this apk. + srcs: ["src/**/*.java"], + certificate: "platform", + libs: [ + "android.test.runner", + "android.test.base", + ], + static_libs: [ + "junit", + "android-support-test", + "mockito-target-minus-junit4", + "truth-prebuilt", + "platform-compat-test-rules" + ], +} diff --git a/tests/PlatformCompatGating/AndroidManifest.xml b/tests/PlatformCompatGating/AndroidManifest.xml new file mode 100644 index 000000000000..7f14b83fbc75 --- /dev/null +++ b/tests/PlatformCompatGating/AndroidManifest.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tests.gating"> + <application android:label="GatingTest"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.tests.gating"/> +</manifest> diff --git a/tests/PlatformCompatGating/AndroidTest.xml b/tests/PlatformCompatGating/AndroidTest.xml new file mode 100644 index 000000000000..c62684837332 --- /dev/null +++ b/tests/PlatformCompatGating/AndroidTest.xml @@ -0,0 +1,30 @@ +<!-- 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. +--> +<configuration description="Test compatibility change gating."> + <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="PlatformCompatGating.apk"/> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/> + <option name="test-suite-tag" value="apct"/> + <option name="test-tag" value="Gating"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.tests.gating"/> + <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java b/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java new file mode 100644 index 000000000000..731be8e3d9f0 --- /dev/null +++ b/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 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.compat.testing; + +import android.compat.Compatibility; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.compat.IPlatformCompat; + +/** + * This is a dummy API to test gating + * + * @hide + */ +public class DummyApi { + + public static final long CHANGE_ID = 666013; + public static final long CHANGE_ID_1 = 666014; + public static final long CHANGE_ID_2 = 666015; + public static final long CHANGE_SYSTEM_SERVER = 666016; + + /** + * Dummy method + * @return "A" if change is enabled, "B" otherwise. + */ + public static String dummyFunc() { + if (Compatibility.isChangeEnabled(CHANGE_ID)) { + return "A"; + } + return "B"; + } + + /** + * Dummy combined method + * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled, + "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled, + "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled, + "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled. + */ + public static String dummyCombinedFunc() { + if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "0"; + } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "1"; + } else if (Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "2"; + } + return "3"; + } + + /** + * Dummy api using system server API. + */ + public static boolean dummySystemServer(Context context) { + IPlatformCompat platformCompat = IPlatformCompat.Stub + .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + if (platformCompat == null) { + throw new RuntimeException("Could not obtain IPlatformCompat instance!"); + } + String packageName = context.getPackageName(); + try { + return platformCompat.isChangeEnabledByPackageName(CHANGE_SYSTEM_SERVER, packageName, + context.getUserId()); + } catch (RemoteException e) { + throw new RuntimeException("Could not get change value!", e); + } + } +} diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java new file mode 100644 index 000000000000..dc317f1941c7 --- /dev/null +++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java @@ -0,0 +1,94 @@ +/* + * 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.tests.gating; + +import static com.google.common.truth.Truth.assertThat; + +import android.compat.testing.PlatformCompatChangeRule; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import com.android.compat.testing.DummyApi; + +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; + +/** + * Tests for platform compatibility change gating. + */ +@RunWith(AndroidJUnit4.class) +public class PlatformCompatGatingTest { + + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingPositive() { + assertThat(DummyApi.dummyFunc()).isEqualTo("A"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingNegative() { + assertThat(DummyApi.dummyFunc()).isEqualTo("B"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined0() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1}) + @EnableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined1() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1}) + @DisableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined2() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined3() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) + public void testDummyGatingPositiveSystemServer() { + assertThat( + DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue(); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) + public void testDummyGatingNegativeSystemServer() { + assertThat( + DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse(); + } +} diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp new file mode 100644 index 000000000000..8211ef523ee7 --- /dev/null +++ b/tests/PlatformCompatGating/test-rules/Android.bp @@ -0,0 +1,26 @@ +// +// Copyright (C) 2019 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. +// + +java_library { + name: "platform-compat-test-rules", + srcs: ["src/**/*.java"], + static_libs: [ + "junit", + "android-support-test", + "truth-prebuilt", + "core-compat-test-rules" + ], +}
\ No newline at end of file diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java new file mode 100644 index 000000000000..932ec643d478 --- /dev/null +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019 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.compat.testing; + +import android.app.Instrumentation; +import android.compat.Compatibility; +import android.compat.Compatibility.ChangeConfig; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.support.test.InstrumentationRegistry; + +import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.IPlatformCompat; + +import libcore.junit.util.compat.CoreCompatChangeRule; + +import org.junit.runners.model.Statement; + +/** + * Allows tests to specify the which change to disable. + * + * <p>To use add the following to the test class. It will only change the behavior of a test method + * if it is annotated with + * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or + * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges}. + * </p> + * <pre> + * @Rule + * public TestRule compatChangeRule = new PlatformCompatChangeRule(); + * </pre> + * + * <p>Each test method that needs to disable a specific change needs to be annotated + * with {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or + * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} specifying the change + * id. e.g.: + * </p> + * <pre> + * @Test + * @DisableCompatChanges({42}) + * public void testAsIfChange42Disabled() { + * // check behavior + * } + * + * @Test + * @EnableCompatChanges({42}) + * public void testAsIfChange42Enabled() { + * // check behavior + * + * </pre> + */ +public class PlatformCompatChangeRule extends CoreCompatChangeRule { + + @Override + protected Statement createStatementForConfig(final Statement statement, ChangeConfig config) { + return new CompatChangeStatement(statement, config); + } + + + private static class CompatChangeStatement extends Statement { + private final Statement mTestStatement; + private final ChangeConfig mConfig; + + private CompatChangeStatement(Statement testStatement, ChangeConfig config) { + this.mTestStatement = testStatement; + this.mConfig = config; + } + + @Override + public void evaluate() throws Throwable { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + String packageName = instrumentation.getTargetContext().getPackageName(); + IPlatformCompat platformCompat = IPlatformCompat.Stub + .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + if (platformCompat == null) { + throw new IllegalStateException("Could not get IPlatformCompat service!"); + } + Compatibility.setOverrides(mConfig); + try { + platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), + packageName); + try { + mTestStatement.evaluate(); + } finally { + platformCompat.clearOverridesForTest(packageName); + } + } catch (RemoteException e) { + throw new RuntimeException("Could not call IPlatformCompat binder method!", e); + } finally { + Compatibility.clearOverrides(); + } + } + } +} diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index bad294794337..b767b0842f78 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -19,6 +19,7 @@ package com.android.tests.rollback.host; import static org.junit.Assert.assertTrue; import com.android.ddmlib.Log.LogLevel; +import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; @@ -95,7 +96,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { + "watchdog_request_timeout_millis 300000"); // Simulate re-installation of new NetworkStack with rollbacks enabled getDevice().executeShellCommand("pm install -r --staged --enable-rollback " - + "/system/priv-app/NetworkStack/NetworkStack.apk"); + + getNetworkStackPath()); // Sleep to allow writes to disk before reboot Thread.sleep(5000); @@ -141,7 +142,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { + "watchdog_request_timeout_millis 300000"); // Simulate re-installation of new NetworkStack with rollbacks enabled getDevice().executeShellCommand("pm install -r --staged --enable-rollback " - + "/system/priv-app/NetworkStack/NetworkStack.apk"); + + getNetworkStackPath()); // Sleep to allow writes to disk before reboot Thread.sleep(5000); @@ -165,4 +166,9 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { // Verify rollback was not executed after health check deadline runPhase("assertNoNetworkStackRollbackCommitted"); } + + private String getNetworkStackPath() throws DeviceNotAvailableException { + // Find the NetworkStack path (can be NetworkStack.apk or NetworkStackNext.apk) + return getDevice().executeShellCommand("ls /system/priv-app/NetworkStack*/*.apk"); + } } diff --git a/tests/net/common/java/android/net/NetworkScoreTest.kt b/tests/net/common/java/android/net/NetworkScoreTest.kt new file mode 100644 index 000000000000..30836b7c9be1 --- /dev/null +++ b/tests/net/common/java/android/net/NetworkScoreTest.kt @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net + +import android.os.Parcelable +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.assertParcelSane +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +private const val TEST_SCORE = 80 +private const val KEY_DEFAULT_CAPABILITIES = "DEFAULT_CAPABILITIES" + +@RunWith(AndroidJUnit4::class) +@SmallTest +class NetworkScoreTest { + @Test + fun testParcelNetworkScore() { + val networkScore = NetworkScore() + val defaultCap = NetworkCapabilities() + networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) + assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES)) + networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) + assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) + assertParcelSane(networkScore, 1) + } + + @Test + fun testNullKeyAndValue() { + val networkScore = NetworkScore() + val defaultCap = NetworkCapabilities() + networkScore.putIntExtension(null, TEST_SCORE) + assertEquals(TEST_SCORE, networkScore.getIntExtension(null)) + networkScore.putExtension(null, defaultCap) + assertEquals(defaultCap, networkScore.getExtension(null)) + networkScore.putExtension(null, null) + val result: Parcelable? = networkScore.getExtension(null) + assertEquals(null, result) + } + + @Test + fun testRemoveExtension() { + val networkScore = NetworkScore() + val defaultCap = NetworkCapabilities() + networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) + networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) + assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES)) + assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) + networkScore.removeExtension(KEY_DEFAULT_CAPABILITIES) + networkScore.removeExtension(NetworkScore.LEGACY_SCORE) + val result: Parcelable? = networkScore.getExtension(KEY_DEFAULT_CAPABILITIES) + assertEquals(null, result) + assertEquals(0, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) + } + + @Test + fun testEqualsNetworkScore() { + val ns1 = NetworkScore() + val ns2 = NetworkScore() + assertTrue(ns1.equals(ns2)) + assertEquals(ns1.hashCode(), ns2.hashCode()) + + ns1.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) + assertFalse(ns1.equals(ns2)) + assertNotEquals(ns1.hashCode(), ns2.hashCode()) + ns2.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) + assertTrue(ns1.equals(ns2)) + assertEquals(ns1.hashCode(), ns2.hashCode()) + + val defaultCap = NetworkCapabilities() + ns1.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) + assertFalse(ns1.equals(ns2)) + assertNotEquals(ns1.hashCode(), ns2.hashCode()) + ns2.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) + assertTrue(ns1.equals(ns2)) + assertEquals(ns1.hashCode(), ns2.hashCode()) + + ns1.putIntExtension(null, 10) + assertFalse(ns1.equals(ns2)) + assertNotEquals(ns1.hashCode(), ns2.hashCode()) + ns2.putIntExtension(null, 10) + assertTrue(ns1.equals(ns2)) + assertEquals(ns1.hashCode(), ns2.hashCode()) + } +} diff --git a/tests/net/integration/AndroidManifest.xml b/tests/net/integration/AndroidManifest.xml index 91b3cd9e791f..4dd3b5a23d7a 100644 --- a/tests/net/integration/AndroidManifest.xml +++ b/tests/net/integration/AndroidManifest.xml @@ -17,7 +17,6 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" package="com.android.server.net.integrationtests"> <!-- For ConnectivityService registerReceiverAsUser (receiving broadcasts) --> @@ -26,13 +25,19 @@ <uses-permission android:name="android.permission.MANAGE_USERS" /> <!-- ConnectivityService sends notifications to BatteryStats --> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> + <!-- Reading network status --> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> + <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> + <!-- Reading DeviceConfig flags --> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> <!-- This manifest is merged with the base manifest of the real NetworkStack app. Remove the NetworkStackService from the base (real) manifest, and replace with a test service that responds to the same intent --> - <service android:name="com.android.server.NetworkStackService" tools:node="remove"/> <service android:name=".TestNetworkStackService" android:process="com.android.server.net.integrationtests.testnetworkstack"> <intent-filter> @@ -45,9 +50,9 @@ <action android:name=".INetworkStackInstrumentation"/> </intent-filter> </service> - <service tools:replace="android:process" - android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService" - android:process="com.android.server.net.integrationtests.testnetworkstack"/> + <service android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService" + android:process="com.android.server.net.integrationtests.testnetworkstack" + android:permission="android.permission.BIND_JOB_SERVICE"/> </application> diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java index 1f2bb0ac05ee..84c5784d3fa8 100644 --- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java +++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java @@ -46,7 +46,6 @@ import androidx.test.runner.AndroidJUnit4; import libcore.util.HexEncoding; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -202,14 +201,29 @@ public class InetDiagSocketTest { checkGetConnectionOwnerUid("::1", "::1"); } - @Ignore("Times out on Marlin/Sailfish") /* Verify fix for b/141603906 */ @Test public void testB141603906() throws Exception { final InetSocketAddress src = new InetSocketAddress(0); final InetSocketAddress dst = new InetSocketAddress(0); - for (int i = 1; i <= 100000; i++) { - mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst); + final int numThreads = 8; + final int numSockets = 5000; + final Thread[] threads = new Thread[numThreads]; + + for (int i = 0; i < numThreads; i++) { + threads[i] = new Thread(() -> { + for (int j = 0; j < numSockets; j++) { + mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst); + } + }); + } + + for (Thread thread : threads) { + thread.start(); + } + + for (Thread thread : threads) { + thread.join(); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 61f37fd6c7e2..d6ce32018190 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -20,6 +20,9 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; +import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; +import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; +import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; @@ -28,6 +31,7 @@ import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; @@ -145,6 +149,7 @@ import android.net.MatchAllNetworkSpecifier; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkFactory; +import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; @@ -244,6 +249,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; import kotlin.reflect.KClass; @@ -330,6 +336,9 @@ public class ConnectivityServiceTest { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; + // Contains all registered receivers since this object was created. Useful to clear + // them when needed, as BroadcastInterceptingContext does not provide this facility. + private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>(); @Spy private Resources mResources; private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); @@ -343,6 +352,7 @@ public class ConnectivityServiceTest { "wifi,1,1,1,-1,true", "mobile,0,0,0,-1,true", "mobile_mms,2,0,2,60000,true", + "mobile_supl,3,0,2,60000,true", }); when(mResources.getStringArray( @@ -410,6 +420,19 @@ public class ConnectivityServiceTest { // make sure the code does not rely on unexpected permissions. super.enforceCallingOrSelfPermission(permission, message); } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + mRegisteredReceivers.add(receiver); + return super.registerReceiver(receiver, filter); + } + + public void clearRegisteredReceivers() { + // super.unregisterReceiver is a no-op for receivers that are not registered (because + // they haven't been registered or because they have already been unregistered). + // For the same reason, don't bother clearing mRegisteredReceivers. + for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv); + } } private void waitForIdle() { @@ -1228,16 +1251,25 @@ public class ConnectivityServiceTest { * broadcasts are received. */ private ConditionVariable waitForConnectivityBroadcasts(final int count) { + return waitForConnectivityBroadcasts(count, intent -> true); + } + + private ConditionVariable waitForConnectivityBroadcasts(final int count, + @NonNull final Predicate<Intent> filter) { final ConditionVariable cv = new ConditionVariable(); - mServiceContext.registerReceiver(new BroadcastReceiver() { + final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION); + intentFilter.addAction(CONNECTIVITY_ACTION_SUPL); + final BroadcastReceiver receiver = new BroadcastReceiver() { private int remaining = count; public void onReceive(Context context, Intent intent) { + if (!filter.test(intent)) return; if (--remaining == 0) { cv.open(); mServiceContext.unregisterReceiver(this); } } - }, new IntentFilter(CONNECTIVITY_ACTION)); + }; + mServiceContext.registerReceiver(receiver, intentFilter); return cv; } @@ -1258,6 +1290,75 @@ public class ConnectivityServiceTest { } @Test + public void testNetworkFeature() throws Exception { + // Connect the cell agent and wait for the connected broadcast. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL); + final ConditionVariable cv1 = waitForConnectivityBroadcasts(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE); + mCellNetworkAgent.connect(true); + waitFor(cv1); + + // Build legacy request for SUPL. + final NetworkCapabilities legacyCaps = new NetworkCapabilities(); + legacyCaps.addTransportType(TRANSPORT_CELLULAR); + legacyCaps.addCapability(NET_CAPABILITY_SUPL); + final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL, + ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST); + + // Send request and check that the legacy broadcast for SUPL is sent correctly. + final TestNetworkCallback callback = new TestNetworkCallback(); + final ConditionVariable cv2 = waitForConnectivityBroadcasts(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + mCm.requestNetwork(legacyRequest, callback); + callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + waitFor(cv2); + + // File another request, withdraw it and make sure no broadcast is sent + final ConditionVariable cv3 = waitForConnectivityBroadcasts(1); + final TestNetworkCallback callback2 = new TestNetworkCallback(); + mCm.requestNetwork(legacyRequest, callback2); + callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + mCm.unregisterNetworkCallback(callback2); + assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent + // As the broadcast did not fire, the receiver was not unregistered. Do this now. + mServiceContext.clearRegisteredReceivers(); + + // Withdraw the request and check that the broadcast for disconnection is sent. + final ConditionVariable cv4 = waitForConnectivityBroadcasts(1, intent -> + !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected() + && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + mCm.unregisterNetworkCallback(callback); + waitFor(cv4); + + // Re-file the request and expect the connected broadcast again + final ConditionVariable cv5 = waitForConnectivityBroadcasts(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + final TestNetworkCallback callback3 = new TestNetworkCallback(); + mCm.requestNetwork(legacyRequest, callback3); + callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + waitFor(cv5); + + // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one + // for mobile. Use a small hack to check that both have been sent, but the order is + // not contractual. + final AtomicBoolean vanillaAction = new AtomicBoolean(false); + final AtomicBoolean suplAction = new AtomicBoolean(false); + final ConditionVariable cv6 = waitForConnectivityBroadcasts(2, intent -> { + if (intent.getAction().equals(CONNECTIVITY_ACTION)) { + vanillaAction.set(true); + } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) { + suplAction.set(true); + } + return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected(); + }); + mCellNetworkAgent.disconnect(); + waitFor(cv6); + assertTrue(vanillaAction.get()); + assertTrue(suplAction.get()); + } + + @Test public void testLingering() throws Exception { verifyNoNetwork(); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt index f045369459c9..42d4cf3c382b 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -18,6 +18,7 @@ package com.android.server import android.net.ConnectivityManager.TYPE_ETHERNET import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_MOBILE_SUPL import android.net.ConnectivityManager.TYPE_WIFI import android.net.ConnectivityManager.TYPE_WIMAX import android.net.NetworkInfo.DetailedState.CONNECTED @@ -46,7 +47,7 @@ const val UNSUPPORTED_TYPE = TYPE_WIMAX @RunWith(AndroidJUnit4::class) @SmallTest class LegacyTypeTrackerTest { - private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET) + private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL) private val mMockService = mock(ConnectivityService::class.java).apply { doReturn(false).`when`(this).isDefaultNetwork(any()) @@ -70,6 +71,26 @@ class LegacyTypeTrackerTest { } @Test + fun testSupl() { + val mobileNai = mock(NetworkAgentInfo::class.java) + mTracker.add(TYPE_MOBILE, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE) + reset(mMockService) + mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.remove(mobileNai, false) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE) + } + + @Test fun testAddNetwork() { val mobileNai = mock(NetworkAgentInfo::class.java) val wifiNai = mock(NetworkAgentInfo::class.java) diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 142769f61335..535298f9b09a 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -39,6 +39,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkMisc; +import android.net.NetworkScore; import android.os.INetworkManagementService; import android.text.format.DateUtils; @@ -354,8 +355,10 @@ public class LingerMonitorTest { NetworkCapabilities caps = new NetworkCapabilities(); caps.addCapability(0); caps.addTransportType(transport); + NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, - caps, 50, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS, + caps, ns, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS, NetworkFactory.SerialNumber.NONE); nai.everValidated = true; return nai; diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index 5f62c08f55f3..9e5717b4bd64 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -208,6 +208,12 @@ public class TetheringTest { if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; return super.getSystemService(name); } + + @Override + public String getSystemServiceName(Class<?> serviceClass) { + if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE; + return super.getSystemServiceName(serviceClass); + } } public class MockIpServerDependencies extends IpServer.Dependencies { diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 1d29a824d10d..4d42a612030d 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -192,8 +192,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService = new NetworkStatsService( mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock, - TelephonyManager.getDefault(), mSettings, mStatsFactory, - new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); + mServiceContext.getSystemService(TelephonyManager.class), mSettings, + mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); mHandlerThread = new HandlerThread("HandlerThread"); mHandlerThread.start(); Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService); diff --git a/tests/touchlag/Android.bp b/tests/touchlag/Android.bp deleted file mode 100644 index 092eea918b1d..000000000000 --- a/tests/touchlag/Android.bp +++ /dev/null @@ -1,14 +0,0 @@ -cc_test { - name: "test-touchlag", - gtest: false, - srcs: ["touchlag.cpp"], - shared_libs: [ - "libcutils", - "libutils", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], -} diff --git a/tests/touchlag/touchlag.cpp b/tests/touchlag/touchlag.cpp deleted file mode 100644 index 9264a254ed24..000000000000 --- a/tests/touchlag/touchlag.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <sys/types.h> - -#include <fcntl.h> -#include <sys/ioctl.h> -#include <linux/fb.h> -#include <linux/input.h> -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <cutils/memory.h> -#include <asm-generic/mman.h> -#include <sys/mman.h> -#include <utils/threads.h> -#include <unistd.h> -#include <math.h> - -using namespace android; - -#ifndef FBIO_WAITFORVSYNC -#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) -#endif - -struct Buffer { - size_t w; - size_t h; - size_t s; - union { - void* addr; - uint32_t* pixels; - }; -}; - -void clearBuffer(Buffer* buf, uint32_t pixel) { - android_memset32(buf->pixels, pixel, buf->s * buf->h * 4); -} - -void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) { - if (y>0 && y<ssize_t(buf->h)) { - uint32_t* bits = buf->pixels + y * buf->s; - if (x>=0 && x<ssize_t(buf->w)) { - bits[x] = pixel; - } - ssize_t W(w); - if ((x+W)>=0 && (x+W)<ssize_t(buf->w)) { - bits[x+W] = pixel; - } - } -} - -void drawHLine(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) { - if (y>0 && y<ssize_t(buf->h)) { - ssize_t W(w); - if (x<0) { - W += x; - x = 0; - } - if (x+w > buf->w) { - W = buf->w - x; - } - if (W>0) { - uint32_t* bits = buf->pixels + y * buf->s + x; - android_memset32(bits, pixel, W*4); - } - } -} - -void drawRect(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w, size_t h) { - ssize_t W(w), H(h); - if (x<0) { - w += x; - x = 0; - } - if (y<0) { - h += y; - y = 0; - } - if (x+w > buf->w) W = buf->w - x; - if (y+h > buf->h) H = buf->h - y; - if (W>0 && H>0) { - uint32_t* bits = buf->pixels + y * buf->s + x; - for (ssize_t i=0 ; i<H ; i++) { - android_memset32(bits, pixel, W*4); - bits += buf->s; - } - } -} - -void drawCircle(Buffer* buf, uint32_t pixel, - size_t x0, size_t y0, size_t radius, bool filled = false) { - ssize_t f = 1 - radius; - ssize_t ddF_x = 1; - ssize_t ddF_y = -2 * radius; - ssize_t x = 0; - ssize_t y = radius; - if (filled) { - drawHLine(buf, pixel, x0-radius, y0, 2*radius); - } else { - drawTwoPixels(buf, pixel, x0-radius, y0, 2*radius); - } - while (x < y) { - if (f >= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - if (filled) { - drawHLine(buf, pixel, x0-x, y0+y, 2*x); - drawHLine(buf, pixel, x0-x, y0-y, 2*x); - drawHLine(buf, pixel, x0-y, y0+x, 2*y); - drawHLine(buf, pixel, x0-y, y0-x, 2*y); - } else { - drawTwoPixels(buf, pixel, x0-x, y0+y, 2*x); - drawTwoPixels(buf, pixel, x0-x, y0-y, 2*x); - drawTwoPixels(buf, pixel, x0-y, y0+x, 2*y); - drawTwoPixels(buf, pixel, x0-y, y0-x, 2*y); - } - } -} - -class TouchEvents { - class EventThread : public Thread { - int fd; - - virtual bool threadLoop() { - input_event event; - int first_down = 0; - do { - read(fd, &event, sizeof(event)); - if (event.type == EV_ABS) { - if (event.code == ABS_MT_TRACKING_ID) { - down = event.value == -1 ? 0 : 1; - first_down = down; - } - if (event.code == ABS_MT_POSITION_X) { - x = event.value; - } - if (event.code == ABS_MT_POSITION_Y) { - y = event.value; - } - } - } while (event.type == EV_SYN); - return true; - } - - public: - int x, y, down; - EventThread() : Thread(false), - x(0), y(0), down(0) - { - fd = open("/dev/input/event1", O_RDONLY); - } -}; - sp<EventThread> thread; - -public: - TouchEvents() { - thread = new EventThread(); - thread->run("EventThread", PRIORITY_URGENT_DISPLAY); - } - - int getMostRecentPosition(int* x, int* y) { - *x = thread->x; - *y = thread->y; - return thread->down; - } -}; - - -struct Queue { - struct position { - int x, y; - }; - int index; - position q[16]; - Queue() : index(0) { } - void push(int x, int y) { - index++; - index &= 0xF; - q[index].x = x; - q[index].y = y; - } - void get(int lag, int* x, int* y) { - const int i = (index - lag) & 0xF; - *x = q[i].x; - *y = q[i].y; - } -}; - -extern char *optarg; -extern int optind; -extern int optopt; -extern int opterr; -extern int optreset; - -void usage(const char* name) { - printf("\nusage: %s [-h] [-l lag]\n", name); -} - -int main(int argc, char** argv) { - fb_var_screeninfo vi; - fb_fix_screeninfo fi; - - int lag = 0; - int fd = open("/dev/graphics/fb0", O_RDWR); - ioctl(fd, FBIOGET_VSCREENINFO, &vi); - ioctl(fd, FBIOGET_FSCREENINFO, &fi); - void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - Buffer framebuffer; - framebuffer.w = vi.xres; - framebuffer.h = vi.yres; - framebuffer.s = fi.line_length / (vi.bits_per_pixel >> 3); - framebuffer.addr = bits; - - int ch; - while ((ch = getopt(argc, argv, "hl:")) != -1) { - switch (ch) { - case 'l': - lag = atoi(optarg); - break; - case 'h': - default: - usage(argv[0]); - exit(0); - } - } - argc -= optind; - argv += optind; - - - TouchEvents touch; - Queue queue; - - - int x=0, y=0; - int lag_x=0, lag_y=0; - - clearBuffer(&framebuffer, 0); - while (true) { - uint32_t crt = 0; - ioctl(fd, FBIO_WAITFORVSYNC, &crt); - - // draw beam marker - drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h); - // erase screen - if (lag) { - drawCircle(&framebuffer, 0, lag_x, lag_y, 100); - drawHLine(&framebuffer, 0, 0, lag_y, 32); - } - drawCircle(&framebuffer, 0, x, y, 100, true); - drawHLine(&framebuffer, 0, 0, y, 32); - - // draw a line at y=1000 - drawHLine(&framebuffer, 0x808080, 0, 1000, framebuffer.w); - - // get touch events - touch.getMostRecentPosition(&x, &y); - queue.push(x, y); - queue.get(lag, &lag_x, &lag_y); - - if (lag) { - drawCircle(&framebuffer, 0x00FF00, lag_x, lag_y, 100); - drawHLine(&framebuffer, 0x00FF00, 0, lag_y, 32); - } - - drawCircle(&framebuffer, 0xFFFFFF, x, y, 100, true); - drawHLine(&framebuffer, 0xFFFFFF, 0, y, 32); - - // draw end of frame beam marker - drawRect(&framebuffer, 0x004000, framebuffer.w-2, 0, 2, framebuffer.h); - } - - close(fd); - return 0; -} diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp index c5de9e058907..5e0300b3071b 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp @@ -231,7 +231,7 @@ class Visitor : public ValueVisitor { Visitor sub_visitor(pool_, method_); if (plural->values[i]) { plural->values[i]->Accept(&sub_visitor); - if (sub_visitor.value) { + if (sub_visitor.item) { localized->values[i] = std::move(sub_visitor.item); } else { localized->values[i] = std::unique_ptr<Item>(plural->values[i]->Clone(pool_)); diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp index 31358020ab60..e816c86e20a8 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp @@ -234,6 +234,27 @@ TEST(PseudolocaleGeneratorTest, PseudolocalizeOnlyDefaultConfigs) { test::ParseConfigOrDie("ar-rXB"))); } +TEST(PseudolocaleGeneratorTest, PluralsArePseudolocalized) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder().SetPackageId("com.pkg", 0x7F).Build(); + std::unique_ptr<Plural> plural = util::make_unique<Plural>(); + plural->values = {util::make_unique<String>(table->string_pool.MakeRef("zero")), + util::make_unique<String>(table->string_pool.MakeRef("one"))}; + ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.pkg:plurals/foo"), ConfigDescription{}, + {}, std::move(plural), context->GetDiagnostics())); + std::unique_ptr<Plural> expected = util::make_unique<Plural>(); + expected->values = {util::make_unique<String>(table->string_pool.MakeRef("[žéŕö one]")), + util::make_unique<String>(table->string_pool.MakeRef("[öñé one]"))}; + + PseudolocaleGenerator generator; + ASSERT_TRUE(generator.Consume(context.get(), table.get())); + + const auto* actual = test::GetValueForConfig<Plural>(table.get(), "com.pkg:plurals/foo", + test::ParseConfigOrDie("en-rXA")); + EXPECT_TRUE(actual->Equals(expected.get())); +} + TEST(PseudolocaleGeneratorTest, RespectUntranslateableSections) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().SetCompilationPackage("android").Build(); diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp index f1890488276c..9cef7b3d2ce3 100644 --- a/tools/aapt2/format/Container.cpp +++ b/tools/aapt2/format/Container.cpp @@ -30,6 +30,7 @@ namespace aapt { constexpr const static uint32_t kContainerFormatMagic = 0x54504141u; constexpr const static uint32_t kContainerFormatVersion = 1u; +constexpr const static size_t kPaddingAlignment = 4u; ContainerWriter::ContainerWriter(ZeroCopyOutputStream* out, size_t entry_count) : out_(out), total_entry_count_(entry_count), current_entry_count_(0u) { @@ -49,11 +50,17 @@ ContainerWriter::ContainerWriter(ZeroCopyOutputStream* out, size_t entry_count) } } -inline static void WritePadding(int padding, CodedOutputStream* out) { - if (padding < 4) { - const uint32_t zero = 0u; - out->WriteRaw(&zero, padding); - } +inline static size_t CalculatePaddingForAlignment(size_t size) { + size_t overage = size % kPaddingAlignment; + return overage == 0 ? 0 : kPaddingAlignment - overage; +} + +inline static void WritePadding(size_t padding, CodedOutputStream* out) { + CHECK(padding < kPaddingAlignment); + const uint32_t zero = 0u; + static_assert(sizeof(zero) >= kPaddingAlignment, "Not enough source bytes for padding"); + + out->WriteRaw(&zero, padding); } bool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) { @@ -70,7 +77,7 @@ bool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) { // Write the aligned size. const ::google::protobuf::uint64 size = table.ByteSize(); - const int padding = 4 - (size % 4); + const int padding = CalculatePaddingForAlignment(size); coded_out.WriteLittleEndian64(size); // Write the table. @@ -103,9 +110,9 @@ bool ContainerWriter::AddResFileEntry(const pb::internal::CompiledFile& file, // Write the aligned size. const ::google::protobuf::uint32 header_size = file.ByteSize(); - const int header_padding = 4 - (header_size % 4); + const int header_padding = CalculatePaddingForAlignment(header_size); const ::google::protobuf::uint64 data_size = in->TotalSize(); - const int data_padding = 4 - (data_size % 4); + const int data_padding = CalculatePaddingForAlignment(data_size); coded_out.WriteLittleEndian64(kResFileEntryHeaderSize + header_size + header_padding + data_size + data_padding); diff --git a/tools/aapt2/formats.md b/tools/aapt2/formats.md index bb31a005ef42..25a0e798dea2 100644 --- a/tools/aapt2/formats.md +++ b/tools/aapt2/formats.md @@ -23,7 +23,7 @@ boundary, so if a previous entry ends unaligned, padding must be inserted. | Size (in bytes) | Field | Description | |:----------------|:---------------|:----------------------------------------------------------------------------------------------------------| | `4` | `entry_type` | The type of the entry. This can be one of two types: `RES_TABLE (0x00000000)` or `RES_FILE (0x00000001)`. | -| `8` | `entry_length` | The length of the data that follows. | +| `8` | `entry_length` | The length of the data that follows. Do not use if `entry_type` is `RES_FILE`; this value may be wrong. | | `entry_length` | `data` | The payload. The contents of this varies based on the `entry_type`. | If the `entry_type` is equal to `RES_TABLE (0x00000000)`, the `data` field contains a serialized @@ -32,13 +32,14 @@ If the `entry_type` is equal to `RES_TABLE (0x00000000)`, the `data` field conta If the `entry_type` is equal to `RES_FILE (0x00000001)`, the `data` field contains the following: -| Size (in bytes) | Field | Description | -|:----------------|:---------------|:----------------------------------------------------------------------------------------------------------| -| `4` | `header_size` | The size of the `header` field. | -| `8` | `data_size` | The size of the `data` field. | -| `header_size` | `header` | The serialized Protobuf message [aapt.pb.internal.CompiledFile](ResourcesInternal.proto). | -| `x` | `padding` | Up to 4 bytes of zeros, if padding is necessary to align the `data` field on a 32-bit boundary. | -| `data_size` | `data` | The payload, which is determined by the `type` field in the `aapt.pb.internal.CompiledFile`. This can be a PNG file, binary XML, or [aapt.pb.XmlNode](Resources.proto). | +| Size (in bytes) | Field | Description | +|:----------------|:-----------------|:----------------------------------------------------------------------------------------------------------| +| `4` | `header_size` | The size of the `header` field. | +| `8` | `data_size` | The size of the `data` field. | +| `header_size` | `header` | The serialized Protobuf message [aapt.pb.internal.CompiledFile](ResourcesInternal.proto). | +| `x` | `header_padding` | Up to 3 bytes of zeros, if padding is necessary to align the `data` field on a 32-bit boundary. | +| `data_size` | `data` | The payload, which is determined by the `type` field in the `aapt.pb.internal.CompiledFile`. This can be a PNG file, binary XML, or [aapt.pb.XmlNode](Resources.proto). | +| `y` | `data_padding` | Up to 3 bytes of zeros, if `data_size` is not a multiple of 4. | ## AAPT2 Static Library Format (extension `.sapk`) diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp index 05ba8f05ec67..806f4e37e22a 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -404,12 +404,15 @@ void WriteKeepSet(const KeepSet& keep_set, OutputStream* out, bool minimal_keep) for (const auto& entry : keep_set.conditional_class_set_) { std::set<UsageLocation> locations; - bool can_be_conditional = true; - for (const UsageLocation& location : entry.second) { - can_be_conditional &= CollectLocations(location, keep_set, &locations); + bool can_be_conditional = false; + if (keep_set.conditional_keep_rules_) { + can_be_conditional = true; + for (const UsageLocation& location : entry.second) { + can_be_conditional &= CollectLocations(location, keep_set, &locations); + } } - if (keep_set.conditional_keep_rules_ && can_be_conditional) { + if (can_be_conditional) { for (const UsageLocation& location : locations) { printer.Print("# Referenced at ").Println(location.source.to_string()); printer.Print("-if class **.R$layout { int ") diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h index f9656d112b7b..b15df59f56a6 100644 --- a/tools/aapt2/java/ProguardRules.h +++ b/tools/aapt2/java/ProguardRules.h @@ -99,11 +99,13 @@ bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set, // inline bool operator==(const UsageLocation& lhs, const UsageLocation& rhs) { + // The "source" member is ignored because we only need "name" for outputting + // keep rules; "source" is used for comments. return lhs.name == rhs.name; } -inline int operator<(const UsageLocation& lhs, const UsageLocation& rhs) { - return lhs.name.compare(rhs.name); +inline bool operator<(const UsageLocation& lhs, const UsageLocation& rhs) { + return lhs.name.compare(rhs.name) < 0; } // diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp index 559b07af3e80..25b55ab003b0 100644 --- a/tools/aapt2/java/ProguardRules_test.cpp +++ b/tools/aapt2/java/ProguardRules_test.cpp @@ -364,4 +364,12 @@ TEST(ProguardRulesTest, TransitionRulesAreEmitted) { "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }")); } +TEST(ProguardRulesTest, UsageLocationComparator) { + proguard::UsageLocation location1 = {{"pkg", ResourceType::kAttr, "x"}}; + proguard::UsageLocation location2 = {{"pkg", ResourceType::kAttr, "y"}}; + + EXPECT_EQ(location1 < location2, true); + EXPECT_EQ(location2 < location1, false); +} + } // namespace aapt diff --git a/tools/apilint/apilint b/tools/apilint/apilint deleted file mode 100755 index e42857f1a190..000000000000 --- a/tools/apilint/apilint +++ /dev/null @@ -1,147 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2019 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. - -if [ "$1" == "--help" -o "$1" == "-h" ]; then -echo "Usage: apilint [FILTERS...]" -echo " Shows lint from currently open files (as diffed from HEAD), i.e. errors" -echo " you will receive if you upload this CL." -echo -echo "Usage: apilint --all [FILTERS...]" -echo " Shows all lint errors present in the current working directory, regardless" -echo " of when they were added." -echo -echo "Usage: apilint --level API_LEVEL [FILTERS...]" -echo " Shows lint as it stands in API_LEVEL" -echo -echo "Usage: apilint --shal SHA [FILTERS...]" -echo " Shows lint from locally commited git change SHA." -echo -echo "Usage: apilint --unreleased [FILTERS...]" -echo " Shows all lint errors in the current working directory directory added since" -echo " the last released SDK version." -echo -echo "FILTERS" -echo " List of class or package names by which to filter the results." -echo -exit -fi - -if [ \( -z "$ANDROID_BUILD_TOP" \) \ - -a \( ! -f frameworks/base/api/current.txt \) \ - -a \( ! -f frameworks/base/api/system-current.txt \) \ - ]; then - echo "apilint must be run either with ANDROID_BUILD_TOP set or from the" 1>&2 - echo "root of the android source tree" 1>&2 - exit 1 -fi - -if [ ${ANDROID_BUILD_TOP:0:1} != "/" ]; then - echo "ANDROID_BUILD_TOP must be an absolute path, not: $ANDROID_BUILD_TOP" 1>&2 - exit 1 -fi - -if [ -z "$ANDROID_BUILD_TOP" ]; then - ANDROID_BUILD_TOP=$(pwd) -fi - -FW_BASE=$ANDROID_BUILD_TOP/frameworks/base - -MODE=open - -OPTIONS=$(getopt -n apilint -o "" -l "all,sha:,unreleased" -- "$@") - -[ $? -eq 0 ] || { - exit 1 -} - -eval set -- "$OPTIONS" -while true; do - case "$1" in - --all) - MODE=all - ;; - --sha) - shift; # The arg is next in position args - MODE=sha - SHA=$1 - ;; - --unreleased) - MODE=unreleased - ;; - --) - shift - break - ;; - esac - shift -done -FILTERS= -for var in "$@" -do - FILTERS="$FILTERS --filter $var" -done - -if [ $MODE = "all" ]; then - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SDK" \ - $FILTERS \ - $ANDROID_BUILD_TOP/frameworks/base/api/current.txt - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SystemApi" \ - $FILTERS \ - --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \ - $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt -elif [ $MODE = "open" ]; then - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SDK" \ - $FILTERS \ - $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \ - <(cd $FW_BASE ; git show HEAD:api/current.txt) - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SystemApi" \ - $FILTERS \ - --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \ - --base-previous <(cd $FW_BASE ; git show HEAD:api/current.txt) \ - $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \ - <(cd $FW_BASE ; git show HEAD:api/system-current.txt) -elif [ $MODE = "sha" ]; then - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SDK" \ - $FILTERS \ - <(cd $FW_BASE ; git show $SHA:api/current.txt) \ - <(cd $FW_BASE ; git show $SHA^:api/current.txt) - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SystemApi" \ - $FILTERS \ - --base-current <(cd $FW_BASE ; git show $SHA:api/current.txt) \ - --base-previous <(cd $FW_BASE ; git show $SHA^:api/current.txt) \ - <(cd $FW_BASE ; git show $SHA:api/system-current.txt) \ - <(cd $FW_BASE ; git show $SHA^:api/system-current.txt) -elif [ $MODE = "unreleased" ]; then - LAST_SDK=$(ls $ANDROID_BUILD_TOP/prebuilts/sdk | grep "^[0-9][0-9]*$" | sort -n | tail -n 1) - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SDK" \ - $FILTERS \ - $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \ - $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt - python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \ - --title "SystemApi" \ - $FILTERS \ - --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \ - --base-previous $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt \ - $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \ - $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/system/api/android.txt -fi diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py deleted file mode 100644 index 912c1ad377c1..000000000000 --- a/tools/apilint/apilint.py +++ /dev/null @@ -1,2353 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2014 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. - -""" -Enforces common Android public API design patterns. It ignores lint messages from -a previous API level, if provided. - -Usage: apilint.py current.txt -Usage: apilint.py current.txt previous.txt - -You can also splice in blame details like this: -$ git blame api/current.txt -t -e > /tmp/currentblame.txt -$ apilint.py /tmp/currentblame.txt previous.txt --no-color -""" - -import re, sys, collections, traceback, argparse, itertools - - -BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) - -ALLOW_GOOGLE = False -USE_COLOR = True - -def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False): - # manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes - if not USE_COLOR: return "" - codes = [] - if reset: codes.append("0") - else: - if not fg is None: codes.append("3%d" % (fg)) - if not bg is None: - if not bright: codes.append("4%d" % (bg)) - else: codes.append("10%d" % (bg)) - if bold: codes.append("1") - elif dim: codes.append("2") - else: codes.append("22") - return "\033[%sm" % (";".join(codes)) - - -class Field(): - def __init__(self, clazz, line, raw, blame, sig_format = 1): - self.clazz = clazz - self.line = line - self.raw = raw.strip(" {;") - self.blame = blame - - if sig_format == 2: - V2LineParser(raw).parse_into_field(self) - elif sig_format == 1: - # drop generics for now; may need multiple passes - raw = re.sub("<[^<]+?>", "", raw) - raw = re.sub("<[^<]+?>", "", raw) - - raw = raw.split() - self.split = list(raw) - - for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]: - while r in raw: raw.remove(r) - - # ignore annotations for now - raw = [ r for r in raw if not r.startswith("@") ] - - self.typ = raw[0] - self.name = raw[1].strip(";") - if len(raw) >= 4 and raw[2] == "=": - self.value = raw[3].strip(';"') - else: - self.value = None - self.annotations = [] - - self.ident = "-".join((self.typ, self.name, self.value or "")) - - def __hash__(self): - return hash(self.raw) - - def __repr__(self): - return self.raw - - -class Argument(object): - - __slots__ = ["type", "annotations", "name", "default"] - - def __init__(self, type): - self.type = type - self.annotations = [] - self.name = None - self.default = None - - -class Method(): - def __init__(self, clazz, line, raw, blame, sig_format = 1): - self.clazz = clazz - self.line = line - self.raw = raw.strip(" {;") - self.blame = blame - - if sig_format == 2: - V2LineParser(raw).parse_into_method(self) - elif sig_format == 1: - # drop generics for now; may need multiple passes - raw = re.sub("<[^<]+?>", "", raw) - raw = re.sub("<[^<]+?>", "", raw) - - # handle each clause differently - raw_prefix, raw_args, _, raw_throws = re.match(r"(.*?)\((.*?)\)( throws )?(.*?);$", raw).groups() - - # parse prefixes - raw = re.split("[\s]+", raw_prefix) - for r in ["", ";"]: - while r in raw: raw.remove(r) - self.split = list(raw) - - for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default", "operator", "synchronized"]: - while r in raw: raw.remove(r) - - self.typ = raw[0] - self.name = raw[1] - - # parse args - self.detailed_args = [] - for arg in re.split(",\s*", raw_args): - arg = re.split("\s", arg) - # ignore annotations for now - arg = [ a for a in arg if not a.startswith("@") ] - if len(arg[0]) > 0: - self.detailed_args.append(Argument(arg[0])) - - # parse throws - self.throws = [] - for throw in re.split(",\s*", raw_throws): - self.throws.append(throw) - - self.annotations = [] - else: - raise ValueError("Unknown signature format: " + sig_format) - - self.args = map(lambda a: a.type, self.detailed_args) - self.ident = "-".join((self.typ, self.name, "-".join(self.args))) - - def sig_matches(self, typ, name, args): - return typ == self.typ and name == self.name and args == self.args - - def __hash__(self): - return hash(self.raw) - - def __repr__(self): - return self.raw - - -class Class(): - def __init__(self, pkg, line, raw, blame, sig_format = 1): - self.pkg = pkg - self.line = line - self.raw = raw.strip(" {;") - self.blame = blame - self.ctors = [] - self.fields = [] - self.methods = [] - self.annotations = [] - - if sig_format == 2: - V2LineParser(raw).parse_into_class(self) - elif sig_format == 1: - # drop generics for now; may need multiple passes - raw = re.sub("<[^<]+?>", "", raw) - raw = re.sub("<[^<]+?>", "", raw) - - raw = raw.split() - self.split = list(raw) - if "class" in raw: - self.fullname = raw[raw.index("class")+1] - elif "interface" in raw: - self.fullname = raw[raw.index("interface")+1] - elif "@interface" in raw: - self.fullname = raw[raw.index("@interface")+1] - else: - raise ValueError("Funky class type %s" % (self.raw)) - - if "extends" in raw: - self.extends = raw[raw.index("extends")+1] - else: - self.extends = None - - if "implements" in raw: - self.implements = raw[raw.index("implements")+1] - self.implements_all = [self.implements] - else: - self.implements = None - self.implements_all = [] - else: - raise ValueError("Unknown signature format: " + sig_format) - - self.fullname = self.pkg.name + "." + self.fullname - self.fullname_path = self.fullname.split(".") - - if self.extends is not None: - self.extends_path = self.extends.split(".") - else: - self.extends_path = [] - - self.name = self.fullname[self.fullname.rindex(".")+1:] - - def merge_from(self, other): - self.ctors.extend(other.ctors) - self.fields.extend(other.fields) - self.methods.extend(other.methods) - - def __hash__(self): - return hash((self.raw, tuple(self.ctors), tuple(self.fields), tuple(self.methods))) - - def __repr__(self): - return self.raw - - -class Package(): - NAME = re.compile("package(?: .*)? ([A-Za-z0-9.]+)") - - def __init__(self, line, raw, blame): - self.line = line - self.raw = raw.strip(" {;") - self.blame = blame - - self.name = Package.NAME.match(raw).group(1) - self.name_path = self.name.split(".") - - def __repr__(self): - return self.raw - -class V2Tokenizer(object): - __slots__ = ["raw"] - - SIGNATURE_PREFIX = "// Signature format: " - DELIMITER = re.compile(r'\s+|[()@<>;,={}/"!?]|\[\]|\.\.\.') - STRING_SPECIAL = re.compile(r'["\\]') - - def __init__(self, raw): - self.raw = raw - - def tokenize(self): - tokens = [] - current = 0 - raw = self.raw - length = len(raw) - - while current < length: - while current < length: - start = current - match = V2Tokenizer.DELIMITER.search(raw, start) - if match is not None: - match_start = match.start() - if match_start == current: - end = match.end() - else: - end = match_start - else: - end = length - - token = raw[start:end] - current = end - - if token == "" or token[0] == " ": - continue - else: - break - - if token == "@": - if raw[start:start+11] == "@interface ": - current = start + 11 - tokens.append("@interface") - continue - elif token == '/': - if raw[start:start+2] == "//": - current = length - continue - elif token == '"': - current, string_token = self.tokenize_string(raw, length, current) - tokens.append(token + string_token) - continue - - tokens.append(token) - - return tokens - - def tokenize_string(self, raw, length, current): - start = current - end = length - while start < end: - match = V2Tokenizer.STRING_SPECIAL.search(raw, start) - if match: - if match.group() == '"': - end = match.end() - break - elif match.group() == '\\': - # ignore whatever is after the slash - start += 2 - else: - raise ValueError("Unexpected match: `%s`" % (match.group())) - else: - raise ValueError("Unexpected EOF tokenizing string: `%s`" % (raw[current - 1:],)) - - token = raw[current:end] - return end, token - -class V2LineParser(object): - __slots__ = ["tokenized", "current", "len"] - - FIELD_KINDS = ("field", "property", "enum_constant") - MODIFIERS = set("public protected internal private abstract default static final transient volatile synchronized native operator sealed strictfp infix inline suspend vararg".split()) - JAVA_LANG_TYPES = set("AbstractMethodError AbstractStringBuilder Appendable ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException AssertionError AutoCloseable Boolean BootstrapMethodError Byte Character CharSequence Class ClassCastException ClassCircularityError ClassFormatError ClassLoader ClassNotFoundException Cloneable CloneNotSupportedException Comparable Compiler Deprecated Double Enum EnumConstantNotPresentException Error Exception ExceptionInInitializerError Float FunctionalInterface IllegalAccessError IllegalAccessException IllegalArgumentException IllegalMonitorStateException IllegalStateException IllegalThreadStateException IncompatibleClassChangeError IndexOutOfBoundsException InheritableThreadLocal InstantiationError InstantiationException Integer InternalError InterruptedException Iterable LinkageError Long Math NegativeArraySizeException NoClassDefFoundError NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException NullPointerException Number NumberFormatException Object OutOfMemoryError Override Package package-info.java Process ProcessBuilder ProcessEnvironment ProcessImpl Readable ReflectiveOperationException Runnable Runtime RuntimeException RuntimePermission SafeVarargs SecurityException SecurityManager Short StackOverflowError StackTraceElement StrictMath String StringBuffer StringBuilder StringIndexOutOfBoundsException SuppressWarnings System Thread ThreadDeath ThreadGroup ThreadLocal Throwable TypeNotPresentException UNIXProcess UnknownError UnsatisfiedLinkError UnsupportedClassVersionError UnsupportedOperationException VerifyError VirtualMachineError Void".split()) - - def __init__(self, raw): - self.tokenized = V2Tokenizer(raw).tokenize() - self.current = 0 - self.len = len(self.tokenized) - - def parse_into_method(self, method): - method.split = [] - kind = self.parse_one_of("ctor", "method") - method.split.append(kind) - method.annotations = self.parse_annotations() - method.split.extend(self.parse_modifiers()) - self.parse_matching_paren("<", ">") - if "@Deprecated" in method.annotations: - method.split.append("deprecated") - if kind == "ctor": - method.typ = "ctor" - else: - method.typ = self.parse_type() - method.split.append(method.typ) - method.name = self.parse_name() - method.split.append(method.name) - self.parse_token("(") - method.detailed_args = self.parse_args() - self.parse_token(")") - method.throws = self.parse_throws() - if "@interface" in method.clazz.split: - self.parse_annotation_default() - self.parse_token(";") - self.parse_eof() - - def parse_into_class(self, clazz): - clazz.split = [] - clazz.annotations = self.parse_annotations() - if "@Deprecated" in clazz.annotations: - clazz.split.append("deprecated") - clazz.split.extend(self.parse_modifiers()) - kind = self.parse_one_of("class", "interface", "@interface", "enum") - if kind == "enum": - # enums are implicitly final - clazz.split.append("final") - clazz.split.append(kind) - clazz.fullname = self.parse_name() - self.parse_matching_paren("<", ">") - extends = self.parse_extends() - clazz.extends = extends[0] if extends else None - clazz.implements_all = self.parse_implements() - # The checks assume that interfaces are always found in implements, which isn't true for - # subinterfaces. - if not clazz.implements_all and "interface" in clazz.split: - clazz.implements_all = [clazz.extends] - clazz.implements = clazz.implements_all[0] if clazz.implements_all else None - self.parse_token("{") - self.parse_eof() - - def parse_into_field(self, field): - kind = self.parse_one_of(*V2LineParser.FIELD_KINDS) - field.split = [kind] - field.annotations = self.parse_annotations() - if "@Deprecated" in field.annotations: - field.split.append("deprecated") - field.split.extend(self.parse_modifiers()) - field.typ = self.parse_type() - field.split.append(field.typ) - field.name = self.parse_name() - field.split.append(field.name) - if self.parse_if("="): - field.value = self.parse_value_stripped() - else: - field.value = None - - self.parse_token(";") - self.parse_eof() - - def lookahead(self): - return self.tokenized[self.current] - - def parse_one_of(self, *options): - found = self.lookahead() - if found not in options: - raise ValueError("Parsing failed, expected one of `%s` but found `%s` in %s" % (options, found, repr(self.tokenized))) - return self.parse_token() - - def parse_token(self, tok = None): - found = self.lookahead() - if tok is not None and found != tok: - raise ValueError("Parsing failed, expected `%s` but found `%s` in %s" % (tok, found, repr(self.tokenized))) - self.current += 1 - return found - - def eof(self): - return self.current == self.len - - def parse_eof(self): - if not self.eof(): - raise ValueError("Parsing failed, expected EOF, but %s has not been parsed in %s" % (self.tokenized[self.current:], self.tokenized)) - - def parse_if(self, tok): - if not self.eof() and self.lookahead() == tok: - self.parse_token() - return True - return False - - def parse_annotations(self): - ret = [] - while self.lookahead() == "@": - ret.append(self.parse_annotation()) - return ret - - def parse_annotation(self): - ret = self.parse_token("@") + self.parse_token() - self.parse_matching_paren("(", ")") - return ret - - def parse_matching_paren(self, open, close): - start = self.current - if not self.parse_if(open): - return - length = len(self.tokenized) - count = 1 - while count > 0: - if self.current == length: - raise ValueError("Unexpected EOF looking for closing paren: `%s`" % (self.tokenized[start:],)) - t = self.parse_token() - if t == open: - count += 1 - elif t == close: - count -= 1 - return self.tokenized[start:self.current] - - def parse_modifiers(self): - ret = [] - while self.lookahead() in V2LineParser.MODIFIERS: - ret.append(self.parse_token()) - return ret - - def parse_kotlin_nullability(self): - t = self.lookahead() - if t == "?" or t == "!": - return self.parse_token() - return None - - def parse_type(self): - self.parse_annotations() - type = self.parse_token() - if type[-1] == '.': - self.parse_annotations() - type += self.parse_token() - if type in V2LineParser.JAVA_LANG_TYPES: - type = "java.lang." + type - self.parse_matching_paren("<", ">") - while True: - t = self.lookahead() - if t == "@": - self.parse_annotation() - elif t == "[]": - type += self.parse_token() - elif self.parse_kotlin_nullability() is not None: - pass # discard nullability for now - else: - break - return type - - def parse_arg_type(self): - type = self.parse_type() - if self.parse_if("..."): - type += "..." - self.parse_kotlin_nullability() # discard nullability for now - return type - - def parse_name(self): - return self.parse_token() - - def parse_args(self): - args = [] - if self.lookahead() == ")": - return args - - while True: - args.append(self.parse_arg()) - if self.lookahead() == ")": - return args - self.parse_token(",") - - def parse_arg(self): - self.parse_if("vararg") # kotlin vararg - annotations = self.parse_annotations() - arg = Argument(self.parse_arg_type()) - arg.annotations = annotations - l = self.lookahead() - if l != "," and l != ")": - if self.lookahead() != '=': - arg.name = self.parse_token() # kotlin argument name - if self.parse_if('='): # kotlin default value - arg.default = self.parse_expression() - return arg - - def parse_expression(self): - while not self.lookahead() in [')', ',', ';']: - (self.parse_matching_paren('(', ')') or - self.parse_matching_paren('{', '}') or - self.parse_token()) - - def parse_throws(self): - ret = [] - if self.parse_if("throws"): - ret.append(self.parse_type()) - while self.parse_if(","): - ret.append(self.parse_type()) - return ret - - def parse_extends(self): - if self.parse_if("extends"): - return self.parse_space_delimited_type_list() - return [] - - def parse_implements(self): - if self.parse_if("implements"): - return self.parse_space_delimited_type_list() - return [] - - def parse_space_delimited_type_list(self, terminals = ["implements", "{"]): - types = [] - while True: - types.append(self.parse_type()) - if self.lookahead() in terminals: - return types - - def parse_annotation_default(self): - if self.parse_if("default"): - self.parse_expression() - - def parse_value(self): - if self.lookahead() == "{": - return " ".join(self.parse_matching_paren("{", "}")) - elif self.lookahead() == "(": - return " ".join(self.parse_matching_paren("(", ")")) - else: - return self.parse_token() - - def parse_value_stripped(self): - value = self.parse_value() - if value[0] == '"': - return value[1:-1] - return value - - -def _parse_stream(f, clazz_cb=None, base_f=None, out_classes_with_base=None, - in_classes_with_base=[]): - api = {} - in_classes_with_base = _retry_iterator(in_classes_with_base) - - if base_f: - base_classes = _retry_iterator(_parse_stream_to_generator(base_f)) - else: - base_classes = [] - - def handle_class(clazz): - if clazz_cb: - clazz_cb(clazz) - else: # In callback mode, don't keep track of the full API - api[clazz.fullname] = clazz - - def handle_missed_classes_with_base(clazz): - for c in _yield_until_matching_class(in_classes_with_base, clazz): - base_class = _skip_to_matching_class(base_classes, c) - if base_class: - handle_class(base_class) - - for clazz in _parse_stream_to_generator(f): - # Before looking at clazz, let's see if there's some classes that were not present, but - # may have an entry in the base stream. - handle_missed_classes_with_base(clazz) - - base_class = _skip_to_matching_class(base_classes, clazz) - if base_class: - clazz.merge_from(base_class) - if out_classes_with_base is not None: - out_classes_with_base.append(clazz) - handle_class(clazz) - - handle_missed_classes_with_base(None) - - return api - -def _parse_stream_to_generator(f): - line = 0 - pkg = None - clazz = None - blame = None - sig_format = 1 - - re_blame = re.compile(r"^(\^?[a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$") - - field_prefixes = map(lambda kind: " %s" % (kind,), V2LineParser.FIELD_KINDS) - def startsWithFieldPrefix(raw): - for prefix in field_prefixes: - if raw.startswith(prefix): - return True - return False - - for raw in f: - line += 1 - raw = raw.rstrip() - match = re_blame.match(raw) - if match is not None: - blame = match.groups()[0:2] - if blame[0].startswith("^"): # Outside of blame range - blame = None - raw = match.groups()[2] - else: - blame = None - - if line == 1 and V2Tokenizer.SIGNATURE_PREFIX in raw: - sig_format_string = raw[len(V2Tokenizer.SIGNATURE_PREFIX):] - if sig_format_string in ["2.0", "3.0"]: - sig_format = 2 - else: - raise ValueError("Unknown format: %s" % (sig_format_string,)) - elif raw.startswith("package"): - pkg = Package(line, raw, blame) - elif raw.startswith(" ") and raw.endswith("{"): - clazz = Class(pkg, line, raw, blame, sig_format=sig_format) - elif raw.startswith(" ctor"): - clazz.ctors.append(Method(clazz, line, raw, blame, sig_format=sig_format)) - elif raw.startswith(" method"): - clazz.methods.append(Method(clazz, line, raw, blame, sig_format=sig_format)) - elif startsWithFieldPrefix(raw): - clazz.fields.append(Field(clazz, line, raw, blame, sig_format=sig_format)) - elif raw.startswith(" }") and clazz: - yield clazz - -def _retry_iterator(it): - """Wraps an iterator, such that calling send(True) on it will redeliver the same element""" - for e in it: - while True: - retry = yield e - if not retry: - break - # send() was called, asking us to redeliver clazz on next(). Still need to yield - # a dummy value to the send() first though. - if (yield "Returning clazz on next()"): - raise TypeError("send() must be followed by next(), not send()") - -def _skip_to_matching_class(classes, needle): - """Takes a classes iterator and consumes entries until it returns the class we're looking for - - This relies on classes being sorted by package and class name.""" - - for clazz in classes: - if clazz.pkg.name < needle.pkg.name: - # We haven't reached the right package yet - continue - if clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname: - # We're in the right package, but not the right class yet - continue - if clazz.fullname == needle.fullname: - return clazz - # We ran past the right class. Send it back into the generator, then report failure. - classes.send(clazz) - return None - -def _yield_until_matching_class(classes, needle): - """Takes a class iterator and yields entries it until it reaches the class we're looking for. - - This relies on classes being sorted by package and class name.""" - - for clazz in classes: - if needle is None: - yield clazz - elif clazz.pkg.name < needle.pkg.name: - # We haven't reached the right package yet - yield clazz - elif clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname: - # We're in the right package, but not the right class yet - yield clazz - elif clazz.fullname == needle.fullname: - # Class found, abort. - return - else: - # We ran past the right class. Send it back into the iterator, then abort. - classes.send(clazz) - return - -class Failure(): - def __init__(self, sig, clazz, detail, error, rule, msg): - self.clazz = clazz - self.sig = sig - self.error = error - self.rule = rule - self.msg = msg - - if error: - self.head = "Error %s" % (rule) if rule else "Error" - dump = "%s%s:%s %s" % (format(fg=RED, bg=BLACK, bold=True), self.head, format(reset=True), msg) - else: - self.head = "Warning %s" % (rule) if rule else "Warning" - dump = "%s%s:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), self.head, format(reset=True), msg) - - self.line = clazz.line - blame = clazz.blame - if detail is not None: - dump += "\n in " + repr(detail) - self.line = detail.line - blame = detail.blame - dump += "\n in " + repr(clazz) - dump += "\n in " + repr(clazz.pkg) - dump += "\n at line " + repr(self.line) - if blame is not None: - dump += "\n last modified by %s in %s" % (blame[1], blame[0]) - - self.dump = dump - - def __repr__(self): - return self.dump - - -failures = {} - -def _fail(clazz, detail, error, rule, msg): - """Records an API failure to be processed later.""" - global failures - - sig = "%s-%s-%s" % (clazz.fullname, detail.ident if detail else None, msg) - sig = sig.replace(" deprecated ", " ") - - failures[sig] = Failure(sig, clazz, detail, error, rule, msg) - - -def warn(clazz, detail, rule, msg): - _fail(clazz, detail, False, rule, msg) - -def error(clazz, detail, rule, msg): - _fail(clazz, detail, True, rule, msg) - - -noticed = {} - -def notice(clazz): - global noticed - - noticed[clazz.fullname] = hash(clazz) - - -verifiers = {} - -def verifier(f): - verifiers[f.__name__] = f - return f - - -@verifier -def verify_constants(clazz): - """All static final constants must be FOO_NAME style.""" - if re.match("android\.R\.[a-z]+", clazz.fullname): return - if clazz.fullname.startswith("android.os.Build"): return - if clazz.fullname == "android.system.OsConstants": return - - req = ["java.lang.String","byte","short","int","long","float","double","boolean","char"] - for f in clazz.fields: - if "static" in f.split and "final" in f.split: - if re.match("[A-Z0-9_]+", f.name) is None: - error(clazz, f, "C2", "Constant field names must be FOO_NAME") - if f.typ != "java.lang.String": - if f.name.startswith("MIN_") or f.name.startswith("MAX_"): - warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods") - if f.typ in req and f.value is None: - error(clazz, f, None, "All constants must be defined at compile time") - -@verifier -def verify_enums(clazz): - """Enums are bad, mmkay?""" - if clazz.extends == "java.lang.Enum" or "enum" in clazz.split: - error(clazz, None, "F5", "Enums are not allowed") - -@verifier -def verify_class_names(clazz): - """Try catching malformed class names like myMtp or MTPUser.""" - if clazz.fullname.startswith("android.opengl"): return - if clazz.fullname.startswith("android.renderscript"): return - if re.match("android\.R\.[a-z]+", clazz.fullname): return - - if re.search("[A-Z]{2,}", clazz.name) is not None: - warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP") - if re.match("[^A-Z]", clazz.name): - error(clazz, None, "S1", "Class must start with uppercase char") - if clazz.name.endswith("Impl"): - error(clazz, None, None, "Don't expose your implementation details") - - -@verifier -def verify_method_names(clazz): - """Try catching malformed method names, like Foo() or getMTU().""" - if clazz.fullname.startswith("android.opengl"): return - if clazz.fullname.startswith("android.renderscript"): return - if clazz.fullname == "android.system.OsConstants": return - - for m in clazz.methods: - if re.search("[A-Z]{2,}", m.name) is not None: - warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()") - if re.match("[^a-z]", m.name): - error(clazz, m, "S1", "Method name must start with lowercase char") - - -@verifier -def verify_callbacks(clazz): - """Verify Callback classes. - All methods must follow onFoo() naming style.""" - if clazz.fullname == "android.speech.tts.SynthesisCallback": return - - if clazz.name.endswith("Callbacks"): - error(clazz, None, "L1", "Callback class names should be singular") - if clazz.name.endswith("Observer"): - warn(clazz, None, "L1", "Class should be named FooCallback") - - if clazz.name.endswith("Callback"): - for m in clazz.methods: - if not re.match("on[A-Z][a-z]*", m.name): - error(clazz, m, "L1", "Callback method names must be onFoo() style") - - -@verifier -def verify_listeners(clazz): - """Verify Listener classes. - All Listener classes must be interface. - All methods must follow onFoo() naming style. - If only a single method, it must match class name: - interface OnFooListener { void onFoo() }""" - - if clazz.name.endswith("Listener"): - if "abstract" in clazz.split and "class" in clazz.split: - error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback") - - for m in clazz.methods: - if not re.match("on[A-Z][a-z]*", m.name): - error(clazz, m, "L1", "Listener method names must be onFoo() style") - - if len(clazz.methods) == 1 and clazz.name.startswith("On"): - m = clazz.methods[0] - if (m.name + "Listener").lower() != clazz.name.lower(): - error(clazz, m, "L1", "Single listener method name must match class name") - - -@verifier -def verify_actions(clazz): - """Verify intent actions. - All action names must be named ACTION_FOO. - All action values must be scoped by package and match name: - package android.foo { - String ACTION_BAR = "android.foo.action.BAR"; - }""" - for f in clazz.fields: - if f.value is None: continue - if f.name.startswith("EXTRA_"): continue - if f.name == "SERVICE_INTERFACE" or f.name == "PROVIDER_INTERFACE": continue - if "INTERACTION" in f.name: continue - - if "static" in f.split and "final" in f.split and f.typ == "java.lang.String": - if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower(): - if not f.name.startswith("ACTION_"): - error(clazz, f, "C3", "Intent action constant name must be ACTION_FOO") - else: - if clazz.fullname == "android.content.Intent": - prefix = "android.intent.action" - elif clazz.fullname == "android.provider.Settings": - prefix = "android.settings" - elif clazz.fullname == "android.app.admin.DevicePolicyManager" or clazz.fullname == "android.app.admin.DeviceAdminReceiver": - prefix = "android.app.action" - else: - prefix = clazz.pkg.name + ".action" - expected = prefix + "." + f.name[7:] - if f.value != expected: - error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected)) - - -@verifier -def verify_extras(clazz): - """Verify intent extras. - All extra names must be named EXTRA_FOO. - All extra values must be scoped by package and match name: - package android.foo { - String EXTRA_BAR = "android.foo.extra.BAR"; - }""" - if clazz.fullname == "android.app.Notification": return - if clazz.fullname == "android.appwidget.AppWidgetManager": return - - for f in clazz.fields: - if f.value is None: continue - if f.name.startswith("ACTION_"): continue - - if "static" in f.split and "final" in f.split and f.typ == "java.lang.String": - if "_EXTRA" in f.name or "EXTRA_" in f.name or ".extra" in f.value.lower(): - if not f.name.startswith("EXTRA_"): - error(clazz, f, "C3", "Intent extra must be EXTRA_FOO") - else: - if clazz.pkg.name == "android.content" and clazz.name == "Intent": - prefix = "android.intent.extra" - elif clazz.pkg.name == "android.app.admin": - prefix = "android.app.extra" - else: - prefix = clazz.pkg.name + ".extra" - expected = prefix + "." + f.name[6:] - if f.value != expected: - error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected)) - - -@verifier -def verify_equals(clazz): - """Verify that equals() and hashCode() must be overridden together.""" - eq = False - hc = False - for m in clazz.methods: - if "static" in m.split: continue - if m.sig_matches("boolean", "equals", ["java.lang.Object"]): eq = True - if m.sig_matches("int", "hashCode", []): hc = True - if eq != hc: - error(clazz, None, "M8", "Must override both equals and hashCode; missing one") - - -@verifier -def verify_parcelable(clazz): - """Verify that Parcelable objects aren't hiding required bits.""" - if clazz.implements == "android.os.Parcelable": - creator = [ i for i in clazz.fields if i.name == "CREATOR" ] - write = [ i for i in clazz.methods if i.name == "writeToParcel" ] - describe = [ i for i in clazz.methods if i.name == "describeContents" ] - - if len(creator) == 0 or len(write) == 0 or len(describe) == 0: - error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one") - - if "final" not in clazz.split: - error(clazz, None, "FW8", "Parcelable classes must be final") - - for c in clazz.ctors: - if c.args == ["android.os.Parcel"]: - error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors") - - -@verifier -def verify_protected(clazz): - """Verify that no protected methods or fields are allowed.""" - for m in clazz.methods: - if m.name == "finalize": continue - if "protected" in m.split: - error(clazz, m, "M7", "Protected methods not allowed; must be public") - for f in clazz.fields: - if "protected" in f.split: - error(clazz, f, "M7", "Protected fields not allowed; must be public") - - -@verifier -def verify_fields(clazz): - """Verify that all exposed fields are final. - Exposed fields must follow myName style. - Catch internal mFoo objects being exposed.""" - - IGNORE_BARE_FIELDS = [ - "android.app.ActivityManager.RecentTaskInfo", - "android.app.Notification", - "android.content.pm.ActivityInfo", - "android.content.pm.ApplicationInfo", - "android.content.pm.ComponentInfo", - "android.content.pm.ResolveInfo", - "android.content.pm.FeatureGroupInfo", - "android.content.pm.InstrumentationInfo", - "android.content.pm.PackageInfo", - "android.content.pm.PackageItemInfo", - "android.content.res.Configuration", - "android.graphics.BitmapFactory.Options", - "android.os.Message", - "android.system.StructPollfd", - ] - - for f in clazz.fields: - if not "final" in f.split: - if clazz.fullname in IGNORE_BARE_FIELDS: - pass - elif clazz.fullname.endswith("LayoutParams"): - pass - elif clazz.fullname.startswith("android.util.Mutable"): - pass - else: - error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable") - - if "static" not in f.split and "property" not in f.split: - if not re.match("[a-z]([a-zA-Z]+)?", f.name): - error(clazz, f, "S1", "Non-static fields must be named using myField style") - - if re.match("[ms][A-Z]", f.name): - error(clazz, f, "F1", "Internal objects must not be exposed") - - if re.match("[A-Z_]+", f.name): - if "static" not in f.split or "final" not in f.split: - error(clazz, f, "C2", "Constants must be marked static final") - - -@verifier -def verify_register(clazz): - """Verify parity of registration methods. - Callback objects use register/unregister methods. - Listener objects use add/remove methods.""" - methods = [ m.name for m in clazz.methods ] - for m in clazz.methods: - if "Callback" in m.raw: - if m.name.startswith("register"): - other = "unregister" + m.name[8:] - if other not in methods: - error(clazz, m, "L2", "Missing unregister method") - if m.name.startswith("unregister"): - other = "register" + m.name[10:] - if other not in methods: - error(clazz, m, "L2", "Missing register method") - - if m.name.startswith("add") or m.name.startswith("remove"): - error(clazz, m, "L3", "Callback methods should be named register/unregister") - - if "Listener" in m.raw: - if m.name.startswith("add"): - other = "remove" + m.name[3:] - if other not in methods: - error(clazz, m, "L2", "Missing remove method") - if m.name.startswith("remove") and not m.name.startswith("removeAll"): - other = "add" + m.name[6:] - if other not in methods: - error(clazz, m, "L2", "Missing add method") - - if m.name.startswith("register") or m.name.startswith("unregister"): - error(clazz, m, "L3", "Listener methods should be named add/remove") - - -@verifier -def verify_sync(clazz): - """Verify synchronized methods aren't exposed.""" - for m in clazz.methods: - if "synchronized" in m.split: - error(clazz, m, "M5", "Internal locks must not be exposed") - - -@verifier -def verify_intent_builder(clazz): - """Verify that Intent builders are createFooIntent() style.""" - if clazz.name == "Intent": return - - for m in clazz.methods: - if m.typ == "android.content.Intent": - if m.name.startswith("create") and m.name.endswith("Intent"): - pass - else: - warn(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()") - - -@verifier -def verify_helper_classes(clazz): - """Verify that helper classes are named consistently with what they extend. - All developer extendable methods should be named onFoo().""" - test_methods = False - if clazz.extends == "android.app.Service": - test_methods = True - if not clazz.name.endswith("Service"): - error(clazz, None, "CL4", "Inconsistent class name; should be FooService") - - found = False - for f in clazz.fields: - if f.name == "SERVICE_INTERFACE": - found = True - if f.value != clazz.fullname: - error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname)) - - if clazz.extends == "android.content.ContentProvider": - test_methods = True - if not clazz.name.endswith("Provider"): - error(clazz, None, "CL4", "Inconsistent class name; should be FooProvider") - - found = False - for f in clazz.fields: - if f.name == "PROVIDER_INTERFACE": - found = True - if f.value != clazz.fullname: - error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname)) - - if clazz.extends == "android.content.BroadcastReceiver": - test_methods = True - if not clazz.name.endswith("Receiver"): - error(clazz, None, "CL4", "Inconsistent class name; should be FooReceiver") - - if clazz.extends == "android.app.Activity": - test_methods = True - if not clazz.name.endswith("Activity"): - error(clazz, None, "CL4", "Inconsistent class name; should be FooActivity") - - if test_methods: - for m in clazz.methods: - if "final" in m.split: continue - if not re.match("on[A-Z]", m.name): - if "abstract" in m.split: - warn(clazz, m, None, "Methods implemented by developers should be named onFoo()") - else: - warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final") - - -@verifier -def verify_builder(clazz): - """Verify builder classes. - Methods should return the builder to enable chaining.""" - if clazz.extends: return - if not clazz.name.endswith("Builder"): return - - if clazz.name != "Builder": - warn(clazz, None, None, "Builder should be defined as inner class") - - has_build = False - for m in clazz.methods: - if m.name == "build": - has_build = True - continue - - if m.name.startswith("get"): continue - if m.name.startswith("clear"): continue - - if m.name.startswith("with"): - warn(clazz, m, None, "Builder methods names should use setFoo() style") - - if m.name.startswith("set"): - if not m.typ.endswith(clazz.fullname): - warn(clazz, m, "M4", "Methods must return the builder object") - - if not has_build: - warn(clazz, None, None, "Missing build() method") - - if "final" not in clazz.split: - error(clazz, None, None, "Builder should be final") - - -@verifier -def verify_aidl(clazz): - """Catch people exposing raw AIDL.""" - if clazz.extends == "android.os.Binder" or clazz.implements == "android.os.IInterface": - error(clazz, None, None, "Raw AIDL interfaces must not be exposed") - - -@verifier -def verify_internal(clazz): - """Catch people exposing internal classes.""" - if clazz.pkg.name.startswith("com.android"): - error(clazz, None, None, "Internal classes must not be exposed") - -def layering_build_ranking(ranking_list): - r = {} - for rank, ps in enumerate(ranking_list): - if not isinstance(ps, list): - ps = [ps] - for p in ps: - rs = r - for n in p.split('.'): - if n not in rs: - rs[n] = {} - rs = rs[n] - rs['-rank'] = rank - return r - -LAYERING_PACKAGE_RANKING = layering_build_ranking([ - ["android.service","android.accessibilityservice","android.inputmethodservice","android.printservice","android.appwidget","android.webkit","android.preference","android.gesture","android.print"], - "android.app", - "android.widget", - "android.view", - "android.animation", - "android.provider", - ["android.content","android.graphics.drawable"], - "android.database", - "android.text", - "android.graphics", - "android.os", - "android.util" -]) - -@verifier -def verify_layering(clazz): - """Catch package layering violations. - For example, something in android.os depending on android.app.""" - - def rank(p): - r = None - l = LAYERING_PACKAGE_RANKING - for n in p.split('.'): - if n in l: - l = l[n] - if '-rank' in l: - r = l['-rank'] - else: - break - return r - - cr = rank(clazz.pkg.name) - if cr is None: return - - for f in clazz.fields: - ir = rank(f.typ) - if ir is not None and ir < cr: - warn(clazz, f, "FW6", "Field type violates package layering") - - for m in itertools.chain(clazz.methods, clazz.ctors): - ir = rank(m.typ) - if ir is not None and ir < cr: - warn(clazz, m, "FW6", "Method return type violates package layering") - for arg in m.args: - ir = rank(arg) - if ir is not None and ir < cr: - warn(clazz, m, "FW6", "Method argument type violates package layering") - - -@verifier -def verify_boolean(clazz): - """Verifies that boolean accessors are named correctly. - For example, hasFoo() and setHasFoo().""" - - def is_get(m): return len(m.args) == 0 and m.typ == "boolean" - def is_set(m): return len(m.args) == 1 and m.args[0] == "boolean" - - gets = [ m for m in clazz.methods if is_get(m) ] - sets = [ m for m in clazz.methods if is_set(m) ] - - def error_if_exists(methods, trigger, expected, actual): - for m in methods: - if m.name == actual: - error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected)) - - for m in clazz.methods: - if is_get(m): - if re.match("is[A-Z]", m.name): - target = m.name[2:] - expected = "setIs" + target - error_if_exists(sets, m.name, expected, "setHas" + target) - elif re.match("has[A-Z]", m.name): - target = m.name[3:] - expected = "setHas" + target - error_if_exists(sets, m.name, expected, "setIs" + target) - error_if_exists(sets, m.name, expected, "set" + target) - elif re.match("get[A-Z]", m.name): - target = m.name[3:] - expected = "set" + target - error_if_exists(sets, m.name, expected, "setIs" + target) - error_if_exists(sets, m.name, expected, "setHas" + target) - - if is_set(m): - if re.match("set[A-Z]", m.name): - target = m.name[3:] - expected = "get" + target - error_if_exists(sets, m.name, expected, "is" + target) - error_if_exists(sets, m.name, expected, "has" + target) - - -@verifier -def verify_collections(clazz): - """Verifies that collection types are interfaces.""" - if clazz.fullname == "android.os.Bundle": return - if clazz.fullname == "android.os.Parcel": return - - bad = ["java.util.Vector", "java.util.LinkedList", "java.util.ArrayList", "java.util.Stack", - "java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"] - for m in clazz.methods: - if m.typ in bad: - error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface") - for arg in m.args: - if arg in bad: - error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface") - - -@verifier -def verify_uris(clazz): - bad = ["java.net.URL", "java.net.URI", "android.net.URL"] - - for f in clazz.fields: - if f.typ in bad: - error(clazz, f, None, "Field must be android.net.Uri instead of " + f.typ) - - for m in clazz.methods + clazz.ctors: - if m.typ in bad: - error(clazz, m, None, "Must return android.net.Uri instead of " + m.typ) - for arg in m.args: - if arg in bad: - error(clazz, m, None, "Argument must take android.net.Uri instead of " + arg) - - -@verifier -def verify_flags(clazz): - """Verifies that flags are non-overlapping.""" - known = collections.defaultdict(int) - for f in clazz.fields: - if "FLAG_" in f.name: - try: - val = int(f.value) - except: - continue - - scope = f.name[0:f.name.index("FLAG_")] - if val & known[scope]: - warn(clazz, f, "C1", "Found overlapping flag constant value") - known[scope] |= val - - -@verifier -def verify_exception(clazz): - """Verifies that methods don't throw generic exceptions.""" - for m in clazz.methods: - for t in m.throws: - if t in ["java.lang.Exception", "java.lang.Throwable", "java.lang.Error"]: - error(clazz, m, "S1", "Methods must not throw generic exceptions") - - if t in ["android.os.RemoteException"]: - if clazz.fullname == "android.content.ContentProviderClient": continue - if clazz.fullname == "android.os.Binder": continue - if clazz.fullname == "android.os.IBinder": continue - - error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException") - - if len(m.args) == 0 and t in ["java.lang.IllegalArgumentException", "java.lang.NullPointerException"]: - warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException") - - -GOOGLE_IGNORECASE = re.compile("google", re.IGNORECASE) - -# Not marked as @verifier, because it is only conditionally applied. -def verify_google(clazz): - """Verifies that APIs never reference Google.""" - - if GOOGLE_IGNORECASE.search(clazz.raw) is not None: - error(clazz, None, None, "Must never reference Google") - - for test in clazz.ctors, clazz.fields, clazz.methods: - for t in test: - if GOOGLE_IGNORECASE.search(t.raw) is not None: - error(clazz, t, None, "Must never reference Google") - - -@verifier -def verify_bitset(clazz): - """Verifies that we avoid using heavy BitSet.""" - - for f in clazz.fields: - if f.typ == "java.util.BitSet": - error(clazz, f, None, "Field type must not be heavy BitSet") - - for m in clazz.methods: - if m.typ == "java.util.BitSet": - error(clazz, m, None, "Return type must not be heavy BitSet") - for arg in m.args: - if arg == "java.util.BitSet": - error(clazz, m, None, "Argument type must not be heavy BitSet") - - -@verifier -def verify_manager(clazz): - """Verifies that FooManager is only obtained from Context.""" - - if not clazz.name.endswith("Manager"): return - - for c in clazz.ctors: - error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors") - - for m in clazz.methods: - if m.typ == clazz.fullname: - error(clazz, m, None, "Managers must always be obtained from Context") - - -@verifier -def verify_boxed(clazz): - """Verifies that methods avoid boxed primitives.""" - - boxed = ["java.lang.Number","java.lang.Byte","java.lang.Double","java.lang.Float","java.lang.Integer","java.lang.Long","java.lang.Short"] - - for c in clazz.ctors: - for arg in c.args: - if arg in boxed: - error(clazz, c, "M11", "Must avoid boxed primitives") - - for f in clazz.fields: - if f.typ in boxed: - error(clazz, f, "M11", "Must avoid boxed primitives") - - for m in clazz.methods: - if m.typ in boxed: - error(clazz, m, "M11", "Must avoid boxed primitives") - for arg in m.args: - if arg in boxed: - error(clazz, m, "M11", "Must avoid boxed primitives") - - -@verifier -def verify_static_utils(clazz): - """Verifies that helper classes can't be constructed.""" - if clazz.fullname.startswith("android.opengl"): return - if clazz.fullname.startswith("android.R"): return - - # Only care about classes with default constructors - if len(clazz.ctors) == 1 and len(clazz.ctors[0].args) == 0: - test = [] - test.extend(clazz.fields) - test.extend(clazz.methods) - - if len(test) == 0: return - for t in test: - if "static" not in t.split: - return - - error(clazz, None, None, "Fully-static utility classes must not have constructor") - - -# @verifier # Disabled for now -def verify_overload_args(clazz): - """Verifies that method overloads add new arguments at the end.""" - if clazz.fullname.startswith("android.opengl"): return - - overloads = collections.defaultdict(list) - for m in clazz.methods: - if "deprecated" in m.split: continue - overloads[m.name].append(m) - - for name, methods in overloads.items(): - if len(methods) <= 1: continue - - # Look for arguments common across all overloads - def cluster(args): - count = collections.defaultdict(int) - res = set() - for i in range(len(args)): - a = args[i] - res.add("%s#%d" % (a, count[a])) - count[a] += 1 - return res - - common_args = cluster(methods[0].args) - for m in methods: - common_args = common_args & cluster(m.args) - - if len(common_args) == 0: continue - - # Require that all common arguments are present at start of signature - locked_sig = None - for m in methods: - sig = m.args[0:len(common_args)] - if not common_args.issubset(cluster(sig)): - warn(clazz, m, "M2", "Expected common arguments [%s] at beginning of overloaded method" % (", ".join(common_args))) - elif not locked_sig: - locked_sig = sig - elif locked_sig != sig: - error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig))) - - -@verifier -def verify_callback_handlers(clazz): - """Verifies that methods adding listener/callback have overload - for specifying delivery thread.""" - - # Ignore UI packages which assume main thread - skip = [ - "animation", - "view", - "graphics", - "transition", - "widget", - "webkit", - ] - for s in skip: - if s in clazz.pkg.name_path: return - if s in clazz.extends_path: return - - # Ignore UI classes which assume main thread - if "app" in clazz.pkg.name_path or "app" in clazz.extends_path: - for s in ["ActionBar","Dialog","Application","Activity","Fragment","Loader"]: - if s in clazz.fullname: return - if "content" in clazz.pkg.name_path or "content" in clazz.extends_path: - for s in ["Loader"]: - if s in clazz.fullname: return - - found = {} - by_name = collections.defaultdict(list) - examine = clazz.ctors + clazz.methods - for m in examine: - if m.name.startswith("unregister"): continue - if m.name.startswith("remove"): continue - if re.match("on[A-Z]+", m.name): continue - - by_name[m.name].append(m) - - for a in m.args: - if a.endswith("Listener") or a.endswith("Callback") or a.endswith("Callbacks"): - found[m.name] = m - - for f in found.values(): - takes_handler = False - takes_exec = False - for m in by_name[f.name]: - if "android.os.Handler" in m.args: - takes_handler = True - if "java.util.concurrent.Executor" in m.args: - takes_exec = True - if not takes_exec: - warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Executor") - - -@verifier -def verify_context_first(clazz): - """Verifies that methods accepting a Context keep it the first argument.""" - examine = clazz.ctors + clazz.methods - for m in examine: - if len(m.args) > 1 and m.args[0] != "android.content.Context": - if "android.content.Context" in m.args[1:]: - error(clazz, m, "M3", "Context is distinct, so it must be the first argument") - if len(m.args) > 1 and m.args[0] != "android.content.ContentResolver": - if "android.content.ContentResolver" in m.args[1:]: - error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument") - - -@verifier -def verify_listener_last(clazz): - """Verifies that methods accepting a Listener or Callback keep them as last arguments.""" - examine = clazz.ctors + clazz.methods - for m in examine: - if "Listener" in m.name or "Callback" in m.name: continue - found = False - for a in m.args: - if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"): - found = True - elif found: - warn(clazz, m, "M3", "Listeners should always be at end of argument list") - - -@verifier -def verify_resource_names(clazz): - """Verifies that resource names have consistent case.""" - if not re.match("android\.R\.[a-z]+", clazz.fullname): return - - # Resources defined by files are foo_bar_baz - if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]: - for f in clazz.fields: - if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue - if f.name.startswith("config_"): - error(clazz, f, None, "Expected config name to be config_fooBarBaz style") - - if re.match("[a-z1-9_]+$", f.name): continue - error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style") - - # Resources defined inside files are fooBarBaz - if clazz.name in ["array","attr","id","bool","fraction","integer"]: - for f in clazz.fields: - if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue - if re.match("layout_[a-z][a-zA-Z1-9]*$", f.name): continue - if re.match("state_[a-z_]*$", f.name): continue - - if re.match("[a-z][a-zA-Z1-9]*$", f.name): continue - error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style") - - # Styles are FooBar_Baz - if clazz.name in ["style"]: - for f in clazz.fields: - if re.match("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*$", f.name): continue - error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style") - - -@verifier -def verify_files(clazz): - """Verifies that methods accepting File also accept streams.""" - - has_file = set() - has_stream = set() - - test = [] - test.extend(clazz.ctors) - test.extend(clazz.methods) - - for m in test: - if "java.io.File" in m.args: - has_file.add(m) - if "java.io.FileDescriptor" in m.args or "android.os.ParcelFileDescriptor" in m.args or "java.io.InputStream" in m.args or "java.io.OutputStream" in m.args: - has_stream.add(m.name) - - for m in has_file: - if m.name not in has_stream: - warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams") - - -@verifier -def verify_manager_list(clazz): - """Verifies that managers return List<? extends Parcelable> instead of arrays.""" - - if not clazz.name.endswith("Manager"): return - - for m in clazz.methods: - if m.typ.startswith("android.") and m.typ.endswith("[]"): - warn(clazz, m, None, "Methods should return List<? extends Parcelable> instead of Parcelable[] to support ParceledListSlice under the hood") - - -@verifier -def verify_abstract_inner(clazz): - """Verifies that abstract inner classes are static.""" - - if re.match(".+?\.[A-Z][^\.]+\.[A-Z]", clazz.fullname): - if "abstract" in clazz.split and "static" not in clazz.split: - warn(clazz, None, None, "Abstract inner classes should be static to improve testability") - - -@verifier -def verify_runtime_exceptions(clazz): - """Verifies that runtime exceptions aren't listed in throws.""" - - banned = [ - "java.lang.NullPointerException", - "java.lang.ClassCastException", - "java.lang.IndexOutOfBoundsException", - "java.lang.reflect.UndeclaredThrowableException", - "java.lang.reflect.MalformedParametersException", - "java.lang.reflect.MalformedParameterizedTypeException", - "java.lang.invoke.WrongMethodTypeException", - "java.lang.EnumConstantNotPresentException", - "java.lang.IllegalMonitorStateException", - "java.lang.SecurityException", - "java.lang.UnsupportedOperationException", - "java.lang.annotation.AnnotationTypeMismatchException", - "java.lang.annotation.IncompleteAnnotationException", - "java.lang.TypeNotPresentException", - "java.lang.IllegalStateException", - "java.lang.ArithmeticException", - "java.lang.IllegalArgumentException", - "java.lang.ArrayStoreException", - "java.lang.NegativeArraySizeException", - "java.util.MissingResourceException", - "java.util.EmptyStackException", - "java.util.concurrent.CompletionException", - "java.util.concurrent.RejectedExecutionException", - "java.util.IllformedLocaleException", - "java.util.ConcurrentModificationException", - "java.util.NoSuchElementException", - "java.io.UncheckedIOException", - "java.time.DateTimeException", - "java.security.ProviderException", - "java.nio.BufferUnderflowException", - "java.nio.BufferOverflowException", - ] - - examine = clazz.ctors + clazz.methods - for m in examine: - for t in m.throws: - if t in banned: - error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses") - - -@verifier -def verify_error(clazz): - """Verifies that we always use Exception instead of Error.""" - if not clazz.extends: return - if clazz.extends.endswith("Error"): - error(clazz, None, None, "Trouble must be reported through an Exception, not Error") - if clazz.extends.endswith("Exception") and not clazz.name.endswith("Exception"): - error(clazz, None, None, "Exceptions must be named FooException") - - -@verifier -def verify_units(clazz): - """Verifies that we use consistent naming for units.""" - - # If we find K, recommend replacing with V - bad = { - "Ns": "Nanos", - "Ms": "Millis or Micros", - "Sec": "Seconds", "Secs": "Seconds", - "Hr": "Hours", "Hrs": "Hours", - "Mo": "Months", "Mos": "Months", - "Yr": "Years", "Yrs": "Years", - "Byte": "Bytes", "Space": "Bytes", - } - - for m in clazz.methods: - if m.typ not in ["short","int","long"]: continue - for k, v in bad.iteritems(): - if m.name.endswith(k): - error(clazz, m, None, "Expected method name units to be " + v) - if m.name.endswith("Nanos") or m.name.endswith("Micros"): - warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision") - if m.name.endswith("Seconds"): - error(clazz, m, None, "Returned time values must be in milliseconds") - - for m in clazz.methods: - typ = m.typ - if typ == "void": - if len(m.args) != 1: continue - typ = m.args[0] - - if m.name.endswith("Fraction") and typ != "float": - error(clazz, m, None, "Fractions must use floats") - if m.name.endswith("Percentage") and typ != "int": - error(clazz, m, None, "Percentage must use ints") - - -@verifier -def verify_closable(clazz): - """Verifies that classes are AutoClosable.""" - if "java.lang.AutoCloseable" in clazz.implements_all: return - if "java.io.Closeable" in clazz.implements_all: return - - for m in clazz.methods: - if len(m.args) > 0: continue - if m.name in ["close","release","destroy","finish","finalize","disconnect","shutdown","stop","free","quit"]: - warn(clazz, m, None, "Classes that release resources should implement AutoClosable and CloseGuard") - return - - -@verifier -def verify_member_name_not_kotlin_keyword(clazz): - """Prevent method names which are keywords in Kotlin.""" - - # https://kotlinlang.org/docs/reference/keyword-reference.html#hard-keywords - # This list does not include Java keywords as those are already impossible to use. - keywords = [ - 'as', - 'fun', - 'in', - 'is', - 'object', - 'typealias', - 'val', - 'var', - 'when', - ] - - for m in clazz.methods: - if m.name in keywords: - error(clazz, m, None, "Method name must not be a Kotlin keyword") - for f in clazz.fields: - if f.name in keywords: - error(clazz, f, None, "Field name must not be a Kotlin keyword") - - -@verifier -def verify_method_name_not_kotlin_operator(clazz): - """Warn about method names which become operators in Kotlin.""" - - binary = set() - - def unique_binary_op(m, op): - if op in binary: - error(clazz, m, None, "Only one of '{0}' and '{0}Assign' methods should be present for Kotlin".format(op)) - binary.add(op) - - for m in clazz.methods: - if 'static' in m.split or 'operator' in m.split: - continue - - # https://kotlinlang.org/docs/reference/operator-overloading.html#unary-prefix-operators - if m.name in ['unaryPlus', 'unaryMinus', 'not'] and len(m.args) == 0: - warn(clazz, m, None, "Method can be invoked as a unary operator from Kotlin") - - # https://kotlinlang.org/docs/reference/operator-overloading.html#increments-and-decrements - if m.name in ['inc', 'dec'] and len(m.args) == 0 and m.typ != 'void': - # This only applies if the return type is the same or a subtype of the enclosing class, but we have no - # practical way of checking that relationship here. - warn(clazz, m, None, "Method can be invoked as a pre/postfix inc/decrement operator from Kotlin") - - # https://kotlinlang.org/docs/reference/operator-overloading.html#arithmetic - if m.name in ['plus', 'minus', 'times', 'div', 'rem', 'mod', 'rangeTo'] and len(m.args) == 1: - warn(clazz, m, None, "Method can be invoked as a binary operator from Kotlin") - unique_binary_op(m, m.name) - - # https://kotlinlang.org/docs/reference/operator-overloading.html#in - if m.name == 'contains' and len(m.args) == 1 and m.typ == 'boolean': - warn(clazz, m, None, "Method can be invoked as a 'in' operator from Kotlin") - - # https://kotlinlang.org/docs/reference/operator-overloading.html#indexed - if (m.name == 'get' and len(m.args) > 0) or (m.name == 'set' and len(m.args) > 1): - warn(clazz, m, None, "Method can be invoked with an indexing operator from Kotlin") - - # https://kotlinlang.org/docs/reference/operator-overloading.html#invoke - if m.name == 'invoke': - warn(clazz, m, None, "Method can be invoked with function call syntax from Kotlin") - - # https://kotlinlang.org/docs/reference/operator-overloading.html#assignments - if m.name in ['plusAssign', 'minusAssign', 'timesAssign', 'divAssign', 'remAssign', 'modAssign'] \ - and len(m.args) == 1 \ - and m.typ == 'void': - warn(clazz, m, None, "Method can be invoked as a compound assignment operator from Kotlin") - unique_binary_op(m, m.name[:-6]) # Remove 'Assign' suffix - - -@verifier -def verify_collections_over_arrays(clazz): - """Warn that [] should be Collections.""" - - if "@interface" in clazz.split: - return - - safe = ["java.lang.String[]","byte[]","short[]","int[]","long[]","float[]","double[]","boolean[]","char[]"] - for m in clazz.methods: - if m.typ.endswith("[]") and m.typ not in safe: - warn(clazz, m, None, "Method should return Collection<> (or subclass) instead of raw array") - for arg in m.args: - if arg.endswith("[]") and arg not in safe: - warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array") - - -@verifier -def verify_user_handle(clazz): - """Methods taking UserHandle should be ForUser or AsUser.""" - if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return - if clazz.fullname == "android.app.admin.DeviceAdminReceiver": return - if clazz.fullname == "android.content.pm.LauncherApps": return - if clazz.fullname == "android.os.UserHandle": return - if clazz.fullname == "android.os.UserManager": return - - for m in clazz.methods: - if re.match("on[A-Z]+", m.name): continue - - has_arg = "android.os.UserHandle" in m.args - has_name = m.name.endswith("AsUser") or m.name.endswith("ForUser") - - if clazz.fullname.endswith("Manager") and has_arg: - warn(clazz, m, None, "When a method overload is needed to target a specific " - "UserHandle, callers should be directed to use " - "Context.createPackageContextAsUser() and re-obtain the relevant " - "Manager, and no new API should be added") - elif has_arg and not has_name: - warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' " - "or 'queryFooForUser'") - - -@verifier -def verify_params(clazz): - """Parameter classes should be 'Params'.""" - if clazz.name.endswith("Params"): return - if clazz.fullname == "android.app.ActivityOptions": return - if clazz.fullname == "android.app.BroadcastOptions": return - if clazz.fullname == "android.os.Bundle": return - if clazz.fullname == "android.os.BaseBundle": return - if clazz.fullname == "android.os.PersistableBundle": return - - bad = ["Param","Parameter","Parameters","Args","Arg","Argument","Arguments","Options","Bundle"] - for b in bad: - if clazz.name.endswith(b): - error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'") - - -@verifier -def verify_services(clazz): - """Service name should be FOO_BAR_SERVICE = 'foo_bar'.""" - if clazz.fullname != "android.content.Context": return - - for f in clazz.fields: - if f.typ != "java.lang.String": continue - found = re.match(r"([A-Z_]+)_SERVICE", f.name) - if found: - expected = found.group(1).lower() - if f.value != expected: - error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected)) - - -@verifier -def verify_tense(clazz): - """Verify tenses of method names.""" - if clazz.fullname.startswith("android.opengl"): return - - for m in clazz.methods: - if m.name.endswith("Enable"): - warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'") - - -@verifier -def verify_icu(clazz): - """Verifies that richer ICU replacements are used.""" - better = { - "java.util.TimeZone": "android.icu.util.TimeZone", - "java.util.Calendar": "android.icu.util.Calendar", - "java.util.Locale": "android.icu.util.ULocale", - "java.util.ResourceBundle": "android.icu.util.UResourceBundle", - "java.util.SimpleTimeZone": "android.icu.util.SimpleTimeZone", - "java.util.StringTokenizer": "android.icu.util.StringTokenizer", - "java.util.GregorianCalendar": "android.icu.util.GregorianCalendar", - "java.lang.Character": "android.icu.lang.UCharacter", - "java.text.BreakIterator": "android.icu.text.BreakIterator", - "java.text.Collator": "android.icu.text.Collator", - "java.text.DecimalFormatSymbols": "android.icu.text.DecimalFormatSymbols", - "java.text.NumberFormat": "android.icu.text.NumberFormat", - "java.text.DateFormatSymbols": "android.icu.text.DateFormatSymbols", - "java.text.DateFormat": "android.icu.text.DateFormat", - "java.text.SimpleDateFormat": "android.icu.text.SimpleDateFormat", - "java.text.MessageFormat": "android.icu.text.MessageFormat", - "java.text.DecimalFormat": "android.icu.text.DecimalFormat", - } - - for m in clazz.ctors + clazz.methods: - types = [] - types.extend(m.typ) - types.extend(m.args) - for arg in types: - if arg in better: - warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg])) - - -@verifier -def verify_clone(clazz): - """Verify that clone() isn't implemented; see EJ page 61.""" - for m in clazz.methods: - if m.name == "clone": - error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()") - - -@verifier -def verify_pfd(clazz): - """Verify that android APIs use PFD over FD.""" - if clazz.fullname == "android.os.FileUtils" or clazz.fullname == "android.system.Os": - return - - examine = clazz.ctors + clazz.methods - for m in examine: - if m.typ == "java.io.FileDescriptor": - error(clazz, m, "FW11", "Must use ParcelFileDescriptor") - if m.typ == "int": - if "Fd" in m.name or "FD" in m.name or "FileDescriptor" in m.name: - error(clazz, m, "FW11", "Must use ParcelFileDescriptor") - for arg in m.args: - if arg == "java.io.FileDescriptor": - error(clazz, m, "FW11", "Must use ParcelFileDescriptor") - - for f in clazz.fields: - if f.typ == "java.io.FileDescriptor": - error(clazz, f, "FW11", "Must use ParcelFileDescriptor") - - -@verifier -def verify_numbers(clazz): - """Discourage small numbers types like short and byte.""" - - discouraged = ["short","byte"] - - for c in clazz.ctors: - for arg in c.args: - if arg in discouraged: - warn(clazz, c, "FW12", "Should avoid odd sized primitives; use int instead") - - for f in clazz.fields: - if f.typ in discouraged: - warn(clazz, f, "FW12", "Should avoid odd sized primitives; use int instead") - - for m in clazz.methods: - if m.typ in discouraged: - warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead") - for arg in m.args: - if arg in discouraged: - warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead") - - -PRIMITIVES = {"void", "int", "float", "boolean", "short", "char", "byte", "long", "double"} - -@verifier -def verify_nullability(clazz): - """Catches missing nullability annotations""" - - for f in clazz.fields: - if "enum_constant" in f.split: - continue # Enum constants are never null - if f.value is not None and 'final' in f.split: - continue # Nullability of constants can be inferred. - if f.typ not in PRIMITIVES and not has_nullability(f.annotations): - error(clazz, f, "M12", "Field must be marked either @NonNull or @Nullable") - - for c in clazz.ctors: - verify_nullability_args(clazz, c) - - for m in clazz.methods: - if m.name == "writeToParcel" or m.name == "onReceive" or m.name == "onBind": - continue # Parcelable.writeToParcel(), BroadcastReceiver.onReceive(), and Service.onBind() are not yet annotated - - if (m.name == "equals" and m.args == ["java.lang.Object"] or - m.name == "toString" and m.args == []): - continue # Nullability of equals and toString is implicit. - - if m.typ not in PRIMITIVES and not has_nullability(m.annotations): - error(clazz, m, "M12", "Return value must be marked either @NonNull or @Nullable") - verify_nullability_args(clazz, m) - -def verify_nullability_args(clazz, m): - for i, arg in enumerate(m.detailed_args): - if arg.type not in PRIMITIVES and not has_nullability(arg.annotations): - error(clazz, m, "M12", "Argument %d must be marked either @NonNull or @Nullable" % (i+1,)) - -def has_nullability(annotations): - return "@NonNull" in annotations or "@Nullable" in annotations - - -@verifier -def verify_intdef(clazz): - """intdefs must be @hide, because the constant names cannot be stored in - the stubs (only the values are, which is not useful)""" - if "@interface" not in clazz.split: - return - if "@IntDef" in clazz.annotations or "@LongDef" in clazz.annotations: - error(clazz, None, None, "@IntDef and @LongDef annotations must be @hide") - - -@verifier -def verify_singleton(clazz): - """Catch singleton objects with constructors.""" - - singleton = False - for m in clazz.methods: - if m.name.startswith("get") and m.name.endswith("Instance") and " static " in m.raw: - singleton = True - - if singleton: - for c in clazz.ctors: - error(clazz, c, None, "Singleton classes should use getInstance() methods") - - - -def is_interesting(clazz): - """Test if given class is interesting from an Android PoV.""" - - if clazz.pkg.name.startswith("java"): return False - if clazz.pkg.name.startswith("junit"): return False - if clazz.pkg.name.startswith("org.apache"): return False - if clazz.pkg.name.startswith("org.xml"): return False - if clazz.pkg.name.startswith("org.json"): return False - if clazz.pkg.name.startswith("org.w3c"): return False - if clazz.pkg.name.startswith("android.icu."): return False - return True - - -def examine_clazz(clazz): - """Find all style issues in the given class.""" - - notice(clazz) - - if not is_interesting(clazz): return - - for v in verifiers.itervalues(): - v(clazz) - - if not ALLOW_GOOGLE: verify_google(clazz) - - -def examine_stream(stream, base_stream=None, in_classes_with_base=[], out_classes_with_base=None): - """Find all style issues in the given API stream.""" - global failures, noticed - failures = {} - noticed = {} - _parse_stream(stream, examine_clazz, base_f=base_stream, - in_classes_with_base=in_classes_with_base, - out_classes_with_base=out_classes_with_base) - return (failures, noticed) - - -def examine_api(api): - """Find all style issues in the given parsed API.""" - global failures - failures = {} - for key in sorted(api.keys()): - examine_clazz(api[key]) - return failures - - -def verify_compat(cur, prev): - """Find any incompatible API changes between two levels.""" - global failures - - def class_exists(api, test): - return test.fullname in api - - def ctor_exists(api, clazz, test): - for m in clazz.ctors: - if m.ident == test.ident: return True - return False - - def all_methods(api, clazz): - methods = list(clazz.methods) - if clazz.extends is not None: - methods.extend(all_methods(api, api[clazz.extends])) - return methods - - def method_exists(api, clazz, test): - methods = all_methods(api, clazz) - for m in methods: - if m.ident == test.ident: return True - return False - - def field_exists(api, clazz, test): - for f in clazz.fields: - if f.ident == test.ident: return True - return False - - failures = {} - for key in sorted(prev.keys()): - prev_clazz = prev[key] - - if not class_exists(cur, prev_clazz): - error(prev_clazz, None, None, "Class removed or incompatible change") - continue - - cur_clazz = cur[key] - - for test in prev_clazz.ctors: - if not ctor_exists(cur, cur_clazz, test): - error(prev_clazz, prev_ctor, None, "Constructor removed or incompatible change") - - methods = all_methods(prev, prev_clazz) - for test in methods: - if not method_exists(cur, cur_clazz, test): - error(prev_clazz, test, None, "Method removed or incompatible change") - - for test in prev_clazz.fields: - if not field_exists(cur, cur_clazz, test): - error(prev_clazz, test, None, "Field removed or incompatible change") - - return failures - - -def match_filter(filters, fullname): - for f in filters: - if fullname == f: - return True - if fullname.startswith(f + '.'): - return True - return False - - -def show_deprecations_at_birth(cur, prev): - """Show API deprecations at birth.""" - global failures - - # Remove all existing things so we're left with new - for prev_clazz in prev.values(): - if prev_clazz.fullname not in cur: - # The class was removed this release; we can safely ignore it. - continue - - cur_clazz = cur[prev_clazz.fullname] - if not is_interesting(cur_clazz): continue - - sigs = { i.ident: i for i in prev_clazz.ctors } - cur_clazz.ctors = [ i for i in cur_clazz.ctors if i.ident not in sigs ] - sigs = { i.ident: i for i in prev_clazz.methods } - cur_clazz.methods = [ i for i in cur_clazz.methods if i.ident not in sigs ] - sigs = { i.ident: i for i in prev_clazz.fields } - cur_clazz.fields = [ i for i in cur_clazz.fields if i.ident not in sigs ] - - # Forget about class entirely when nothing new - if len(cur_clazz.ctors) == 0 and len(cur_clazz.methods) == 0 and len(cur_clazz.fields) == 0: - del cur[prev_clazz.fullname] - - for clazz in cur.values(): - if not is_interesting(clazz): continue - - if "deprecated" in clazz.split and not clazz.fullname in prev: - error(clazz, None, None, "Found API deprecation at birth") - - for i in clazz.ctors + clazz.methods + clazz.fields: - if "deprecated" in i.split: - error(clazz, i, None, "Found API deprecation at birth") - - print "%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), - format(reset=True))) - for f in sorted(failures): - print failures[f] - print - - -def show_stats(cur, prev): - """Show API stats.""" - - stats = collections.defaultdict(int) - for cur_clazz in cur.values(): - if not is_interesting(cur_clazz): continue - - if cur_clazz.fullname not in prev: - stats['new_classes'] += 1 - stats['new_ctors'] += len(cur_clazz.ctors) - stats['new_methods'] += len(cur_clazz.methods) - stats['new_fields'] += len(cur_clazz.fields) - else: - prev_clazz = prev[cur_clazz.fullname] - - sigs = { i.ident: i for i in prev_clazz.ctors } - ctors = len([ i for i in cur_clazz.ctors if i.ident not in sigs ]) - sigs = { i.ident: i for i in prev_clazz.methods } - methods = len([ i for i in cur_clazz.methods if i.ident not in sigs ]) - sigs = { i.ident: i for i in prev_clazz.fields } - fields = len([ i for i in cur_clazz.fields if i.ident not in sigs ]) - - if ctors + methods + fields > 0: - stats['extend_classes'] += 1 - stats['extend_ctors'] += ctors - stats['extend_methods'] += methods - stats['extend_fields'] += fields - - print "#", "".join([ k.ljust(20) for k in sorted(stats.keys()) ]) - print " ", "".join([ str(stats[k]).ljust(20) for k in sorted(stats.keys()) ]) - - -def main(): - parser = argparse.ArgumentParser(description="Enforces common Android public API design \ - patterns. It ignores lint messages from a previous API level, if provided.") - parser.add_argument("--base-current", nargs='?', type=argparse.FileType('r'), default=None, - help="The base current.txt to use when examining system-current.txt or" - " test-current.txt") - parser.add_argument("--base-previous", nargs='?', type=argparse.FileType('r'), default=None, - help="The base previous.txt to use when examining system-previous.txt or" - " test-previous.txt") - parser.add_argument("--no-color", action='store_const', const=True, - help="Disable terminal colors") - parser.add_argument("--color", action='store_const', const=True, - help="Use terminal colors") - parser.add_argument("--allow-google", action='store_const', const=True, - help="Allow references to Google") - parser.add_argument("--show-noticed", action='store_const', const=True, - help="Show API changes noticed") - parser.add_argument("--show-deprecations-at-birth", action='store_const', const=True, - help="Show API deprecations at birth") - parser.add_argument("--show-stats", action='store_const', const=True, - help="Show API stats") - parser.add_argument("--title", action='store', default=None, - help="Title to put in for display purposes") - parser.add_argument("--filter", action="append", - help="If provided, only show lint for the given packages or classes.") - parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt") - parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None, - help="previous.txt") - args = vars(parser.parse_args()) - - if args['no_color']: - USE_COLOR = False - elif args['color']: - USE_COLOR = True - else: - USE_COLOR = sys.stdout.isatty() - - if args['allow_google']: - ALLOW_GOOGLE = True - - current_file = args['current.txt'] - base_current_file = args['base_current'] - previous_file = args['previous.txt'] - base_previous_file = args['base_previous'] - filters = args['filter'] - if not filters: - filters = [] - title = args['title'] - if not title: - title = current_file.name - - if args['show_deprecations_at_birth']: - with current_file as f: - cur = _parse_stream(f) - with previous_file as f: - prev = _parse_stream(f) - show_deprecations_at_birth(cur, prev) - sys.exit() - - if args['show_stats']: - with current_file as f: - cur = _parse_stream(f) - with previous_file as f: - prev = _parse_stream(f) - show_stats(cur, prev) - sys.exit() - - classes_with_base = [] - - with current_file as f: - if base_current_file: - with base_current_file as base_f: - cur_fail, cur_noticed = examine_stream(f, base_f, - out_classes_with_base=classes_with_base) - else: - cur_fail, cur_noticed = examine_stream(f, out_classes_with_base=classes_with_base) - - if not previous_file is None: - with previous_file as f: - if base_previous_file: - with base_previous_file as base_f: - prev_fail, prev_noticed = examine_stream(f, base_f, - in_classes_with_base=classes_with_base) - else: - prev_fail, prev_noticed = examine_stream(f, in_classes_with_base=classes_with_base) - - # ignore errors from previous API level - for p in prev_fail: - if p in cur_fail: - del cur_fail[p] - - # ignore classes unchanged from previous API level - for k, v in prev_noticed.iteritems(): - if k in cur_noticed and v == cur_noticed[k]: - del cur_noticed[k] - - """ - # NOTE: disabled because of memory pressure - # look for compatibility issues - compat_fail = verify_compat(cur, prev) - - print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True))) - for f in sorted(compat_fail): - print compat_fail[f] - print - """ - - # ignore everything but the given filters, if provided - if filters: - cur_fail = dict([(key, failure) for key, failure in cur_fail.iteritems() - if match_filter(filters, failure.clazz.fullname)]) - - if args['show_noticed'] and len(cur_noticed) != 0: - print "%s API changes noticed %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True))) - for f in sorted(cur_noticed.keys()): - print f - print - - if len(cur_fail) != 0: - print "%s API style issues: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True), - title, format(reset=True))) - for f in filters: - print "%s filter: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True), - f, format(reset=True))) - print - for f in sorted(cur_fail): - print cur_fail[f] - print - print "%d errors" % len(cur_fail) - sys.exit(77) - -if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - sys.exit(1) diff --git a/tools/apilint/apilint_sha.sh b/tools/apilint/apilint_sha.sh deleted file mode 100755 index 2a45b10392d7..000000000000 --- a/tools/apilint/apilint_sha.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then - python tools/apilint/apilint.py <(git show $1:api/current.txt) <(git show $1^:api/current.txt) -fi diff --git a/tools/apilint/apilint_sha_system.sh b/tools/apilint/apilint_sha_system.sh deleted file mode 100755 index 8538a3d904f5..000000000000 --- a/tools/apilint/apilint_sha_system.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# 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. - -if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then - python tools/apilint/apilint.py \ - --base-current <(git show $1:api/current.txt) \ - --base-previous <(git show $1^:api/current.txt) \ - <(git show $1:api/system-current.txt) \ - <(git show $1^:api/system-current.txt) -fi diff --git a/tools/apilint/apilint_stats.sh b/tools/apilint/apilint_stats.sh deleted file mode 100755 index 052d9a5265fe..000000000000 --- a/tools/apilint/apilint_stats.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -API=28 -while [ $API -gt 14 ]; do - echo "# Changes in API $((API))" - python tools/apilint/apilint.py --show-stats ../../prebuilts/sdk/$((API))/public/api/android.txt ../../prebuilts/sdk/$((API-1))/public/api/android.txt - let API=API-1 -done diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py deleted file mode 100644 index 811cb9aa23d5..000000000000 --- a/tools/apilint/apilint_test.py +++ /dev/null @@ -1,414 +0,0 @@ -#!/usr/bin/env python - -# 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. - -import unittest - -import apilint - -def cls(pkg, name): - return apilint.Class(apilint.Package(999, "package %s {" % pkg, None), 999, - "public final class %s {" % name, None) - -_ri = apilint._retry_iterator - -c1 = cls("android.app", "ActivityManager") -c2 = cls("android.app", "Notification") -c3 = cls("android.app", "Notification.Action") -c4 = cls("android.graphics", "Bitmap") - -class UtilTests(unittest.TestCase): - def test_retry_iterator(self): - it = apilint._retry_iterator([1, 2, 3, 4]) - self.assertEqual(it.next(), 1) - self.assertEqual(it.next(), 2) - self.assertEqual(it.next(), 3) - it.send("retry") - self.assertEqual(it.next(), 3) - self.assertEqual(it.next(), 4) - with self.assertRaises(StopIteration): - it.next() - - def test_retry_iterator_one(self): - it = apilint._retry_iterator([1]) - self.assertEqual(it.next(), 1) - it.send("retry") - self.assertEqual(it.next(), 1) - with self.assertRaises(StopIteration): - it.next() - - def test_retry_iterator_one(self): - it = apilint._retry_iterator([1]) - self.assertEqual(it.next(), 1) - it.send("retry") - self.assertEqual(it.next(), 1) - with self.assertRaises(StopIteration): - it.next() - - def test_skip_to_matching_class_found(self): - it = _ri([c1, c2, c3, c4]) - self.assertEquals(apilint._skip_to_matching_class(it, c3), - c3) - self.assertEqual(it.next(), c4) - - def test_skip_to_matching_class_not_found(self): - it = _ri([c1, c2, c3, c4]) - self.assertEquals(apilint._skip_to_matching_class(it, cls("android.content", "ContentProvider")), - None) - self.assertEqual(it.next(), c4) - - def test_yield_until_matching_class_found(self): - it = _ri([c1, c2, c3, c4]) - self.assertEquals(list(apilint._yield_until_matching_class(it, c3)), - [c1, c2]) - self.assertEqual(it.next(), c4) - - def test_yield_until_matching_class_not_found(self): - it = _ri([c1, c2, c3, c4]) - self.assertEquals(list(apilint._yield_until_matching_class(it, cls("android.content", "ContentProvider"))), - [c1, c2, c3]) - self.assertEqual(it.next(), c4) - - def test_yield_until_matching_class_None(self): - it = _ri([c1, c2, c3, c4]) - self.assertEquals(list(apilint._yield_until_matching_class(it, None)), - [c1, c2, c3, c4]) - - -faulty_current_txt = """ -// Signature format: 2.0 -package android.app { - public final class Activity { - } - - public final class WallpaperColors implements android.os.Parcelable { - ctor public WallpaperColors(@NonNull android.os.Parcel); - method public int describeContents(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; - } -} -""".strip().split('\n') - -ok_current_txt = """ -// Signature format: 2.0 -package android.app { - public final class Activity { - } - - public final class WallpaperColors implements android.os.Parcelable { - ctor public WallpaperColors(); - method public int describeContents(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; - } -} -""".strip().split('\n') - -system_current_txt = """ -// Signature format: 2.0 -package android.app { - public final class WallpaperColors implements android.os.Parcelable { - method public int getSomething(); - } -} -""".strip().split('\n') - - - -class BaseFileTests(unittest.TestCase): - def test_base_file_avoids_errors(self): - failures, _ = apilint.examine_stream(system_current_txt, ok_current_txt) - self.assertEquals(failures, {}) - - def test_class_with_base_finds_same_errors(self): - failures_with_classes_with_base, _ = apilint.examine_stream("", faulty_current_txt, - in_classes_with_base=[cls("android.app", "WallpaperColors")]) - failures_with_system_txt, _ = apilint.examine_stream(system_current_txt, faulty_current_txt) - - self.assertEquals(failures_with_classes_with_base.keys(), failures_with_system_txt.keys()) - - def test_classes_with_base_is_emited(self): - classes_with_base = [] - _, _ = apilint.examine_stream(system_current_txt, faulty_current_txt, - out_classes_with_base=classes_with_base) - self.assertEquals(map(lambda x: x.fullname, classes_with_base), ["android.app.WallpaperColors"]) - -class ParseV2Stream(unittest.TestCase): - def test_field_kinds(self): - api = apilint._parse_stream(""" -// Signature format: 2.0 -package android { - public enum SomeEnum { - enum_constant public static final android.SomeEnum ENUM_CONST; - field public static final int FIELD_CONST; - property public final int someProperty; - ctor public SomeEnum(); - method public Object? getObject(); - } -} - """.strip().split('\n')) - - self.assertEquals(api['android.SomeEnum'].fields[0].split[0], 'enum_constant') - self.assertEquals(api['android.SomeEnum'].fields[1].split[0], 'field') - self.assertEquals(api['android.SomeEnum'].fields[2].split[0], 'property') - self.assertEquals(api['android.SomeEnum'].ctors[0].split[0], 'ctor') - self.assertEquals(api['android.SomeEnum'].methods[0].split[0], 'method') - -class ParseV3Stream(unittest.TestCase): - def test_field_kinds(self): - api = apilint._parse_stream(""" -// Signature format: 3.0 -package a { - - public final class ContextKt { - method public static inline <reified T> T! getSystemService(android.content.Context); - method public static inline void withStyledAttributes(android.content.Context, android.util.AttributeSet? set = null, int[] attrs, @AttrRes int defStyleAttr = 0, @StyleRes int defStyleRes = 0, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block); - } -} - """.strip().split('\n')) - self.assertEquals(api['a.ContextKt'].methods[0].name, 'getSystemService') - self.assertEquals(api['a.ContextKt'].methods[0].split[:4], ['method', 'public', 'static', 'inline']) - self.assertEquals(api['a.ContextKt'].methods[1].name, 'withStyledAttributes') - self.assertEquals(api['a.ContextKt'].methods[1].split[:4], ['method', 'public', 'static', 'inline']) - -class V2TokenizerTests(unittest.TestCase): - def _test(self, raw, expected): - self.assertEquals(apilint.V2Tokenizer(raw).tokenize(), expected) - - def test_simple(self): - self._test(" method public some.Type someName(some.Argument arg, int arg);", - ['method', 'public', 'some.Type', 'someName', '(', 'some.Argument', - 'arg', ',', 'int', 'arg', ')', ';']) - self._test("class Some.Class extends SomeOther {", - ['class', 'Some.Class', 'extends', 'SomeOther', '{']) - - def test_varargs(self): - self._test("name(String...)", - ['name', '(', 'String', '...', ')']) - - def test_kotlin(self): - self._test("String? name(String!...)", - ['String', '?', 'name', '(', 'String', '!', '...', ')']) - - def test_annotation(self): - self._test("method @Nullable public void name();", - ['method', '@', 'Nullable', 'public', 'void', 'name', '(', ')', ';']) - - def test_annotation_args(self): - self._test("@Some(val=1, other=2) class Class {", - ['@', 'Some', '(', 'val', '=', '1', ',', 'other', '=', '2', ')', - 'class', 'Class', '{']) - def test_comment(self): - self._test("some //comment", ['some']) - - def test_strings(self): - self._test(r'"" "foo" "\"" "\\"', ['""', '"foo"', r'"\""', r'"\\"']) - - def test_at_interface(self): - self._test("public @interface Annotation {", - ['public', '@interface', 'Annotation', '{']) - - def test_array_type(self): - self._test("int[][]", ['int', '[]', '[]']) - - def test_generics(self): - self._test("<>foobar<A extends Object>", - ['<', '>', 'foobar', '<', 'A', 'extends', 'Object', '>']) - -class V2ParserTests(unittest.TestCase): - def _cls(self, raw): - pkg = apilint.Package(999, "package pkg {", None) - return apilint.Class(pkg, 1, raw, '', sig_format=2) - - def _method(self, raw, cls=None): - if not cls: - cls = self._cls("class Class {") - return apilint.Method(cls, 1, raw, '', sig_format=2) - - def _field(self, raw): - cls = self._cls("class Class {") - return apilint.Field(cls, 1, raw, '', sig_format=2) - - def test_parse_package(self): - pkg = apilint.Package(999, "package wifi.p2p {", None) - self.assertEquals("wifi.p2p", pkg.name) - - def test_class(self): - cls = self._cls("@Deprecated @IntRange(from=1, to=2) public static abstract class Some.Name extends Super<Class> implements Interface<Class> {") - self.assertTrue('deprecated' in cls.split) - self.assertTrue('static' in cls.split) - self.assertTrue('abstract' in cls.split) - self.assertTrue('class' in cls.split) - self.assertEquals('Super', cls.extends) - self.assertEquals('Interface', cls.implements) - self.assertEquals('pkg.Some.Name', cls.fullname) - - def test_enum(self): - cls = self._cls("public enum Some.Name {") - self._field("enum_constant public static final android.ValueType COLOR;") - - def test_interface(self): - cls = self._cls("@Deprecated @IntRange(from=1, to=2) public interface Some.Name extends Interface<Class> {") - self.assertTrue('deprecated' in cls.split) - self.assertTrue('interface' in cls.split) - self.assertEquals('Interface', cls.extends) - self.assertEquals('Interface', cls.implements) - self.assertEquals('pkg.Some.Name', cls.fullname) - - def test_at_interface(self): - cls = self._cls("@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint {") - self.assertTrue('@interface' in cls.split) - self.assertEquals('pkg.SuppressLint', cls.fullname) - - def test_parse_method(self): - m = self._method("method @Deprecated public static native <T> Class<T>[][] name(" - + "Class<T[]>[][], Class<T[][][]>[][]...) throws Exception, T;") - self.assertTrue('static' in m.split) - self.assertTrue('public' in m.split) - self.assertTrue('method' in m.split) - self.assertTrue('native' in m.split) - self.assertTrue('deprecated' in m.split) - self.assertEquals('java.lang.Class[][]', m.typ) - self.assertEquals('name', m.name) - self.assertEquals(['java.lang.Class[][]', 'java.lang.Class[][]...'], m.args) - self.assertEquals(['java.lang.Exception', 'T'], m.throws) - - def test_ctor(self): - m = self._method("ctor @Deprecated <T> ClassName();") - self.assertTrue('ctor' in m.split) - self.assertTrue('deprecated' in m.split) - self.assertEquals('ctor', m.typ) - self.assertEquals('ClassName', m.name) - - def test_parse_annotation_method(self): - cls = self._cls("@interface Annotation {") - self._method('method abstract String category() default "";', cls=cls) - self._method('method abstract boolean deepExport() default false;', cls=cls) - self._method('method abstract ViewDebug.FlagToString[] flagMapping() default {};', cls=cls) - self._method('method abstract ViewDebug.FlagToString[] flagMapping() default (double)java.lang.Float.NEGATIVE_INFINITY;', cls=cls) - - def test_parse_string_field(self): - f = self._field('field @Deprecated public final String SOME_NAME = "value";') - self.assertTrue('field' in f.split) - self.assertTrue('deprecated' in f.split) - self.assertTrue('final' in f.split) - self.assertEquals('java.lang.String', f.typ) - self.assertEquals('SOME_NAME', f.name) - self.assertEquals('value', f.value) - - def test_parse_field(self): - f = self._field('field public Object SOME_NAME;') - self.assertTrue('field' in f.split) - self.assertEquals('java.lang.Object', f.typ) - self.assertEquals('SOME_NAME', f.name) - self.assertEquals(None, f.value) - - def test_parse_int_field(self): - f = self._field('field public int NAME = 123;') - self.assertTrue('field' in f.split) - self.assertEquals('int', f.typ) - self.assertEquals('NAME', f.name) - self.assertEquals('123', f.value) - - def test_parse_quotient_field(self): - f = self._field('field public int NAME = (0.0/0.0);') - self.assertTrue('field' in f.split) - self.assertEquals('int', f.typ) - self.assertEquals('NAME', f.name) - self.assertEquals('( 0.0 / 0.0 )', f.value) - - def test_kotlin_types(self): - self._field('field public List<Integer[]?[]!>?[]![]? NAME;') - self._method("method <T?> Class<T!>?[]![][]? name(Type!, Type argname," - + "Class<T?>[][]?[]!...!) throws Exception, T;") - self._method("method <T> T name(T a = 1, T b = A(1), Lambda f = { false }, N? n = null, " - + """double c = (1/0), float d = 1.0f, String s = "heyo", char c = 'a');""") - - def test_kotlin_operator(self): - self._method('method public operator void unaryPlus(androidx.navigation.NavDestination);') - self._method('method public static operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);') - self._method('method public static operator <T> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);') - - def test_kotlin_property(self): - self._field('property public VM value;') - self._field('property public final String? action;') - - def test_kotlin_varargs(self): - self._method('method public void error(int p = "42", Integer int2 = "null", int p1 = "42", vararg String args);') - - def test_kotlin_default_values(self): - self._method('method public void foo(String! = null, String! = "Hello World", int = 42);') - self._method('method void method(String, String firstArg = "hello", int secondArg = "42", String thirdArg = "world");') - self._method('method void method(String, String firstArg = "hello", int secondArg = "42");') - self._method('method void method(String, String firstArg = "hello");') - self._method('method void edit(android.Type, boolean commit = false, Function1<? super Editor,kotlin.Unit> action);') - self._method('method <K, V> LruCache<K,V> lruCache(int maxSize, Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, Function1<? extends V> create = { (V)null }, Function4<kotlin.Unit> onEntryRemoved = { _, _, _, _ -> });') - self._method('method android.Bitmap? drawToBitmap(android.View, android.Config config = android.graphics.Bitmap.Config.ARGB_8888);') - self._method('method void emptyLambda(Function0<kotlin.Unit> sizeOf = {});') - self._method('method void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);') - self._method('method void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);') - self._method('method void method3(String str, int p, int int2 = double(int) + str.length);') - self._method('method void print(test.pkg.Foo foo = test.pkg.Foo());') - - def test_type_use_annotation(self): - self._method('method public static int codePointAt(char @NonNull [], int);') - self._method('method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();') - - m = self._method('method @NonNull public java.lang.annotation.@NonNull Annotation @NonNull [] getAnnotations();') - self.assertEquals('java.lang.annotation.Annotation[]', m.typ) - - m = self._method('method @NonNull public abstract java.lang.annotation.@NonNull Annotation @NonNull [] @NonNull [] getParameterAnnotations();') - self.assertEquals('java.lang.annotation.Annotation[][]', m.typ) - - m = self._method('method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);') - self.assertEquals('java.lang.String[]', m.typ) - -class PackageTests(unittest.TestCase): - def _package(self, raw): - return apilint.Package(123, raw, "blame") - - def test_regular_package(self): - p = self._package("package an.pref.int {") - self.assertEquals('an.pref.int', p.name) - - def test_annotation_package(self): - p = self._package("package @RestrictTo(a.b.C) an.pref.int {") - self.assertEquals('an.pref.int', p.name) - - def test_multi_annotation_package(self): - p = self._package("package @Rt(a.b.L_G_P) @RestrictTo(a.b.C) an.pref.int {") - self.assertEquals('an.pref.int', p.name) - -class FilterTests(unittest.TestCase): - def test_filter_match_prefix(self): - self.assertTrue(apilint.match_filter(["a"], "a.B")) - self.assertTrue(apilint.match_filter(["a.B"], "a.B.C")) - - def test_filter_dont_match_prefix(self): - self.assertFalse(apilint.match_filter(["c"], "a.B")) - self.assertFalse(apilint.match_filter(["a."], "a.B")) - self.assertFalse(apilint.match_filter(["a.B."], "a.B.C")) - - def test_filter_match_exact(self): - self.assertTrue(apilint.match_filter(["a.B"], "a.B")) - - def test_filter_dont_match_exact(self): - self.assertFalse(apilint.match_filter([""], "a.B")) - self.assertFalse(apilint.match_filter(["a.C"], "a.B")) - self.assertFalse(apilint.match_filter(["a.C"], "a.B")) - -if __name__ == "__main__": - unittest.main() diff --git a/tools/genprotos.sh b/tools/genprotos.sh deleted file mode 100755 index f901c9f588b6..000000000000 --- a/tools/genprotos.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can -# end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to -# the way sbox rewrites the command. See b/70221552. - -set -e - -location_aprotoc=$1 -location_protoc=$2 -location_soong_zip=$3 -genDir=$4 -depfile=$5 -in=$6 -out=$7 - -mkdir -p ${genDir}/${in} && \ - ${location_aprotoc} --plugin=${location_protoc} \ - --dependency_out=${depfile} \ - --javastream_out=${genDir}/${in} \ - -Iexternal/protobuf/src \ - -I . \ - ${in} && \ - ${location_soong_zip} -jar -o ${out} -C ${genDir}/${in} -D ${genDir}/${in} diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index e883c6bed755..46105f4d66b0 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -241,8 +241,6 @@ class FlagsDict: flags = csv[1:] if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags): flags.append(FLAG_WHITELIST) - elif FLAG_TEST_API in flags: - flags.append(FLAG_GREYLIST) self._dict[csv[0]].update(flags) def assign_flag(self, flag, apis, source="<unknown>"): diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py index 4dc880b107d3..55c3a7d718db 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists_test.py +++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py @@ -53,14 +53,22 @@ class TestHiddenapiListGeneration(unittest.TestCase): # Test new additions. flags.parse_and_merge_csv([ 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O ]) - self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O ]) + 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O, + 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, + 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, + 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + ]) + self.assertEqual(flags.generate_csv(), [ + 'A,' + FLAG_GREYLIST, + 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O, + 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, + 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, + 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + ]) # Test unknown flag. with self.assertRaises(AssertionError): - flags.parse_and_merge_csv([ 'C,foo' ]) + flags.parse_and_merge_csv([ 'Z,foo' ]) def test_assign_flag(self): flags = FlagsDict() diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp index 0e33fddcde07..1e96234543c8 100644 --- a/tools/processors/unsupportedappusage/Android.bp +++ b/tools/processors/unsupportedappusage/Android.bp @@ -1,11 +1,6 @@ -java_plugin { - name: "unsupportedappusage-annotation-processor", - processor_class: "android.processor.unsupportedappusage.UnsupportedAppUsageProcessor", - - java_resources: [ - "META-INF/**/*", - ], +java_library_host { + name: "unsupportedappusage-annotation-processor-lib", srcs: [ "src/**/*.java", ], @@ -22,6 +17,18 @@ java_plugin { "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", ], }, +} + +java_plugin { + name: "unsupportedappusage-annotation-processor", + processor_class: "android.processor.unsupportedappusage.UnsupportedAppUsageProcessor", + + java_resources: [ + "META-INF/**/*", + ], + static_libs: [ + "unsupportedappusage-annotation-processor-lib" + ], use_tools_jar: true, } diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java index 5a5703ed520c..65fc733fa364 100644 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java +++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java @@ -101,14 +101,20 @@ public class SignatureBuilder { private String getClassSignature(TypeElement clazz) { StringBuilder sb = new StringBuilder("L"); for (Element enclosing : getEnclosingElements(clazz)) { - if (enclosing.getKind() == PACKAGE) { - sb.append(((PackageElement) enclosing) - .getQualifiedName() - .toString() - .replace('.', '/')); - sb.append('/'); - } else { - sb.append(enclosing.getSimpleName()).append('$'); + switch (enclosing.getKind()) { + case MODULE: + // ignore this. + break; + case PACKAGE: + sb.append(((PackageElement) enclosing) + .getQualifiedName() + .toString() + .replace('.', '/')); + sb.append('/'); + break; + default: + sb.append(enclosing.getSimpleName()).append('$'); + break; } } diff --git a/tools/processors/unsupportedappusage/test/Android.bp b/tools/processors/unsupportedappusage/test/Android.bp new file mode 100644 index 000000000000..49ea3d4bbc96 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/Android.bp @@ -0,0 +1,28 @@ +// Copyright (C) 2019 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. + +java_test_host { + name: "unsupportedappusage-processor-test", + + srcs: ["src/**/*.java"], + + static_libs: [ + "libjavac", + "unsupportedappusage-annotation-processor-lib", + "truth-host-prebuilt", + "mockito-host", + "junit-host", + "objenesis", + ], +} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java new file mode 100644 index 000000000000..23db99e81194 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 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.processor.unsupportedappusage; + +import com.google.common.base.Splitter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CsvReader { + + private final Splitter mSplitter; + private final List<String> mColumns; + private final List<Map<String, String>> mContents; + + public CsvReader(InputStream in) throws IOException { + mSplitter = Splitter.on(","); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + mColumns = mSplitter.splitToList(br.readLine()); + mContents = new ArrayList<>(); + String line = br.readLine(); + while (line != null) { + List<String> contents = mSplitter.splitToList(line); + Map<String, String> contentMap = new HashMap<>(); + for (int i = 0; i < Math.min(contents.size(), mColumns.size()); ++i) { + contentMap.put(mColumns.get(i), contents.get(i)); + } + mContents.add(contentMap); + line = br.readLine(); + } + br.close(); + } + + public List<String> getColumns() { + return mColumns; + } + + public List<Map<String, String>> getContents() { + return mContents; + } +} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java new file mode 100644 index 000000000000..012e88f17924 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 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.processor.unsupportedappusage; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.javac.Javac; + +import com.google.common.base.Joiner; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Map; + +public class UnsupportedAppUsageProcessorTest { + + private Javac mJavac; + + @Before + public void setup() throws IOException { + mJavac = new Javac(); + mJavac.addSource("dalvik.annotation.compat.UnsupportedAppUsage", Joiner.on('\n').join( + "package dalvik.annotation.compat;", + "public @interface UnsupportedAppUsage {", + " String expectedSignature() default \"\";\n", + " String someProperty() default \"\";", + "}")); + } + + private CsvReader compileAndReadCsv() throws IOException { + mJavac.compileWithAnnotationProcessor(new UnsupportedAppUsageProcessor()); + return new CsvReader( + mJavac.getOutputFile("unsupportedappusage/unsupportedappusage_index.csv")); + } + + @Test + public void testSignatureFormat() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", + "import dalvik.annotation.compat.UnsupportedAppUsage;", + "public class Class {", + " @UnsupportedAppUsage", + " public void method() {}", + "}")); + assertThat(compileAndReadCsv().getContents().get(0)).containsEntry( + "signature", "La/b/Class;->method()V" + ); + } + + @Test + public void testSourcePosition() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", // 1 + "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 + "public class Class {", // 3 + " @UnsupportedAppUsage", // 4 + " public void method() {}", // 5 + "}")); + Map<String, String> row = compileAndReadCsv().getContents().get(0); + assertThat(row).containsEntry("startline", "4"); + assertThat(row).containsEntry("startcol", "3"); + assertThat(row).containsEntry("endline", "4"); + assertThat(row).containsEntry("endcol", "23"); + } + + @Test + public void testAnnotationProperties() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", // 1 + "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 + "public class Class {", // 3 + " @UnsupportedAppUsage(someProperty=\"value\")", // 4 + " public void method() {}", // 5 + "}")); + assertThat(compileAndReadCsv().getContents().get(0)).containsEntry( + "properties", "someProperty=%22value%22"); + } + + +} diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index b8d2971e74bb..8a252dd1e447 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -16,6 +16,8 @@ package android.net.wifi; +import android.net.wifi.WifiClient; + /** * Interface for Soft AP callback. * @@ -36,9 +38,9 @@ oneway interface ISoftApCallback void onStateChanged(int state, int failureReason); /** - * Service to manager callback providing number of connected clients. + * Service to manager callback providing connected client's information. * - * @param numClients number of connected clients + * @param clients the currently connected clients */ - void onNumClientsChanged(int numClients); + void onConnectedClientsChanged(in List<WifiClient> clients); } diff --git a/wifi/java/android/net/wifi/WifiClient.aidl b/wifi/java/android/net/wifi/WifiClient.aidl new file mode 100644 index 000000000000..accdaddfc848 --- /dev/null +++ b/wifi/java/android/net/wifi/WifiClient.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 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.wifi; + +@JavaOnlyStableParcelable parcelable WifiClient;
\ No newline at end of file diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java new file mode 100644 index 000000000000..3e09580802ce --- /dev/null +++ b/wifi/java/android/net/wifi/WifiClient.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 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.wifi; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.net.MacAddress; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** @hide */ +@SystemApi +public final class WifiClient implements Parcelable { + + private final MacAddress mMacAddress; + + /** + * The mac address of this client. + */ + @NonNull + public MacAddress getMacAddress() { + return mMacAddress; + } + + private WifiClient(Parcel in) { + mMacAddress = in.readParcelable(null); + } + + /** @hide */ + public WifiClient(@NonNull MacAddress macAddress) { + Preconditions.checkNotNull(macAddress, "mMacAddress must not be null."); + + this.mMacAddress = macAddress; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mMacAddress, flags); + } + + @NonNull + public static final Creator<WifiClient> CREATOR = new Creator<WifiClient>() { + public WifiClient createFromParcel(Parcel in) { + return new WifiClient(in); + } + + public WifiClient[] newArray(int size) { + return new WifiClient[size]; + } + }; + + @NonNull + @Override + public String toString() { + return "WifiClient{" + + "mMacAddress=" + mMacAddress + + '}'; + } + + @Override + public boolean equals(@NonNull Object o) { + if (this == o) return true; + if (!(o instanceof WifiClient)) return false; + WifiClient client = (WifiClient) o; + return mMacAddress.equals(client.mMacAddress); + } + + @Override + public int hashCode() { + return Objects.hash(mMacAddress); + } +} + + diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 77e02df105c8..68355c603914 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -38,6 +38,7 @@ import android.net.DhcpInfo; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; +import android.net.NetworkStack; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; @@ -532,19 +533,25 @@ public class WifiManager { @SystemApi public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; /** - * The interface used for the softap. + * The lookup key for a String extra that stores the interface name used for the Soft AP. + * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. + * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}. * * @hide */ - public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "wifi_ap_interface_name"; + @SystemApi + public static final String EXTRA_WIFI_AP_INTERFACE_NAME = + "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; /** - * The intended ip mode for this softap. - * @see #IFACE_IP_MODE_TETHERED - * @see #IFACE_IP_MODE_LOCAL_ONLY + * The lookup key for an int extra that stores the intended IP mode for this Soft AP. + * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. + * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. + * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}. * * @hide */ - public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode"; + @SystemApi + public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; /** @hide */ @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { @@ -634,40 +641,53 @@ public class WifiManager { */ public static final int SAP_START_FAILURE_NO_CHANNEL = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { + IFACE_IP_MODE_UNSPECIFIED, + IFACE_IP_MODE_CONFIGURATION_ERROR, + IFACE_IP_MODE_TETHERED, + IFACE_IP_MODE_LOCAL_ONLY}) + public @interface IfaceIpMode {} + /** * Interface IP mode unspecified. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ + @SystemApi public static final int IFACE_IP_MODE_UNSPECIFIED = -1; /** * Interface IP mode for configuration error. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ + @SystemApi public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; /** * Interface IP mode for tethering. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ + @SystemApi public static final int IFACE_IP_MODE_TETHERED = 1; /** * Interface IP mode for Local Only Hotspot. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ + @SystemApi public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; /** @@ -2538,16 +2558,21 @@ public class WifiManager { /** * Call allowing ConnectivityService to update WifiService with interface mode changes. * - * The possible modes include: {@link IFACE_IP_MODE_TETHERED}, - * {@link IFACE_IP_MODE_LOCAL_ONLY}, - * {@link IFACE_IP_MODE_CONFIGURATION_ERROR} - * - * @param ifaceName String name of the updated interface - * @param mode int representing the new mode + * @param ifaceName String name of the updated interface, or null to represent all interfaces + * @param mode int representing the new mode, one of: + * {@link #IFACE_IP_MODE_TETHERED}, + * {@link #IFACE_IP_MODE_LOCAL_ONLY}, + * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}, + * {@link #IFACE_IP_MODE_UNSPECIFIED} * * @hide */ - public void updateInterfaceIpState(String ifaceName, int mode) { + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) + public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) { try { mService.updateInterfaceIpState(ifaceName, mode); } catch (RemoteException e) { @@ -2556,15 +2581,21 @@ public class WifiManager { } /** - * Start SoftAp mode with the specified configuration. - * Note that starting in access point mode disables station - * mode operation - * @param wifiConfig SSID, security and channel details as - * part of WifiConfiguration - * @return {@code true} if the operation succeeds, {@code false} otherwise + * Start Soft AP (hotspot) mode with the specified configuration. + * Note that starting Soft AP mode may disable station mode operation if the device does not + * support concurrency. + * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to + * use the persisted Soft AP configuration that was previously set using + * {@link #setWifiApConfiguration(WifiConfiguration)}. + * @return {@code true} if the operation succeeded, {@code false} otherwise * * @hide */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { try { return mService.startSoftAp(wifiConfig); @@ -2580,6 +2611,11 @@ public class WifiManager { * * @hide */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) public boolean stopSoftAp() { try { return mService.stopSoftAp(); @@ -3085,25 +3121,27 @@ public class WifiManager { * * @hide */ + @SystemApi public interface SoftApCallback { /** * Called when soft AP state changes. * - * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, - * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, - * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} + * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, + * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, + * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} * @param failureReason reason when in failed state. One of - * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} + * {@link #SAP_START_FAILURE_GENERAL}, + * {@link #SAP_START_FAILURE_NO_CHANNEL} */ - public abstract void onStateChanged(@WifiApState int state, + void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason); /** - * Called when number of connected clients to soft AP changes. + * Called when the connected clients to soft AP changes. * - * @param numClients number of connected clients + * @param clients the currently connected clients */ - public abstract void onNumClientsChanged(int numClients); + void onConnectedClientsChanged(@NonNull List<WifiClient> clients); } /** @@ -3112,11 +3150,11 @@ public class WifiManager { * @hide */ private class SoftApCallbackProxy extends ISoftApCallback.Stub { - private final Handler mHandler; + private final Executor mExecutor; private final SoftApCallback mCallback; - SoftApCallbackProxy(Looper looper, SoftApCallback callback) { - mHandler = new Handler(looper); + SoftApCallbackProxy(Executor executor, SoftApCallback callback) { + mExecutor = executor; mCallback = callback; } @@ -3126,18 +3164,23 @@ public class WifiManager { Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" + failureReason); } - mHandler.post(() -> { + + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { mCallback.onStateChanged(state, failureReason); }); } @Override - public void onNumClientsChanged(int numClients) { + public void onConnectedClientsChanged(List<WifiClient> clients) { if (mVerboseLoggingEnabled) { - Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients); + Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsChanged: clients=" + + clients.size() + " clients"); } - mHandler.post(() -> { - mCallback.onNumClientsChanged(numClients); + + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.onConnectedClientsChanged(clients); }); } } @@ -3155,21 +3198,22 @@ public class WifiManager { * <p> * * @param callback Callback for soft AP events - * @param handler The Handler on whose thread to execute the callbacks of the {@code callback} - * object. If null, then the application's main thread will be used. + * @param executor The executor to execute the callbacks of the {@code executor} + * object. If null, then the application's main executor will be used. * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull SoftApCallback callback, - @Nullable Handler handler) { + @Nullable @CallbackExecutor Executor executor) { if (callback == null) throw new IllegalArgumentException("callback cannot be null"); - Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler); + Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); - Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); + executor = (executor == null) ? mContext.getMainExecutor() : executor; Binder binder = new Binder(); try { - mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback), + mService.registerSoftApCallback(binder, new SoftApCallbackProxy(executor, callback), callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java index e59516485112..8f3635fd2f04 100644 --- a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java +++ b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java @@ -20,8 +20,8 @@ import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.TelephonyManager.NetworkType; +import android.telephony.Annotation.NetworkType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk index 401b652289cd..3453d6ec827f 100644 --- a/wifi/tests/Android.mk +++ b/wifi/tests/Android.mk @@ -49,6 +49,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ core-test-rules \ guava \ mockito-target-minus-junit4 \ + net-tests-utils \ frameworks-base-testutils \ truth-prebuilt \ diff --git a/wifi/tests/src/android/net/wifi/WifiClientTest.java b/wifi/tests/src/android/net/wifi/WifiClientTest.java new file mode 100644 index 000000000000..42cab55305b9 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/WifiClientTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 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.wifi; + +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; +import static com.android.testutils.ParcelUtilsKt.assertParcelSane; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import android.net.MacAddress; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +/** + * Unit tests for {@link android.net.wifi.WifiClient}. + */ +@SmallTest +public class WifiClientTest { + private static final String INTERFACE_NAME = "wlan0"; + private static final String MAC_ADDRESS_STRING = "00:0a:95:9d:68:16"; + private static final MacAddress MAC_ADDRESS = MacAddress.fromString(MAC_ADDRESS_STRING); + + /** + * Verify parcel write/read with WifiClient. + */ + @Test + public void testWifiClientParcelWriteRead() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + + assertParcelSane(writeWifiClient, 1); + } + + /** + * Verify equals with WifiClient. + */ + @Test + public void testWifiClientEquals() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS); + + assertEquals(writeWifiClient, writeWifiClientEquals); + assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode()); + assertFieldCountEquals(1, WifiClient.class); + } + + /** + * Verify not-equals with WifiClient. + */ + @Test + public void testWifiClientNotEquals() throws Exception { + final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00"); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals); + + assertNotEquals(writeWifiClient, writeWifiClientNotEquals); + assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); + } +} diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index b75a1acf87c9..cfdb6f1dd304 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -66,6 +66,7 @@ import android.net.wifi.WifiManager.SoftApCallback; import android.net.wifi.WifiManager.TrafficStateCallback; import android.os.Build; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Message; import android.os.Messenger; @@ -101,8 +102,7 @@ public class WifiManagerTest { private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"}; @Mock Context mContext; - @Mock - android.net.wifi.IWifiManager mWifiService; + @Mock android.net.wifi.IWifiManager mWifiService; @Mock ApplicationInfo mApplicationInfo; @Mock WifiConfiguration mApConfig; @Mock IBinder mAppBinder; @@ -118,7 +118,8 @@ public class WifiManagerTest { private Messenger mWifiServiceMessenger; final ArgumentCaptor<Messenger> mMessengerCaptor = ArgumentCaptor.forClass(Messenger.class); - @Before public void setUp() throws Exception { + @Before + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); mHandler = spy(new Handler(mLooper.getLooper())); @@ -214,7 +215,7 @@ public class WifiManagerTest { @Test public void testCreationOfLocalOnlyHotspotSubscription() throws Exception { try (WifiManager.LocalOnlyHotspotSubscription sub = - mWifiManager.new LocalOnlyHotspotSubscription()) { + mWifiManager.new LocalOnlyHotspotSubscription()) { sub.close(); } } @@ -685,7 +686,7 @@ public class WifiManagerTest { @Test public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() { try { - mWifiManager.registerSoftApCallback(null, mHandler); + mWifiManager.registerSoftApCallback(null, new HandlerExecutor(mHandler)); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } @@ -710,7 +711,7 @@ public class WifiManagerTest { public void registerSoftApCallbackUsesMainLooperOnNullArgumentForHandler() { when(mContext.getMainLooper()).thenReturn(mLooper.getLooper()); mWifiManager.registerSoftApCallback(mSoftApCallback, null); - verify(mContext).getMainLooper(); + verify(mContext).getMainExecutor(); } /** @@ -718,7 +719,7 @@ public class WifiManagerTest { */ @Test public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception { - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), anyInt()); } @@ -729,7 +730,7 @@ public class WifiManagerTest { @Test public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception { ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), callbackIdentifier.capture()); @@ -744,7 +745,7 @@ public class WifiManagerTest { public void softApCallbackProxyCallsOnStateChanged() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -757,17 +758,17 @@ public class WifiManagerTest { * Verify client-provided callback is being called through callback proxy */ @Test - public void softApCallbackProxyCallsOnNumClientsChanged() throws Exception { + public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); - final int testNumClients = 3; - callbackCaptor.getValue().onNumClientsChanged(testNumClients); + final List<WifiClient> testClients = new ArrayList(); + callbackCaptor.getValue().onConnectedClientsChanged(testClients); mLooper.dispatchAll(); - verify(mSoftApCallback).onNumClientsChanged(testNumClients); + verify(mSoftApCallback).onConnectedClientsChanged(testClients); } /* @@ -777,18 +778,18 @@ public class WifiManagerTest { public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); - final int testNumClients = 5; + final List<WifiClient> testClients = new ArrayList(); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0); - callbackCaptor.getValue().onNumClientsChanged(testNumClients); + callbackCaptor.getValue().onConnectedClientsChanged(testClients); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); mLooper.dispatchAll(); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0); - verify(mSoftApCallback).onNumClientsChanged(testNumClients); + verify(mSoftApCallback).onConnectedClientsChanged(testClients); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); } @@ -801,7 +802,7 @@ public class WifiManagerTest { ArgumentCaptor.forClass(ISoftApCallback.Stub.class); TestLooper altLooper = new TestLooper(); Handler altHandler = new Handler(altLooper.getLooper()); - mWifiManager.registerSoftApCallback(mSoftApCallback, altHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(altHandler)); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -815,7 +816,7 @@ public class WifiManagerTest { */ @Test public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception { - mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); mLooper.dispatchAll(); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), anyInt()); @@ -1047,8 +1048,8 @@ public class WifiManagerTest { verifyNoMoreInteractions(mWifiService); } - /** -i * Verify that a call to cancel WPS immediately returns a failure. + /** + * Verify that a call to cancel WPS immediately returns a failure. */ @Test public void testCancelWpsImmediatelyFailsWithCallback() { @@ -1343,7 +1344,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Verify getting the factory MAC address. - * @throws Exception */ @Test public void testGetFactoryMacAddress() throws Exception { @@ -1390,7 +1390,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isEnhancedOpenSupported - * @throws Exception */ @Test public void testIsEnhancedOpenSupported() throws Exception { @@ -1404,7 +1403,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isWpa3SaeSupported - * @throws Exception */ @Test public void testIsWpa3SaeSupported() throws Exception { @@ -1418,7 +1416,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isWpa3SuiteBSupported - * @throws Exception */ @Test public void testIsWpa3SuiteBSupported() throws Exception { @@ -1432,7 +1429,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isEasyConnectSupported - * @throws Exception */ @Test public void testIsEasyConnectSupported() throws Exception { @@ -1446,7 +1442,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)} - * @throws Exception */ @Test public void testAddNetwork() throws Exception { @@ -1463,7 +1458,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)} - * @throws Exception */ @Test public void testUpdateNetwork() throws Exception { @@ -1485,7 +1479,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#enableNetwork(int, boolean)} - * @throws Exception */ @Test public void testEnableNetwork() throws Exception { @@ -1497,7 +1490,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#disableNetwork(int)} - * @throws Exception */ @Test public void testDisableNetwork() throws Exception { @@ -1509,7 +1501,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#disconnect()} - * @throws Exception */ @Test public void testDisconnect() throws Exception { @@ -1520,7 +1511,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#reconnect()} - * @throws Exception */ @Test public void testReconnect() throws Exception { @@ -1531,7 +1521,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#reassociate()} - * @throws Exception */ @Test public void testReassociate() throws Exception { @@ -1542,7 +1531,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getSupportedFeatures()} - * @throws Exception */ @Test public void testGetSupportedFeatures() throws Exception { @@ -1569,7 +1557,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getControllerActivityEnergyInfo()} - * @throws Exception */ @Test public void testGetControllerActivityEnergyInfo() throws Exception { @@ -1582,7 +1569,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getConnectionInfo()} - * @throws Exception */ @Test public void testGetConnectionInfo() throws Exception { @@ -1594,7 +1580,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#isDualModeSupported()} ()} - * @throws Exception */ @Test public void testIsDualModeSupported() throws Exception { @@ -1605,7 +1590,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#isDualBandSupported()} - * @throws Exception */ @Test public void testIsDualBandSupported() throws Exception { @@ -1616,7 +1600,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getDhcpInfo()} - * @throws Exception */ @Test public void testGetDhcpInfo() throws Exception { @@ -1629,7 +1612,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#setWifiEnabled(boolean)} - * @throws Exception */ @Test public void testSetWifiEnabled() throws Exception { |