diff options
137 files changed, 1425 insertions, 689 deletions
diff --git a/Android.bp b/Android.bp index 1aaa6044111a..e7845467e758 100644 --- a/Android.bp +++ b/Android.bp @@ -608,7 +608,7 @@ filegroup { java_library { name: "framework-annotations-lib", srcs: [ ":framework-annotations" ], - sdk_version: "current", + sdk_version: "core_current", } filegroup { @@ -739,7 +739,7 @@ java_library { "core/proto/android/privacy.proto", "core/proto/android/section.proto", ], - sdk_version: "current", + sdk_version: "9", srcs: [ "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", @@ -762,6 +762,7 @@ java_library { "core/proto/android/privacy.proto", "core/proto/android/section.proto", ], + sdk_version: "core_current", // Protos have lots of MissingOverride and similar. errorprone: { javacflags: ["-XepDisableAllChecks"], diff --git a/ApiDocs.bp b/ApiDocs.bp index bd4a32bfab7a..60f56de73598 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -79,7 +79,7 @@ stubs_defaults { "sdk-dir", "api-versions-jars-dir", ], - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], @@ -101,7 +101,7 @@ droidstubs { arg_files: [ "core/res/AndroidManifest.xml", ], - args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ", + args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ", write_sdk_values: true, } diff --git a/METADATA b/METADATA new file mode 100644 index 000000000000..d97975ca3b99 --- /dev/null +++ b/METADATA @@ -0,0 +1,3 @@ +third_party { + license_type: NOTICE +} diff --git a/StubLibraries.bp b/StubLibraries.bp index 74b0524f4fd2..4a77463160f6 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -48,13 +48,12 @@ stubs_defaults { ":opt-telephony-srcs", ":opt-net-voip-srcs", ":art-module-public-api-stubs-source", - ":conscrypt.module.public.api.stubs.source", ":android_icu4j_public_api_files", ], libs: ["framework-internal-utils"], installable: false, annotations_enabled: true, - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], @@ -65,7 +64,10 @@ stubs_defaults { stubs_defaults { name: "metalava-full-api-stubs-default", defaults: ["metalava-base-api-stubs-default"], - srcs: [":framework-updatable-sources"], + srcs: [ + ":conscrypt.module.public.api.stubs.source", + ":framework-updatable-sources", + ], sdk_version: "core_platform", } @@ -97,13 +99,13 @@ droidstubs { removed_api_file: "api/removed.txt", }, last_released: { - api_file: ":last-released-public-api", + api_file: ":android.api.public.latest", removed_api_file: "api/removed.txt", baseline_file: ":public-api-incompatibilities-with-last-released", }, api_lint: { enabled: true, - new_since: ":last-released-public-api", + new_since: ":android.api.public.latest", baseline_file: "api/lint-baseline.txt", }, }, @@ -139,13 +141,13 @@ droidstubs { removed_api_file: "api/system-removed.txt", }, last_released: { - api_file: ":last-released-system-api", + api_file: ":android.api.system.latest", removed_api_file: "api/system-removed.txt", baseline_file: ":system-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-system-api", + new_since: ":android.api.system.latest", baseline_file: "api/system-lint-baseline.txt", }, }, @@ -207,13 +209,13 @@ droidstubs { removed_api_file: "api/module-lib-removed.txt", }, last_released: { - api_file: ":last-released-module-lib-api", + api_file: ":android.api.module-lib.latest", removed_api_file: "api/module-lib-removed.txt", baseline_file: ":module-lib-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-module-lib-api", + new_since: ":android.api.module-lib.latest", baseline_file: "api/module-lib-lint-baseline.txt", }, }, @@ -314,7 +316,7 @@ droidstubs { installable: false, sdk_version: "core_platform", annotations_enabled: true, - previous_api: ":last-released-public-api", + previous_api: ":android.api.public.latest", merge_annotations_dirs: [ "metalava-manual", ], diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp index 707113b9672c..6a787116c005 100644 --- a/apex/sdkextensions/framework/Android.bp +++ b/apex/sdkextensions/framework/Android.bp @@ -48,7 +48,7 @@ stubs_defaults { name: "framework-sdkextensions-stubs-defaults", srcs: [ ":framework-sdkextensions-sources" ], libs: [ "framework-annotations-lib" ], - sdk_version: "system_current", + dist: { dest: "framework-sdkextensions.txt" }, } droidstubs { @@ -56,7 +56,7 @@ droidstubs { defaults: [ "framework-module-stubs-defaults-publicapi", "framework-sdkextensions-stubs-defaults", - ] + ], } droidstubs { @@ -64,7 +64,7 @@ droidstubs { defaults: [ "framework-module-stubs-defaults-systemapi", "framework-sdkextensions-stubs-defaults", - ] + ], } droidstubs { @@ -72,7 +72,7 @@ droidstubs { defaults: [ "framework-module-api-defaults-module_libs_api", "framework-sdkextensions-stubs-defaults", - ] + ], } droidstubs { @@ -80,7 +80,7 @@ droidstubs { defaults: [ "framework-module-stubs-defaults-module_libs_api", "framework-sdkextensions-stubs-defaults", - ] + ], } java_library { @@ -90,7 +90,8 @@ java_library { visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] + ], + dist: { dest: "framework-sdkextensions.jar" }, } java_library { @@ -100,7 +101,8 @@ java_library { visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] + ], + dist: { dest: "framework-sdkextensions.jar" }, } java_library { @@ -110,5 +112,6 @@ java_library { visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK - ] + ], + dist: { dest: "framework-sdkextensions.jar" }, } diff --git a/api/current.txt b/api/current.txt index d5fe8cd585e8..e63cb45e5e30 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29175,6 +29175,7 @@ package android.net { field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf field public static final int NET_CAPABILITY_RCS = 8; // 0x8 field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 + field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19 field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 @@ -45341,12 +45342,14 @@ package android.telephony { public class MbmsDownloadSession implements java.lang.AutoCloseable { method public void addProgressListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.DownloadProgressListener); + method public void addServiceAnnouncementFile(@NonNull byte[]); method public void addStatusListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.DownloadStatusListener); method public void cancelDownload(@NonNull android.telephony.mbms.DownloadRequest); method public void close(); method public static android.telephony.MbmsDownloadSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsDownloadSessionCallback); method @Nullable public static android.telephony.MbmsDownloadSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, int, @NonNull android.telephony.mbms.MbmsDownloadSessionCallback); method public void download(@NonNull android.telephony.mbms.DownloadRequest); + method public static int getMaximumServiceAnnouncementFileSize(); method @Nullable public java.io.File getTempFileRootDirectory(); method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(); method public void removeProgressListener(@NonNull android.telephony.mbms.DownloadRequest, @NonNull android.telephony.mbms.DownloadProgressListener); @@ -46953,6 +46956,7 @@ package android.telephony.mbms { public static class MbmsErrors.DownloadErrors { field public static final int ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT = 401; // 0x191 + field public static final int ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE = 404; // 0x194 field public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402; // 0x192 field public static final int ERROR_UNKNOWN_FILE_INFO = 403; // 0x193 } diff --git a/api/system-current.txt b/api/system-current.txt index 3b349bf6a9bb..4a1bf0d803a6 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -10320,6 +10320,7 @@ package android.telephony.mbms.vendor { public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface { ctor public MbmsDownloadServiceBase(); method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; + method public int addServiceAnnouncementFile(int, @NonNull byte[]); method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; method public android.os.IBinder asBinder(); method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; diff --git a/api/test-current.txt b/api/test-current.txt index 31b4ca82c68e..d3e1e8c4c2bc 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4098,6 +4098,7 @@ package android.telephony.mbms.vendor { public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface { ctor public MbmsDownloadServiceBase(); method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; + method public int addServiceAnnouncementFile(int, @NonNull byte[]); method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; method public android.os.IBinder asBinder(); method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc index 9f4f314a4324..ad4de0ab737a 100644 --- a/cmds/bootanimation/bootanim.rc +++ b/cmds/bootanimation/bootanim.rc @@ -5,4 +5,4 @@ service bootanim /system/bin/bootanimation disabled oneshot ioprio rt 0 - writepid /dev/stune/top-app/tasks + task_profiles MaxPerformance diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 72a8bea9a918..24fbf21f463f 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -382,7 +382,7 @@ cc_benchmark { // ==== java proto device library (for test only) ============================== java_library { name: "statsdprotolite", - sdk_version: "core_platform", + sdk_version: "core_current", proto: { type: "lite", include_dirs: ["external/protobuf/src"], diff --git a/core/java/android/annotation/CallbackExecutor.java b/core/java/android/annotation/CallbackExecutor.java index 5671a3d2b6d6..4258f730eb16 100644 --- a/core/java/android/annotation/CallbackExecutor.java +++ b/core/java/android/annotation/CallbackExecutor.java @@ -19,9 +19,6 @@ package android.annotation; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.content.Context; -import android.os.AsyncTask; - import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.concurrent.Executor; @@ -30,9 +27,10 @@ import java.util.concurrent.Executor; * @paramDoc Callback and listener events are dispatched through this * {@link Executor}, providing an easy way to control which thread is * used. To dispatch events through the main thread of your - * application, you can use {@link Context#getMainExecutor()}. To - * dispatch events through a shared thread pool, you can use - * {@link AsyncTask#THREAD_POOL_EXECUTOR}. + * application, you can use + * {@link android.content.Context#getMainExecutor() Context.getMainExecutor()}. + * To dispatch events through a shared thread pool, you can use + * {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR AsyncTask#THREAD_POOL_EXECUTOR}. * @hide */ @Retention(SOURCE) diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java index e5c0654f8bbe..1d89e31b2b99 100644 --- a/core/java/android/annotation/RequiresPermission.java +++ b/core/java/android/annotation/RequiresPermission.java @@ -15,9 +15,6 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; @@ -25,6 +22,9 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Denotes that the annotated element requires (or may require) one or more permissions. * <p/> @@ -55,7 +55,8 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; * <p> * When specified on a parameter, the annotation indicates that the method requires * a permission which depends on the value of the parameter. For example, consider - * {@link android.app.Activity#startActivity(android.content.Intent)}: + * {@link android.app.Activity#startActivity(android.content.Intent) + * Activity#startActivity(Intent)}: * <pre>{@code * public void startActivity(@RequiresPermission Intent intent) { ... } * }</pre> diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b6f61a2b8f01..4f1d7f2c761c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3618,7 +3618,6 @@ public class Activity extends ContextThemeWrapper * To receive this callback, you must return true from onKeyDown for the current * event stream. * - * @see KeyEvent.Callback#onKeyLongPress() * @see KeyEvent.Callback#onKeyLongPress(int, KeyEvent) */ public boolean onKeyLongPress(int keyCode, KeyEvent event) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index bdaa44034565..85cd21dec283 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2082,8 +2082,7 @@ public class ActivityManager { * has access to it. * * @see ActivityOptions#setLaunchDisplayId(int) - * @see android.view.Display.FLAG_PRIVATE - * @see android.view.Display.TYPE_VIRTUAL + * @see android.view.Display#FLAG_PRIVATE * * @param context Source context, from which an activity will be started. * @param displayId Target display id. diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 7a560c07a365..0feed7383020 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -299,7 +299,8 @@ interface IActivityManager { void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask, in StrictMode.ViolationInfo crashInfo); boolean isTopActivityImmersive(); - void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message); + void crashApplication(int uid, int initialPid, in String packageName, int userId, + in String message, boolean force); @UnsupportedAppUsage String getProviderMimeType(in Uri uri, int userId); // Cause the specified process to dump the specified heap. diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index cff6411c882c..2049b3408c64 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -729,7 +729,7 @@ public class Instrumentation { * a non-null value if the intent needs to be intercepted. * * <p> Whenever a new activity is started, this method will be called on instances created - * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case + * using {@link #ActivityMonitor()} to check if there is a match. In case * of a match, the activity start will be blocked and the returned result will be used. * * @param intent The intent used for starting the activity. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cefec441e702..f2b2635c8636 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3437,7 +3437,7 @@ public class Notification implements Parcelable } /** - * @deprecated use {@link Notification.Builder#Notification.Builder(Context, String)} + * @deprecated use {@link #Builder(Context, String)} * instead. All posted Notifications must specify a NotificationChannel Id. */ @Deprecated @@ -7071,7 +7071,7 @@ public class Notification implements Parcelable * Should be unique amongst all individuals in the conversation, and should be * consistent during re-posts of the notification. * - * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence) + * @see Message#Message(CharSequence, long, CharSequence) * * @return this object for method chaining * @@ -7091,7 +7091,7 @@ public class Notification implements Parcelable * Should be <code>null</code> for messages by the current user, in which case * the platform will insert the user set in {@code MessagingStyle(Person)}. * - * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence) + * @see Message#Message(CharSequence, long, CharSequence) * * @return this object for method chaining */ diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index e25558f16f26..925586feaf1d 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -294,7 +294,7 @@ public class NotificationManager { * </p> * </p> * - * @see {@link #addAutomaticZenRule(AutomaticZenRule)} + * @see #addAutomaticZenRule(AutomaticZenRule) */ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_AUTOMATIC_ZEN_RULE = diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index dc815b631e46..067a35fe1aba 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -803,7 +803,7 @@ public class BackupManager { * has a work profile that was restored from another work profile with serial number * {@code ancestralSerialNumber}. * - * @see UserManager#getSerialNumberForUser(UserHandle) + * @see android.os.UserManager#getSerialNumberForUser(UserHandle) */ @Nullable public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) { diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java index 08b1c2b9f548..ec9c57466310 100644 --- a/core/java/android/app/job/JobScheduler.java +++ b/core/java/android/app/job/JobScheduler.java @@ -41,7 +41,7 @@ import java.util.List; * system will execute this job on your application's {@link android.app.job.JobService}. * You identify the service component that implements the logic for your job when you * construct the JobInfo using - * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}. + * {@link android.app.job.JobInfo.Builder#Builder(int,android.content.ComponentName)}. * </p> * <p> * The framework will be intelligent about when it executes jobs, and attempt to batch @@ -147,7 +147,7 @@ public abstract class JobScheduler { * method is ignored. * * @param jobId unique identifier for the job to be canceled, as supplied to - * {@link JobInfo.Builder#JobInfo.Builder(int, android.content.ComponentName) + * {@link JobInfo.Builder#Builder(int, android.content.ComponentName) * JobInfo.Builder(int, android.content.ComponentName)}. */ public abstract void cancel(int jobId); diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java index 2eb9459af877..4e5443a18bf2 100644 --- a/core/java/android/app/role/RoleManager.java +++ b/core/java/android/app/role/RoleManager.java @@ -102,8 +102,6 @@ public final class RoleManager { /** * The name of the emergency role - * - * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE */ public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY"; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 3ed585c18e57..6e0ce3ff032a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3519,7 +3519,6 @@ public abstract class Context { * @see android.telephony.CarrierConfigManager * @see #EUICC_SERVICE * @see android.telephony.euicc.EuiccManager - * @see #MMS_SERVICE * @see android.telephony.MmsManager * @see #INPUT_METHOD_SERVICE * @see android.view.inputmethod.InputMethodManager diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index d5dadbff419f..7e8bb08e0086 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -16,8 +16,6 @@ package android.hardware.hdmi; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -31,7 +29,7 @@ import android.annotation.SystemService; import android.content.Context; import android.content.pm.PackageManager; import android.os.RemoteException; -import android.os.SystemProperties; +import android.sysprop.HdmiProperties; import android.util.ArrayMap; import android.util.Log; @@ -316,8 +314,7 @@ public final class HdmiControlManager { mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK); mHasAudioSystemDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mHasSwitchDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH); - mIsSwitchDevice = SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + mIsSwitchDevice = HdmiProperties.is_switch().orElse(false); } private static boolean hasDeviceType(int[] types, int type) { diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java index afa63039b6f7..836624beb3b2 100644 --- a/core/java/android/net/Ikev2VpnProfile.java +++ b/core/java/android/net/Ikev2VpnProfile.java @@ -803,7 +803,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { * @param isMetered {@code true} if the VPN network should be treated as metered regardless * of underlying network meteredness. Defaults to {@code true}. * @return this {@link Builder} object to facilitate chaining of method calls - * @see NetworkCapabilities.NET_CAPABILITY_NOT_METERED + * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED */ @NonNull public Builder setMetered(boolean isMetered) { diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java index 68a39355198b..70c4a7235b9d 100644 --- a/core/java/android/net/MatchAllNetworkSpecifier.java +++ b/core/java/android/net/MatchAllNetworkSpecifier.java @@ -43,7 +43,8 @@ public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements } /** @hide */ - public boolean satisfiedBy(NetworkSpecifier other) { + @Override + public boolean canBeSatisfiedBy(NetworkSpecifier other) { /* * The method is called by a NetworkRequest to see if it is satisfied by a proposed * network (e.g. as offered by a network factory). Since MatchAllNetweorkSpecifier must diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index fea3245784b2..74eced796b04 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -169,6 +169,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_OEM_PAID, NET_CAPABILITY_MCX, NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, }) public @interface NetCapability { } @@ -336,8 +337,16 @@ public final class NetworkCapabilities implements Parcelable { @SystemApi public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; + /** + * This capability will be set for networks that are generally metered, but are currently + * unmetered, e.g., because the user is in a particular area. This capability can be changed at + * any time. When it is removed, applications are responsible for stopping any data transfer + * that should not occur on a metered network. + */ + public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -353,7 +362,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_NOT_CONGESTED) | (1 << NET_CAPABILITY_NOT_SUSPENDED) - | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED)); /** * Network capabilities that are not allowed in NetworkRequests. This exists because the @@ -424,6 +434,7 @@ public final class NetworkCapabilities implements Parcelable { */ private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) | (1 << NET_CAPABILITY_NOT_RESTRICTED) | (1 << NET_CAPABILITY_NOT_VPN) | (1 << NET_CAPABILITY_NOT_ROAMING) @@ -1866,6 +1877,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; case NET_CAPABILITY_MCX: return "MCX"; case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; + case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; default: return Integer.toString(capability); } } diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index c233ec0e52cf..6539e0563794 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; @@ -468,11 +469,13 @@ public class NetworkScoreManager { * * @param networks List of {@link ScoredNetwork} containing updated scores. */ + @SuppressLint("CallbackMethodName") void updateScores(@NonNull List<ScoredNetwork> networks); /** * Invokes when all the previously provided scores are no longer valid. */ + @SuppressLint("CallbackMethodName") void clearScores(); } diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 63e510733907..9c2c5b839302 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -836,7 +836,7 @@ public class VpnService extends Service { * @param isMetered {@code true} if VPN network should be treated as metered regardless of * underlying network meteredness * @return this {@link Builder} object to facilitate chaining method calls - * @see #setUnderlyingNetworks(Networks[]) + * @see #setUnderlyingNetworks(Network[]) * @see ConnectivityManager#isActiveNetworkMetered() */ @NonNull diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 3faaff73a0ea..81457074f2fc 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1015,7 +1015,6 @@ public final class StrictMode { * behaviors or empty states. Instead, apps should store data needed * while a user is locked under device protected storage areas. * - * @see Context#createCredentialProtectedStorageContext() * @see Context#createDeviceProtectedStorageContext() */ public @NonNull Builder detectCredentialProtectedWhileLocked() { diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 75b4724c7d26..890057371471 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -55,21 +55,16 @@ public abstract class VibrationEffect implements Parcelable { /** * A click effect. Use this effect as a baseline, as it's the most common type of click effect. - * - * @see #get(int) */ public static final int EFFECT_CLICK = Effect.CLICK; /** * A double click effect. - * - * @see #get(int) */ public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK; /** * A tick effect. This effect is less strong compared to {@link #EFFECT_CLICK}. - * @see #get(int) */ public static final int EFFECT_TICK = Effect.TICK; @@ -93,7 +88,6 @@ public abstract class VibrationEffect implements Parcelable { /** * A heavy click effect. This effect is stronger than {@link #EFFECT_CLICK}. - * @see #get(int) */ public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK; diff --git a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java index 12503f650ab5..89cd43003529 100644 --- a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java +++ b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java @@ -28,7 +28,6 @@ import android.content.Context; * store data needed while a user is locked under device protected storage * areas. * - * @see Context#createCredentialProtectedStorageContext() * @see Context#createDeviceProtectedStorageContext() */ public final class CredentialProtectedWhileLockedViolation extends Violation { diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 9c6c92ace483..17fae1cafe62 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -797,7 +797,6 @@ public final class CalendarContract { * to changes. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = @@ -1796,7 +1795,6 @@ public final class CalendarContract { * to changes. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = @@ -2010,7 +2008,6 @@ public final class CalendarContract { * {@link DevicePolicyManager#setCrossProfileCalendarPackages(ComponentName, Set)}. * * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName) - * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED */ @NonNull public static final Uri ENTERPRISE_CONTENT_URI = diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 4bbd213753c2..3980a5f75eda 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; -import android.content.ContentInterface; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -248,14 +247,14 @@ public final class DocumentsContract { * Get string array identifies the type or types of metadata returned * using DocumentsContract#getDocumentMetadata. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TYPES = "android:documentMetadataTypes"; /** * Get Exif information using DocumentsContract#getDocumentMetadata. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_EXIF = "android:documentExif"; @@ -263,7 +262,7 @@ public final class DocumentsContract { * Get total count of all documents currently stored under the given * directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TREE_COUNT = "android:metadataTreeCount"; @@ -271,7 +270,7 @@ public final class DocumentsContract { * Get total size of all documents currently stored under the given * directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents. * - * @see #getDocumentMetadata(ContentInterface, Uri) + * @see #getDocumentMetadata(ContentResolver, Uri) */ public static final String METADATA_TREE_SIZE = "android:metadataTreeSize"; @@ -395,7 +394,7 @@ public final class DocumentsContract { * Flag indicating that a document can be represented as a thumbnail. * * @see #COLUMN_FLAGS - * @see DocumentsContract#getDocumentThumbnail(ContentInterface, Uri, + * @see DocumentsContract#getDocumentThumbnail(ContentResolver, Uri, * Point, CancellationSignal) * @see DocumentsProvider#openDocumentThumbnail(String, Point, * android.os.CancellationSignal) @@ -421,7 +420,7 @@ public final class DocumentsContract { * Flag indicating that a document is deletable. * * @see #COLUMN_FLAGS - * @see DocumentsContract#deleteDocument(ContentInterface, Uri) + * @see DocumentsContract#deleteDocument(ContentResolver, Uri) * @see DocumentsProvider#deleteDocument(String) */ public static final int FLAG_SUPPORTS_DELETE = 1 << 2; @@ -459,7 +458,7 @@ public final class DocumentsContract { * Flag indicating that a document can be renamed. * * @see #COLUMN_FLAGS - * @see DocumentsContract#renameDocument(ContentInterface, Uri, String) + * @see DocumentsContract#renameDocument(ContentResolver, Uri, String) * @see DocumentsProvider#renameDocument(String, String) */ public static final int FLAG_SUPPORTS_RENAME = 1 << 6; @@ -469,7 +468,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#copyDocument(ContentInterface, Uri, Uri) + * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#copyDocument(String, String) */ public static final int FLAG_SUPPORTS_COPY = 1 << 7; @@ -479,7 +478,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#moveDocument(ContentInterface, Uri, Uri, Uri) + * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri) * @see DocumentsProvider#moveDocument(String, String, String) */ public static final int FLAG_SUPPORTS_MOVE = 1 << 8; @@ -503,7 +502,7 @@ public final class DocumentsContract { * Flag indicating that a document can be removed from a parent. * * @see #COLUMN_FLAGS - * @see DocumentsContract#removeDocument(ContentInterface, Uri, Uri) + * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#removeDocument(String, String) */ public static final int FLAG_SUPPORTS_REMOVE = 1 << 10; @@ -539,7 +538,7 @@ public final class DocumentsContract { * using DocumentsContract#getDocumentMetadata * * @see #COLUMN_FLAGS - * @see DocumentsContract#getDocumentMetadata(ContentInterface, Uri) + * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri) */ public static final int FLAG_SUPPORTS_METADATA = 1 << 14; } @@ -721,7 +720,7 @@ public final class DocumentsContract { * Flag indicating that this root can be ejected. * * @see #COLUMN_FLAGS - * @see DocumentsContract#ejectRoot(ContentInterface, Uri) + * @see DocumentsContract#ejectRoot(ContentResolver, Uri) * @see DocumentsProvider#ejectRoot(String) */ public static final int FLAG_SUPPORTS_EJECT = 1 << 5; diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java index c28d2bbe30ea..e274460cdf03 100644 --- a/core/java/android/service/autofill/CustomDescription.java +++ b/core/java/android/service/autofill/CustomDescription.java @@ -262,7 +262,7 @@ public final class CustomDescription implements Parcelable { * * @param condition condition used to trigger the updates. * @param updates actions to be applied to the - * {@link #CustomDescription.Builder(RemoteViews) template presentation} when the condition + * {@link #Builder(RemoteViews) template presentation} when the condition * is satisfied. * * @return this builder diff --git a/core/java/android/service/autofill/ImageTransformation.java b/core/java/android/service/autofill/ImageTransformation.java index 12376e85e63e..974f0ead9d19 100644 --- a/core/java/android/service/autofill/ImageTransformation.java +++ b/core/java/android/service/autofill/ImageTransformation.java @@ -123,7 +123,7 @@ public final class ImageTransformation extends InternalTransformation implements * {@link RemoteViews presentation} must contain a {@link ImageView} child with that id. * * @deprecated use - * {@link #ImageTransformation.Builder(AutofillId, Pattern, int, CharSequence)} instead. + * {@link #Builder(AutofillId, Pattern, int, CharSequence)} instead. */ @Deprecated public Builder(@NonNull AutofillId id, @NonNull Pattern regex, @DrawableRes int resId) { diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index 94b9d050a44d..3a70befb3558 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -628,7 +628,7 @@ public final class SaveInfo implements Parcelable { * * <p>The sanitizer can also be used as an alternative for a * {@link #setValidator(Validator) validator}. If any of the {@code ids} is a - * {@link #SaveInfo.Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails + * {@link #Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails * because of it, then the save UI is not shown. * * @param sanitizer an implementation provided by the Android System. @@ -686,7 +686,7 @@ public final class SaveInfo implements Parcelable { * Builds a new {@link SaveInfo} instance. * * @throws IllegalStateException if no - * {@link #SaveInfo.Builder(int, AutofillId[]) required ids}, + * {@link #Builder(int, AutofillId[]) required ids}, * or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE} * were set */ diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 7267db3b3a1f..d64077525905 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -379,8 +379,6 @@ public class PhoneStateListener { * * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). - * - * @see #onEmergencyNumberListChanged */ public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000; @@ -459,7 +457,7 @@ public class PhoneStateListener { * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @see #onRegistrationFailed() + * @see #onRegistrationFailed */ @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000; @@ -470,7 +468,7 @@ public class PhoneStateListener { * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @see #onBarringInfoChanged() + * @see #onBarringInfoChanged */ @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_BARRING_INFO = 0x80000000; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fe60bba92739..40dfcfc391a0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -25801,9 +25801,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Returns the View object that had been passed to the - * {@link #View.DragShadowBuilder(View)} + * {@link #DragShadowBuilder(View)} * constructor. If that View parameter was {@code null} or if the - * {@link #View.DragShadowBuilder()} + * {@link #DragShadowBuilder()} * constructor was used to instantiate the builder object, this method will return * null. * diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index d9d92788a434..859b137dc2ce 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -614,7 +614,6 @@ public interface WindowManager extends ViewManager { * @see #TYPE_TOAST * @see #TYPE_SYSTEM_OVERLAY * @see #TYPE_PRIORITY_PHONE - * @see #TYPE_STATUS_BAR_PANEL * @see #TYPE_SYSTEM_DIALOG * @see #TYPE_KEYGUARD_DIALOG * @see #TYPE_SYSTEM_ERROR diff --git a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java index 42a892dedf4d..903fc13a03ea 100644 --- a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java +++ b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; /** * An inspection companion provider that finds companions as inner classes or generated code. - * - * @see android.processor.view.inspector.PlatformInspectableProcessor */ public class StaticInspectionCompanionProvider implements InspectionCompanionProvider { /** diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java index 8182d60ef459..8b659f927633 100644 --- a/core/java/com/android/internal/os/RoSystemProperties.java +++ b/core/java/com/android/internal/os/RoSystemProperties.java @@ -18,6 +18,7 @@ package com.android.internal.os; import android.os.SystemProperties; import android.sysprop.CryptoProperties; +import android.sysprop.HdmiProperties; /** * This is a cache of various ro.* properties so that they can be read just once @@ -37,16 +38,7 @@ public class RoSystemProperties { * mode is off. */ public static final boolean CEC_AUDIO_DEVICE_FORWARD_VOLUME_KEYS_SYSTEM_AUDIO_MODE_OFF = - SystemProperties.getBoolean( - "ro.hdmi.cec_audio_device_forward_volume_keys_system_audio_mode_off", false); - - /** - * Property to indicate if the current device is a cec switch device. - * - * <p> Default is false. - */ - public static final String PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH = - "ro.hdmi.property_is_device_hdmi_cec_switch"; + HdmiProperties.forward_volume_keys_when_system_audio_mode_off().orElse(false); // ------ ro.config.* -------- // public static final boolean CONFIG_AVOID_GFX_ACCEL = diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index ca4735ec665a..8fc1758c44dc 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -35,6 +35,7 @@ static const char* kPathWhitelist[] = { "/apex/com.android.conscrypt/javalib/conscrypt.jar", "/apex/com.android.ipsec/javalib/ike.jar", + "/apex/com.android.i18n/javalib/core-icu4j.jar", "/apex/com.android.media/javalib/updatable-media.jar", "/apex/com.android.sdkext/javalib/framework-sdkextensions.jar", "/apex/com.android.tethering/javalib/framework-tethering.jar", @@ -81,11 +82,18 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { } // Framework jars are allowed. - static const char* kFrameworksPrefix = "/system/framework/"; + static const char* kFrameworksPrefix[] = { + "/system/framework/", + "/system_ext/framework/", + }; + static const char* kJarSuffix = ".jar"; - if (android::base::StartsWith(path, kFrameworksPrefix) - && android::base::EndsWith(path, kJarSuffix)) { - return true; + + for (const auto& frameworks_prefix : kFrameworksPrefix) { + if (android::base::StartsWith(path, frameworks_prefix) + && android::base::EndsWith(path, kJarSuffix)) { + return true; + } } // Jars from the ART APEX are allowed. diff --git a/core/res/res/values-mcc334-mnc020/config.xml b/core/res/res/values-mcc334-mnc020/config.xml index 0970517835b6..82b3ee6448e3 100644 --- a/core/res/res/values-mcc334-mnc020/config.xml +++ b/core/res/res/values-mcc334-mnc020/config.xml @@ -18,4 +18,7 @@ --> <resources> <bool name="config_use_sim_language_file">false</bool> -</resources>
\ No newline at end of file + + <bool name="config_pdp_reject_enable_retry">true</bool> + <integer name="config_pdp_reject_retry_delay_ms">45000</integer> +</resources> diff --git a/core/res/res/values-mcc334-mnc020/strings.xml b/core/res/res/values-mcc334-mnc020/strings.xml new file mode 100644 index 000000000000..91b560aeef7e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2020, 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title"></string> + <string name="config_pdp_reject_user_authentication_failed">AUTHENTICATION FAILURE -29-.</string> + <string name="config_pdp_reject_service_not_subscribed">NOT SUBSCRIBED TO SERVICE -33-.</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed">Multiple PDN connections for a given APN not allowed -55-.</string> +</resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2f301946402b..b908ab8b709e 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4742,7 +4742,7 @@ May be a string value, which is a comma-separated language tag list, such as "ja-JP,zh-CN". When not specified or an empty string is given, it will fallback to the default one. {@see android.os.LocaleList#forLanguageTags(String)} - {@see android.text.TextView#setTextLocales(android.os.LocaleList)} --> + {@see android.widget.TextView#setTextLocales(android.os.LocaleList)} --> <attr name="textLocale" format="string" /> <!-- Text color for links. --> <attr name="textColorLink" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d7ab426ec9dd..6cbea4074484 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4367,4 +4367,9 @@ <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing check after reboot or airplane mode toggling --> <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool> + + <!-- pdp data retry for cause 29, 33 and 55--> + <bool name="config_pdp_reject_enable_retry">false</bool> + <!--pdp data reject retry delay in ms--> + <integer name="config_pdp_reject_retry_delay_ms">-1</integer> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7f463807e1e9..12fc1bb8553c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5653,4 +5653,10 @@ ul.</string> <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS">IMPI unlock successful.</string> <!-- Success message displayed on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS">Network subset service provider unlock successful.</string> + + <!-- pdp data reject dialog string for cause 29, 33 and 55--> + <string name="config_pdp_reject_dialog_title"></string> + <string name="config_pdp_reject_user_authentication_failed"></string> + <string name="config_pdp_reject_service_not_subscribed"></string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed"></string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d65d09233052..a844d8ae5a61 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3872,4 +3872,12 @@ <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" /> <java-symbol type="bool" name="reset_geo_fencing_check_after_boot_or_apm" /> + + <!-- For Pdn throttle feature --> + <java-symbol type="bool" name="config_pdp_reject_enable_retry" /> + <java-symbol type="integer" name="config_pdp_reject_retry_delay_ms" /> + <java-symbol type="string" name="config_pdp_reject_dialog_title" /> + <java-symbol type="string" name="config_pdp_reject_user_authentication_failed" /> + <java-symbol type="string" name="config_pdp_reject_service_not_subscribed" /> + <java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" /> </resources> diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index ae7fe6c46f2f..c3c56dbbc6aa 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -998,7 +998,7 @@ public final class RenderNode { * Sets the rotation value for the display list around the Z axis. * * @param rotation The rotation value of the display list, in degrees - * @see View#setRotationZ(float) + * @see View#setRotation(float) * @see #getRotationZ() * @return True if the value changed, false if the new value was the same as the previous value. */ diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index e70529b6cd1a..9cf12f121e0a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -617,7 +617,7 @@ public abstract class Drawable { * {@link #setTintList(ColorStateList) tint}. * </p> * - * @see {@link #setColorFilter(ColorFilter)} } + * @see #setColorFilter(ColorFilter) * @deprecated use {@link #setColorFilter(ColorFilter)} with an instance * of {@link android.graphics.BlendModeColorFilter} */ diff --git a/graphics/java/android/graphics/fonts/FontStyle.java b/graphics/java/android/graphics/fonts/FontStyle.java index af517d623b01..09799fdf5a13 100644 --- a/graphics/java/android/graphics/fonts/FontStyle.java +++ b/graphics/java/android/graphics/fonts/FontStyle.java @@ -217,7 +217,7 @@ public final class FontStyle { /** * Gets the weight value * - * @see FontStyle#setWeight(int) + * @see #FontStyle(int, int) * @return a weight value */ public @IntRange(from = 0, to = 1000) int getWeight() { diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java index 54622c5e74df..babcfc3815f4 100644 --- a/graphics/java/android/graphics/text/LineBreaker.java +++ b/graphics/java/android/graphics/text/LineBreaker.java @@ -320,7 +320,7 @@ public class LineBreaker { /** * Returns the array of tab stops in pixels. * - * @see #setTabStops(float[], int) + * @see #setTabStops */ public @Nullable float[] getTabStops() { return mVariableTabStops; @@ -329,7 +329,7 @@ public class LineBreaker { /** * Returns the default tab stops in pixels. * - * @see #setTabStop(float[], int) + * @see #setTabStops */ public @Px @FloatRange(from = 0) float getDefaultTabStop() { return mDefaultTabStop; diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index e9bc8026d25e..d35642e362b1 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -1067,6 +1067,17 @@ public class KeyStore { return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); } + /** + * Notify keystore about the latest user locked state. This is to support keyguard-bound key. + */ + public void onUserLockedStateChanged(int userHandle, boolean locked) { + try { + mBinder.onKeyguardVisibilityChanged(locked, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed to update user locked state " + userHandle, e); + } + } + private class KeyAttestationCallbackResult { private KeystoreResponse keystoreResponse; private KeymasterCertificateChain certificateChain; diff --git a/media/Android.bp b/media/Android.bp index 43635684d9b3..a432c8d2a64d 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -26,8 +26,10 @@ java_library { installable: true, - // Make sure that the implementaion only relies on SDK or system APIs. + // TODO: build against stable API surface. Use core_platform for now to avoid + // link-check failure with exoplayer building against "current". sdk_version: "core_platform", + min_sdk_version: "29", libs: [ // The order matters. android_system_* library should come later. "framework_media_annotation", @@ -94,4 +96,5 @@ java_library { name: "framework_media_annotation", srcs: [":framework-media-annotation-srcs"], installable: false, + sdk_version: "core_current", } diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java index 4e7050129058..4c0850b675a8 100644 --- a/media/java/android/media/AudioFocusRequest.java +++ b/media/java/android/media/AudioFocusRequest.java @@ -80,9 +80,9 @@ import android.os.Looper; * <p>An {@code AudioFocusRequest} instance always contains one of the four types of requests * explained above. It is passed when building an {@code AudioFocusRequest} instance with its * builder in the {@link Builder} constructor - * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(int)}, or + * {@link AudioFocusRequest.Builder#Builder(int)}, or * with {@link AudioFocusRequest.Builder#setFocusGain(int)} after copying an existing instance with - * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(AudioFocusRequest)}. + * {@link AudioFocusRequest.Builder#Builder(AudioFocusRequest)}. * * <h3>Qualifying your focus request</h3> * <h4>Use case requiring a focus request</h4> diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 0ced68ef8695..babe0723dc01 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1098,7 +1098,7 @@ public class AudioTrack extends PlayerBase * Can only be called only if the AudioTrack is opened in offload mode * {@see Builder#setOffloadedPlayback(boolean)}. * Can only be called only if the AudioTrack is in state {@link #PLAYSTATE_PLAYING} - * {@see #getPlaystate()}. + * {@see #getPlayState()}. * Use this method in the same thread as any write() operation. */ public void setOffloadEndOfStream() { diff --git a/native/android/Android.bp b/native/android/Android.bp index ae8cb3a47a05..9f52d856ea75 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -93,6 +93,14 @@ cc_library_shared { }, } +// Header-only library used for atrace in platform NDK builds +cc_library_headers { + name: "libandroid_trace", + host_supported: true, + vendor_available: true, + export_include_dirs: ["trace"], +} + // Network library. cc_library_shared { name: "libandroid_net", @@ -137,4 +145,4 @@ filegroup { "aidl/com/android/internal/compat/IPlatformCompatNative.aidl", ], path: "aidl", -}
\ No newline at end of file +} diff --git a/native/android/trace/android/trace.h b/native/android/trace/android/trace.h new file mode 100644 index 000000000000..4e569e566bc2 --- /dev/null +++ b/native/android/trace/android/trace.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 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. + */ +#ifndef ANDROID_ATRACE_HEADERS_H +#define ANDROID_ATRACE_HEADERS_H + +#include <cutils/trace.h> + +inline void ATrace_beginSection(const char* sectionName) { + atrace_begin(ATRACE_TAG_APP, sectionName); +} + +inline void ATrace_endSection() { + atrace_end(ATRACE_TAG_APP); +} + +#endif // ANDROID_ATRACE_HEADERS_H diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 688e8eb8f2e3..7c49c3f961c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -566,6 +566,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated); mRoundnessManager.setOnRoundingChangedCallback(this::invalidate); addOnExpandedHeightChangedListener(mRoundnessManager::setExpanded); + mLockscreenUserManager.addUserChangedListener(userId -> + updateSensitiveness(false /* animated */)); setOutlineProvider(mOutlineProvider); // Blocking helper manager wants to know the expanded state, update as well. @@ -4602,7 +4604,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void setHideSensitive(boolean hideSensitive, boolean animate) { + private void updateSensitiveness(boolean animate) { + boolean hideSensitive = mLockscreenUserManager.isAnyProfilePublicMode(); if (hideSensitive != mAmbientState.isHideSensitive()) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -5306,7 +5309,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd SysuiStatusBarStateController state = (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class); - setHideSensitive(publicMode, state.goingToFullShade() /* animate */); + updateSensitiveness(state.goingToFullShade() /* animate */); setDimmed(onKeyguard, state.fromShadeLocked() /* animate */); setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = getActivatedChild(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 31054260eb15..f2ed3e648220 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -57,6 +57,8 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; @@ -119,6 +121,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private MetricsLogger mMetricsLogger; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + private UserChangedListener mUserChangedListener; private TestableNotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; @@ -137,7 +141,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectTestDependency( NotificationBlockingHelperManager.class, mBlockingHelperManager); - mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState); + mDependency.injectTestDependency(NotificationLockscreenUserManager.class, + mLockscreenUserManager); + mDependency.injectTestDependency(StatusBarStateController.class, mBarState); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager); @@ -152,6 +158,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { NotificationShelf notificationShelf = mock(NotificationShelf.class); + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); // The actual class under test. You may need to work with this class directly when // testing anonymous class members of mStackScroller, like mMenuEventListener, @@ -174,6 +182,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); mStackScroller.setIconAreaController(mNotificationIconAreaController); + verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture()); + mUserChangedListener = userChangedCaptor.getValue(); // Stub out functionality that isn't necessary to test. doNothing().when(mBar) @@ -247,6 +257,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testOnStatePostChange_verifyIfProfileIsPublic() { + mUserChangedListener.onUserChanged(0); + verify(mLockscreenUserManager).isAnyProfilePublicMode(); + } + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 27297c44573c..29660a9c4dce 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -27,7 +27,7 @@ java_defaults { "androidx.annotation_annotation", "netd_aidl_interface-V3-java", "netlink-client", - "networkstack-aidl-interfaces-unstable-java", + "networkstack-aidl-interfaces-java", "android.hardware.tetheroffload.config-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", "net-utils-framework-common", @@ -50,6 +50,11 @@ android_library { cc_library { name: "libtetherutilsjni", sdk_version: "current", + apex_available: [ + "//apex_available:platform", // Used by InProcessTethering + "com.android.tethering", + ], + min_sdk_version: "current", srcs: [ "jni/android_net_util_TetheringUtils.cpp", ], @@ -108,6 +113,7 @@ android_app { manifest: "AndroidManifest_InProcess.xml", // InProcessTethering is a replacement for Tethering overrides: ["Tethering"], + apex_available: ["com.android.tethering"], } // Updatable tethering packaged as an application @@ -121,4 +127,5 @@ android_app { // The permission configuration *must* be included to ensure security of the device required: ["NetworkPermissionConfig"], apex_available: ["com.android.tethering"], + min_sdk_version: "current", } diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp index 24df5f696077..67097a79e5c0 100644 --- a/packages/Tethering/apex/Android.bp +++ b/packages/Tethering/apex/Android.bp @@ -17,7 +17,7 @@ apex { name: "com.android.tethering", updatable: true, - min_sdk_version: "R", + min_sdk_version: "current", java_libs: ["framework-tethering"], apps: ["Tethering"], manifest: "manifest.json", @@ -36,3 +36,12 @@ android_app_certificate { name: "com.android.tethering.certificate", certificate: "com.android.tethering", } + +override_apex { + name: "com.android.tethering.inprocess", + base: "com.android.tethering", + package_name: "com.android.tethering.inprocess", + apps: [ + "InProcessTethering", + ], +} diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index ee6b9f12f9d2..7ac9d251e1bb 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -37,6 +37,12 @@ aidl_interface { cpp: { enabled: false, }, + java: { + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], + }, }, } @@ -67,6 +73,7 @@ java_library { stubs_defaults { name: "framework-tethering-stubs-defaults", srcs: [":framework-tethering-srcs"], + dist: { dest: "framework-tethering.txt" }, } filegroup { @@ -123,16 +130,19 @@ java_library { name: "framework-tethering-stubs-publicapi", srcs: [":framework-tethering-stubs-srcs-publicapi"], defaults: ["framework-module-stubs-lib-defaults-publicapi"], + dist: { dest: "framework-tethering.jar" }, } java_library { name: "framework-tethering-stubs-systemapi", srcs: [":framework-tethering-stubs-srcs-systemapi"], defaults: ["framework-module-stubs-lib-defaults-systemapi"], + dist: { dest: "framework-tethering.jar" }, } java_library { name: "framework-tethering-stubs-module_libs_api", srcs: [":framework-tethering-stubs-srcs-module_libs_api"], - defaults: ["framework-module-stubs-lib-defaults-systemapi"], + defaults: ["framework-module-stubs-lib-defaults-module_libs_api"], + dist: { dest: "framework-tethering.jar" }, } diff --git a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml index 2a7330098faf..d074f1569933 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (5030042590486713460) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (3843613362272973447) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) --> - <skip /> + <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string> + <string name="no_upstream_notification_message" msgid="3843613362272973447">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string> + <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिङ निष्क्रिय पार्नुहोस्"</string> + <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हटस्पट वा टेदरिङ सक्रिय छ"</string> <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string> </resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml index ea04821e33bd..f4b15aab19b7 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (5030042590486713460) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (3843613362272973447) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) --> - <skip /> + <string name="no_upstream_notification_title" msgid="5030042590486713460">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string> + <string name="no_upstream_notification_message" msgid="3843613362272973447">"சாதனங்களால் இணைய முடியவில்லை"</string> + <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"இணைப்பு முறையை ஆஃப் செய்"</string> + <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string> <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string> </resources> diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml index 05b90692ea7b..528a1e52925c 100644 --- a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml @@ -16,9 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過數據連線連上網際網路"</string> + <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過網路共用連上網際網路"</string> <string name="no_upstream_notification_message" msgid="3843613362272973447">"裝置無法連線"</string> - <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉數據連線"</string> - <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"無線基地台或數據連線已開啟"</string> + <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉網路共用"</string> + <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"無線基地台或網路共用已開啟"</string> <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"使用漫遊服務可能須支付額外費用"</string> </resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml index 617c50dd0ce8..1503244f5000 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (611650570559011140) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (6508394877641864863) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) --> - <skip /> + <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string> + <string name="no_upstream_notification_message" msgid="6508394877641864863">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string> + <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिङ निष्क्रिय पार्नुहोस्"</string> + <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हटस्पट वा टेदरिङ सक्रिय छ"</string> <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string> </resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml index 0e437593ee87..2ea2467e5879 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml @@ -16,13 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for no_upstream_notification_title (611650570559011140) --> - <skip /> - <!-- no translation found for no_upstream_notification_message (6508394877641864863) --> - <skip /> - <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) --> - <skip /> - <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) --> - <skip /> + <string name="no_upstream_notification_title" msgid="611650570559011140">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string> + <string name="no_upstream_notification_message" msgid="6508394877641864863">"சாதனங்களால் இணைய முடியவில்லை"</string> + <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"இணைப்பு முறையை ஆஃப் செய்"</string> + <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string> <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string> </resources> diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml index ea01b943fbe8..cd653df1dac6 100644 --- a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml @@ -16,9 +16,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過數據連線連上網際網路"</string> + <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過網路共用連上網際網路"</string> <string name="no_upstream_notification_message" msgid="6508394877641864863">"裝置無法連線"</string> - <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉數據連線"</string> - <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"無線基地台或數據連線已開啟"</string> + <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉網路共用"</string> + <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"無線基地台或網路共用已開啟"</string> <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"使用漫遊服務可能須支付額外費用"</string> </resources> diff --git a/packages/Tethering/res/values-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml index 9d738a76eb0e..50a50bf7a996 100644 --- a/packages/Tethering/res/values-zh-rTW/strings.xml +++ b/packages/Tethering/res/values-zh-rTW/strings.xml @@ -16,11 +16,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="tethered_notification_title" msgid="6426563586025792944">"數據連線或無線基地台已啟用"</string> + <string name="tethered_notification_title" msgid="6426563586025792944">"網路共用或無線基地台已啟用"</string> <string name="tethered_notification_message" msgid="64800879503420696">"輕觸即可進行設定。"</string> - <string name="disable_tether_notification_title" msgid="3004509127903564191">"數據連線已停用"</string> + <string name="disable_tether_notification_title" msgid="3004509127903564191">"網路共用已停用"</string> <string name="disable_tether_notification_message" msgid="6717523799293901476">"詳情請洽你的管理員"</string> - <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與數據連線狀態"</string> + <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與網路共用狀態"</string> <string name="no_upstream_notification_title" msgid="1204601824631788482"></string> <string name="no_upstream_notification_message" msgid="8586582938243032621"></string> <string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string> diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml index effc24ac4de5..c99922196346 100644 --- a/packages/Tethering/res/values/config.xml +++ b/packages/Tethering/res/values/config.xml @@ -62,6 +62,13 @@ <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> + <!-- Used to config periodic polls tether offload stats from tethering offload HAL to make the + data warnings work. 5000(ms) by default. If the device doesn't want to poll tether + offload stats, this should be -1. Note that this setting could be override by + runtime resource overlays. + --> + <integer translatable="false" name="config_tether_offload_poll_interval">5000</integer> + <!-- Array of ConnectivityManager.TYPE_{BLUETOOTH, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI, WIFI} values allowable for tethering. diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml index 16ae8ade19da..4c78a74d5358 100644 --- a/packages/Tethering/res/values/overlayable.xml +++ b/packages/Tethering/res/values/overlayable.xml @@ -24,6 +24,7 @@ <item type="array" name="config_tether_bluetooth_regexs"/> <item type="array" name="config_tether_dhcp_range"/> <item type="bool" name="config_tether_enable_legacy_dhcp_server"/> + <item type="integer" name="config_tether_offload_poll_interval"/> <item type="array" name="config_tether_upstream_types"/> <item type="bool" name="config_tether_upstream_automatic"/> <!-- Configuration values for tethering entitlement check --> diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java index 049a9f68bbd2..3c6e8d88ed13 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.util.SharedLog; import android.os.Bundle; +import android.os.ConditionVariable; import android.os.Handler; import android.os.Parcel; import android.os.PersistableBundle; @@ -45,13 +46,12 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; import android.telephony.CarrierConfigManager; -import android.util.ArraySet; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.StateMachine; import java.io.PrintWriter; +import java.util.BitSet; /** * Re-check tethering provisioning for enabled downstream tether types. @@ -73,39 +73,39 @@ public class EntitlementManager { private final ComponentName mSilentProvisioningService; private static final int MS_PER_HOUR = 60 * 60 * 1000; + private static final int DUMP_TIMEOUT = 10_000; - // The ArraySet contains enabled downstream types, ex: + // The BitSet is the bit map of each enabled downstream types, ex: // {@link TetheringManager.TETHERING_WIFI} // {@link TetheringManager.TETHERING_USB} // {@link TetheringManager.TETHERING_BLUETOOTH} - private final ArraySet<Integer> mCurrentTethers; + private final BitSet mCurrentDownstreams; + private final BitSet mExemptedDownstreams; private final Context mContext; - private final int mPermissionChangeMessageCode; private final SharedLog mLog; private final SparseIntArray mEntitlementCacheValue; private final Handler mHandler; - private final StateMachine mTetherMasterSM; // Key: TetheringManager.TETHERING_*(downstream). // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). - private final SparseIntArray mCellularPermitted; + private final SparseIntArray mCurrentEntitlementResults; + private final Runnable mPermissionChangeCallback; private PendingIntent mProvisioningRecheckAlarm; - private boolean mCellularUpstreamPermitted = true; + private boolean mLastCellularUpstreamPermitted = true; private boolean mUsingCellularAsUpstream = false; private boolean mNeedReRunProvisioningUi = false; private OnUiEntitlementFailedListener mListener; private TetheringConfigurationFetcher mFetcher; - public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, - int permissionChangeMessageCode) { - + public EntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { mContext = ctx; mLog = log.forSubComponent(TAG); - mCurrentTethers = new ArraySet<Integer>(); - mCellularPermitted = new SparseIntArray(); + mCurrentDownstreams = new BitSet(); + mExemptedDownstreams = new BitSet(); + mCurrentEntitlementResults = new SparseIntArray(); mEntitlementCacheValue = new SparseIntArray(); - mTetherMasterSM = tetherMasterSM; - mPermissionChangeMessageCode = permissionChangeMessageCode; - mHandler = tetherMasterSM.getHandler(); + mPermissionChangeCallback = callback; + mHandler = h; mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM), null, mHandler); mSilentProvisioningService = ComponentName.unflattenFromString( @@ -144,13 +144,35 @@ public class EntitlementManager { * Check if cellular upstream is permitted. */ public boolean isCellularUpstreamPermitted() { - // If provisioning is required and EntitlementManager don't know any downstream, - // cellular upstream should not be allowed. final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (mCurrentTethers.size() == 0 && isTetherProvisioningRequired(config)) { - return false; - } - return mCellularUpstreamPermitted; + + return isCellularUpstreamPermitted(config); + } + + private boolean isCellularUpstreamPermitted(final TetheringConfiguration config) { + if (!isTetherProvisioningRequired(config)) return true; + + // If provisioning is required and EntitlementManager doesn't know any downstreams, cellular + // upstream should not be enabled. Enable cellular upstream for exempted downstreams only + // when there is no non-exempted downstream. + if (mCurrentDownstreams.isEmpty()) return !mExemptedDownstreams.isEmpty(); + + return mCurrentEntitlementResults.indexOfValue(TETHER_ERROR_NO_ERROR) > -1; + } + + /** + * Set exempted downstream type. If there is only exempted downstream type active, + * corresponding entitlement check will not be run and cellular upstream will be permitted + * by default. If a privileged app enables tethering without a provisioning check, and then + * another app enables tethering of the same type but does not disable the provisioning check, + * then the downstream immediately loses exempt status and a provisioning check is run. + * If any non-exempted downstream type is active, the cellular upstream will be gated by the + * result of entitlement check from non-exempted downstreams. If entitlement check is still + * in progress on non-exempt downstreams, ceullar upstream would default be disabled. When any + * non-exempted downstream gets positive entitlement result, ceullar upstream will be enabled. + */ + public void setExemptedDownstreamType(final int type) { + mExemptedDownstreams.set(type, true); } /** @@ -164,29 +186,24 @@ public class EntitlementManager { public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) { if (!isValidDownstreamType(downstreamType)) return; - if (!mCurrentTethers.contains(downstreamType)) mCurrentTethers.add(downstreamType); + mCurrentDownstreams.set(downstreamType, true); + + mExemptedDownstreams.set(downstreamType, false); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); - if (isTetherProvisioningRequired(config)) { - // If provisioning is required and the result is not available yet, - // cellular upstream should not be allowed. - if (mCellularPermitted.size() == 0) { - mCellularUpstreamPermitted = false; - } - // If upstream is not cellular, provisioning app would not be launched - // till upstream change to cellular. - if (mUsingCellularAsUpstream) { - if (showProvisioningUi) { - runUiTetherProvisioning(downstreamType, config.activeDataSubId); - } else { - runSilentTetherProvisioning(downstreamType, config.activeDataSubId); - } - mNeedReRunProvisioningUi = false; + if (!isTetherProvisioningRequired(config)) return; + + // If upstream is not cellular, provisioning app would not be launched + // till upstream change to cellular. + if (mUsingCellularAsUpstream) { + if (showProvisioningUi) { + runUiTetherProvisioning(downstreamType, config.activeDataSubId); } else { - mNeedReRunProvisioningUi |= showProvisioningUi; + runSilentTetherProvisioning(downstreamType, config.activeDataSubId); } + mNeedReRunProvisioningUi = false; } else { - mCellularUpstreamPermitted = true; + mNeedReRunProvisioningUi |= showProvisioningUi; } } @@ -195,14 +212,15 @@ public class EntitlementManager { * * @param type tethering type from TetheringManager.TETHERING_{@code *} */ - public void stopProvisioningIfNeeded(int type) { - if (!isValidDownstreamType(type)) return; + public void stopProvisioningIfNeeded(int downstreamType) { + if (!isValidDownstreamType(downstreamType)) return; - mCurrentTethers.remove(type); + mCurrentDownstreams.set(downstreamType, false); // There are lurking bugs where the notion of "provisioning required" or // "tethering supported" may change without without tethering being notified properly. // Remove the mapping all the time no matter provisioning is required or not. - removeDownstreamMapping(type); + removeDownstreamMapping(downstreamType); + mExemptedDownstreams.set(downstreamType, false); } /** @@ -213,7 +231,7 @@ public class EntitlementManager { public void notifyUpstream(boolean isCellular) { if (DBG) { mLog.i("notifyUpstream: " + isCellular - + ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted + + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi); } mUsingCellularAsUpstream = isCellular; @@ -231,7 +249,7 @@ public class EntitlementManager { } private void maybeRunProvisioning(final TetheringConfiguration config) { - if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) { + if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) { return; } @@ -239,8 +257,9 @@ public class EntitlementManager { // are allowed. Therefore even if the silent check here ends in a failure and the UI later // yields success, then the downstream that got a failure will re-evaluate as a result of // the change and get the new correct value. - for (Integer downstream : mCurrentTethers) { - if (mCellularPermitted.indexOfKey(downstream) < 0) { + for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0; + downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) { + if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) { if (mNeedReRunProvisioningUi) { mNeedReRunProvisioningUi = false; runUiTetherProvisioning(downstream, config.activeDataSubId); @@ -286,7 +305,7 @@ public class EntitlementManager { mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread"); } mEntitlementCacheValue.clear(); - mCellularPermitted.clear(); + mCurrentEntitlementResults.clear(); // TODO: refine provisioning check to isTetherProvisioningRequired() ?? if (!config.hasMobileHotspotProvisionApp() @@ -410,26 +429,25 @@ public class EntitlementManager { } private void evaluateCellularPermission(final TetheringConfiguration config) { - final boolean oldPermitted = mCellularUpstreamPermitted; - mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config) - || mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1); + final boolean permitted = isCellularUpstreamPermitted(config); if (DBG) { - mLog.i("Cellular permission change from " + oldPermitted - + " to " + mCellularUpstreamPermitted); + mLog.i("Cellular permission change from " + mLastCellularUpstreamPermitted + + " to " + permitted); } - if (mCellularUpstreamPermitted != oldPermitted) { - mLog.log("Cellular permission change: " + mCellularUpstreamPermitted); - mTetherMasterSM.sendMessage(mPermissionChangeMessageCode); + if (mLastCellularUpstreamPermitted != permitted) { + mLog.log("Cellular permission change: " + permitted); + mPermissionChangeCallback.run(); } // Only schedule periodic re-check when tether is provisioned // and the result is ok. - if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) { + if (permitted && mCurrentEntitlementResults.size() > 0) { scheduleProvisioningRechecks(config); } else { cancelTetherProvisioningRechecks(); } + mLastCellularUpstreamPermitted = permitted; } /** @@ -441,10 +459,10 @@ public class EntitlementManager { */ protected void addDownstreamMapping(int type, int resultCode) { mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode - + " ,TetherTypeRequested: " + mCurrentTethers.contains(type)); - if (!mCurrentTethers.contains(type)) return; + + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type)); + if (!mCurrentDownstreams.get(type)) return; - mCellularPermitted.put(type, resultCode); + mCurrentEntitlementResults.put(type, resultCode); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); evaluateCellularPermission(config); } @@ -455,7 +473,7 @@ public class EntitlementManager { */ protected void removeDownstreamMapping(int type) { mLog.i("removeDownstreamMapping: " + type); - mCellularPermitted.delete(type); + mCurrentEntitlementResults.delete(type); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); evaluateCellularPermission(config); } @@ -488,18 +506,33 @@ public class EntitlementManager { * @param pw {@link PrintWriter} is used to print formatted */ public void dump(PrintWriter pw) { - pw.print("mCellularUpstreamPermitted: "); - pw.println(mCellularUpstreamPermitted); - for (Integer type : mCurrentTethers) { - pw.print("Type: "); - pw.print(typeString(type)); - if (mCellularPermitted.indexOfKey(type) > -1) { - pw.print(", Value: "); - pw.println(errorString(mCellularPermitted.get(type))); - } else { - pw.println(", Value: empty"); + final ConditionVariable mWaiting = new ConditionVariable(); + mHandler.post(() -> { + pw.print("isCellularUpstreamPermitted: "); + pw.println(isCellularUpstreamPermitted()); + for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0; + type = mCurrentDownstreams.nextSetBit(type + 1)) { + pw.print("Type: "); + pw.print(typeString(type)); + if (mCurrentEntitlementResults.indexOfKey(type) > -1) { + pw.print(", Value: "); + pw.println(errorString(mCurrentEntitlementResults.get(type))); + } else { + pw.println(", Value: empty"); + } } + mWaiting.open(); + }); + if (!mWaiting.block(DUMP_TIMEOUT)) { + pw.println("... dump timed out after " + DUMP_TIMEOUT + "ms"); + } + pw.print("Exempted: ["); + for (int type = mExemptedDownstreams.nextSetBit(0); type >= 0; + type = mExemptedDownstreams.nextSetBit(type + 1)) { + pw.print(typeString(type)); + pw.print(", "); } + pw.println("]"); } private static String typeString(int type) { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java index 1817f35f1dcd..88c77b07e7e3 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadController.java @@ -26,6 +26,8 @@ import static android.net.NetworkStats.UID_TETHERING; import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; +import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.usage.NetworkStatsManager; @@ -77,7 +79,6 @@ public class OffloadController { private static final boolean DBG = false; private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); - private static final int DEFAULT_PERFORM_POLL_INTERVAL_MS = 5000; @VisibleForTesting enum StatsType { @@ -134,11 +135,9 @@ public class OffloadController { private final Dependencies mDeps; // TODO: Put more parameters in constructor into dependency object. - static class Dependencies { - int getPerformPollInterval() { - // TODO: Consider make this configurable. - return DEFAULT_PERFORM_POLL_INTERVAL_MS; - } + interface Dependencies { + @NonNull + TetheringConfiguration getTetherConfig(); } public OffloadController(Handler h, OffloadHardwareInterface hwi, @@ -452,12 +451,16 @@ public class OffloadController { if (mHandler.hasCallbacks(mScheduledPollingTask)) { mHandler.removeCallbacks(mScheduledPollingTask); } - mHandler.postDelayed(mScheduledPollingTask, mDeps.getPerformPollInterval()); + mHandler.postDelayed(mScheduledPollingTask, + mDeps.getTetherConfig().getOffloadPollInterval()); } private boolean isPollingStatsNeeded() { return started() && mRemainingAlertQuota > 0 - && !TextUtils.isEmpty(currentUpstreamInterface()); + && !TextUtils.isEmpty(currentUpstreamInterface()) + && mDeps.getTetherConfig() != null + && mDeps.getTetherConfig().getOffloadPollInterval() + >= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; } private boolean maybeUpdateDataLimit(String iface) { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java index 00b94a8bbfc1..d1440a7c7be9 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -62,7 +62,6 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; -import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; @@ -268,12 +267,15 @@ public class Tethering { mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps); mTetherMasterSM.start(); - final NetworkStatsManager statsManager = - (NetworkStatsManager) mContext.getSystemService(Context.NETWORK_STATS_SERVICE); mHandler = mTetherMasterSM.getHandler(); - mOffloadController = new OffloadController(mHandler, - mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(), - statsManager, mLog, new OffloadController.Dependencies()); + mOffloadController = mDeps.getOffloadController(mHandler, mLog, + new OffloadController.Dependencies() { + + @Override + public TetheringConfiguration getTetherConfig() { + return mConfig; + } + }); mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK); mForwardedDownstreams = new LinkedHashSet<>(); @@ -282,8 +284,9 @@ public class Tethering { filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream // permission is changed according to entitlement check result. - mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, mLog, - TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED); + mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog, + () -> mTetherMasterSM.sendMessage( + TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { mLog.log("OBSERVED UiEnitlementFailed"); stopTethering(downstream); @@ -513,8 +516,12 @@ public class Tethering { } mActiveTetheringRequests.put(request.tetheringType, request); - mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, - request.showProvisioningUi); + if (request.exemptFromEntitlementCheck) { + mEntitlementMgr.setExemptedDownstreamType(request.tetheringType); + } else { + mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, + request.showProvisioningUi); + } enableTetheringInternal(request.tetheringType, true /* enabled */, listener); }); } diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index aeac437e24e3..9d4e74732729 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -78,6 +78,12 @@ public class TetheringConfiguration { public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER = "tether_enable_legacy_dhcp_server"; + /** + * Default value that used to periodic polls tether offload stats from tethering offload HAL + * to make the data warnings work. + */ + public static final int DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS = 5000; + public final String[] tetherableUsbRegexs; public final String[] tetherableWifiRegexs; public final String[] tetherableWifiP2pRegexs; @@ -96,6 +102,8 @@ public class TetheringConfiguration { public final int activeDataSubId; + private final int mOffloadPollInterval; + public TetheringConfiguration(Context ctx, SharedLog log, int id) { final SharedLog configLog = log.forSubComponent("config"); @@ -129,6 +137,10 @@ public class TetheringConfiguration { R.integer.config_mobile_hotspot_provision_check_period, 0 /* No periodic re-check */); + mOffloadPollInterval = getResourceInteger(res, + R.integer.config_tether_offload_poll_interval, + DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + configLog.log(toString()); } @@ -189,6 +201,9 @@ public class TetheringConfiguration { dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges); dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS); + pw.print("offloadPollInterval: "); + pw.println(mOffloadPollInterval); + dumpStringArray(pw, "provisioningApp", provisioningApp); pw.print("provisioningAppNoUi: "); pw.println(provisioningAppNoUi); @@ -208,6 +223,7 @@ public class TetheringConfiguration { makeString(tetherableBluetoothRegexs))); sj.add(String.format("isDunRequired:%s", isDunRequired)); sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically)); + sj.add(String.format("offloadPollInterval:%d", mOffloadPollInterval)); sj.add(String.format("preferredUpstreamIfaceTypes:%s", toIntArray(preferredUpstreamIfaceTypes))); sj.add(String.format("provisioningApp:%s", makeString(provisioningApp))); @@ -246,6 +262,10 @@ public class TetheringConfiguration { return (tm != null) ? tm.isTetheringApnRequired() : false; } + public int getOffloadPollInterval() { + return mOffloadPollInterval; + } + private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types); final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length); diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java index 9b54b5ff2403..ce546c701a61 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java @@ -16,6 +16,7 @@ package com.android.networkstack.tethering; +import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.net.INetd; @@ -47,6 +48,19 @@ public abstract class TetheringDependencies { } /** + * Get a reference to the offload controller to be used by tethering. + */ + @NonNull + public OffloadController getOffloadController(@NonNull Handler h, + @NonNull SharedLog log, @NonNull OffloadController.Dependencies deps) { + final NetworkStatsManager statsManager = + (NetworkStatsManager) getContext().getSystemService(Context.NETWORK_STATS_SERVICE); + return new OffloadController(h, getOffloadHardwareInterface(h, log), + getContext().getContentResolver(), statsManager, log, deps); + } + + + /** * Get a reference to the UpstreamNetworkMonitor to be used by tethering. */ public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target, @@ -82,9 +96,9 @@ public abstract class TetheringDependencies { /** * Get a reference to the EntitlementManager to be used by tethering. */ - public EntitlementManager getEntitlementManager(Context ctx, StateMachine target, - SharedLog log, int what) { - return new EntitlementManager(ctx, target, log, what); + public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { + return new EntitlementManager(ctx, h, log, callback); } /** diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java index c82e2be72ad2..af349f2b92a2 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java @@ -16,6 +16,8 @@ package com.android.networkstack.tethering; +import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.TETHER_PRIVILEGED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; @@ -151,7 +153,12 @@ public class TetheringService extends Service { @Override public void startTethering(TetheringRequestParcel request, String callerPkg, String callingAttributionTag, IIntResultListener listener) { - if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; + if (checkAndNotifyCommonError(callerPkg, + callingAttributionTag, + request.exemptFromEntitlementCheck /* onlyAllowPrivileged */, + listener)) { + return; + } mTethering.startTethering(request, listener); } @@ -179,7 +186,7 @@ public class TetheringService extends Service { public void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { try { - if (!mService.hasTetherAccessPermission()) { + if (!hasTetherAccessPermission()) { callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); return; } @@ -191,7 +198,7 @@ public class TetheringService extends Service { public void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { try { - if (!mService.hasTetherAccessPermission()) { + if (!hasTetherAccessPermission()) { callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); return; } @@ -226,10 +233,18 @@ public class TetheringService extends Service { mTethering.dump(fd, writer, args); } - private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag, - IIntResultListener listener) { + private boolean checkAndNotifyCommonError(final String callerPkg, + final String callingAttributionTag, final IIntResultListener listener) { + return checkAndNotifyCommonError(callerPkg, callingAttributionTag, + false /* onlyAllowPrivileged */, listener); + } + + private boolean checkAndNotifyCommonError(final String callerPkg, + final String callingAttributionTag, final boolean onlyAllowPrivileged, + final IIntResultListener listener) { try { - if (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) { + if (!hasTetherChangePermission(callerPkg, callingAttributionTag, + onlyAllowPrivileged)) { listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); return true; } @@ -244,9 +259,10 @@ public class TetheringService extends Service { return false; } - private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag, - ResultReceiver receiver) { - if (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) { + private boolean checkAndNotifyCommonError(final String callerPkg, + final String callingAttributionTag, final ResultReceiver receiver) { + if (!hasTetherChangePermission(callerPkg, callingAttributionTag, + false /* onlyAllowPrivileged */)) { receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null); return true; } @@ -258,6 +274,30 @@ public class TetheringService extends Service { return false; } + private boolean hasTetherPrivilegedPermission() { + return mService.checkCallingOrSelfPermission(TETHER_PRIVILEGED) == PERMISSION_GRANTED; + } + + private boolean hasTetherChangePermission(final String callerPkg, + final String callingAttributionTag, final boolean onlyAllowPrivileged) { + if (hasTetherPrivilegedPermission()) return true; + + if (onlyAllowPrivileged || mTethering.isTetherProvisioningRequired()) return false; + + int uid = Binder.getCallingUid(); + // If callerPkg's uid is not same as Binder.getCallingUid(), + // checkAndNoteWriteSettingsOperation will return false and the operation will be + // denied. + return TetheringService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg, + callingAttributionTag, false /* throwException */); + } + + private boolean hasTetherAccessPermission() { + if (hasTetherPrivilegedPermission()) return true; + + return mService.checkCallingOrSelfPermission( + ACCESS_NETWORK_STATE) == PERMISSION_GRANTED; + } } // if ro.tether.denied = true we default to no tethering @@ -274,26 +314,6 @@ public class TetheringService extends Service { return tetherEnabledInSettings && mTethering.hasTetherableConfiguration(); } - private boolean hasTetherChangePermission(String callerPkg, String callingAttributionTag) { - if (checkCallingOrSelfPermission( - android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { - return true; - } - - if (mTethering.isTetherProvisioningRequired()) return false; - - - int uid = Binder.getCallingUid(); - // If callerPkg's uid is not same as Binder.getCallingUid(), - // checkAndNoteWriteSettingsOperation will return false and the operation will be denied. - if (checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg, - callingAttributionTag, false /* throwException */)) { - return true; - } - - return false; - } - /** * Check if the package is a allowed to write settings. This also accounts that such an access * happened. @@ -308,21 +328,6 @@ public class TetheringService extends Service { throwException); } - private boolean hasTetherAccessPermission() { - if (checkCallingOrSelfPermission( - android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { - return true; - } - - if (checkCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) { - return true; - } - - return false; - } - - /** * An injection method for testing. */ diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java index 8bd0edc2490d..cdd0e243e31f 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java @@ -37,6 +37,8 @@ import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -45,7 +47,7 @@ import android.content.Context; import android.content.res.Resources; import android.net.util.SharedLog; import android.os.Bundle; -import android.os.Message; +import android.os.Handler; import android.os.PersistableBundle; import android.os.ResultReceiver; import android.os.SystemProperties; @@ -56,26 +58,22 @@ import android.telephony.CarrierConfigManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; import com.android.internal.util.test.BroadcastInterceptingContext; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; -import java.util.ArrayList; - @RunWith(AndroidJUnit4.class) @SmallTest public final class EntitlementManagerTest { - private static final int EVENT_EM_UPDATE = 1; private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; @@ -90,8 +88,8 @@ public final class EntitlementManagerTest { private final PersistableBundle mCarrierConfig = new PersistableBundle(); private final TestLooper mLooper = new TestLooper(); private Context mMockContext; + private Runnable mPermissionChangeCallback; - private TestStateMachine mSM; private WrappedEntitlementManager mEnMgr; private TetheringConfiguration mConfig; private MockitoSession mMockingSession; @@ -112,9 +110,9 @@ public final class EntitlementManagerTest { public int uiProvisionCount = 0; public int silentProvisionCount = 0; - public WrappedEntitlementManager(Context ctx, StateMachine target, - SharedLog log, int what) { - super(ctx, target, log, what); + public WrappedEntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { + super(ctx, h, log, callback); } public void reset() { @@ -169,8 +167,9 @@ public final class EntitlementManagerTest { when(mLog.forSubComponent(anyString())).thenReturn(mLog); mMockContext = new MockContext(mContext); - mSM = new TestStateMachine(); - mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE); + mPermissionChangeCallback = spy(() -> { }); + mEnMgr = new WrappedEntitlementManager(mMockContext, new Handler(mLooper.getLooper()), mLog, + mPermissionChangeCallback); mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener); mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mEnMgr.setTetheringConfigurationFetcher(() -> { @@ -180,10 +179,6 @@ public final class EntitlementManagerTest { @After public void tearDown() throws Exception { - if (mSM != null) { - mSM.quit(); - mSM = null; - } mMockingSession.finishMocking(); } @@ -350,68 +345,105 @@ public final class EntitlementManagerTest { mEnMgr.reset(); } + private void assertPermissionChangeCallback(InOrder inOrder) { + inOrder.verify(mPermissionChangeCallback, times(1)).run(); + } + + private void assertNoPermissionChange(InOrder inOrder) { + inOrder.verifyNoMoreInteractions(); + } + @Test public void verifyPermissionResult() { + final InOrder inOrder = inOrder(mPermissionChangeCallback); setupForRequiredProvisioning(); mEnMgr.notifyUpstream(true); mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mLooper.dispatchAll(); + // Permitted: true -> false + assertPermissionChangeCallback(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); mLooper.dispatchAll(); + // Permitted: false -> false + assertNoPermissionChange(inOrder); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mLooper.dispatchAll(); + // Permitted: false -> true + assertPermissionChangeCallback(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); } @Test public void verifyPermissionIfAllNotApproved() { + final InOrder inOrder = inOrder(mPermissionChangeCallback); setupForRequiredProvisioning(); mEnMgr.notifyUpstream(true); mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mLooper.dispatchAll(); + // Permitted: true -> false + assertPermissionChangeCallback(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); mLooper.dispatchAll(); + // Permitted: false -> false + assertNoPermissionChange(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); mLooper.dispatchAll(); + // Permitted: false -> false + assertNoPermissionChange(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); } @Test public void verifyPermissionIfAnyApproved() { + final InOrder inOrder = inOrder(mPermissionChangeCallback); setupForRequiredProvisioning(); mEnMgr.notifyUpstream(true); mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mLooper.dispatchAll(); + // Permitted: true -> true + assertNoPermissionChange(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); - mLooper.dispatchAll(); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); mLooper.dispatchAll(); + // Permitted: true -> true + assertNoPermissionChange(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); mLooper.dispatchAll(); + // Permitted: true -> false + assertPermissionChangeCallback(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); - } @Test public void verifyPermissionWhenProvisioningNotStarted() { + final InOrder inOrder = inOrder(mPermissionChangeCallback); assertTrue(mEnMgr.isCellularUpstreamPermitted()); + assertNoPermissionChange(inOrder); setupForRequiredProvisioning(); assertFalse(mEnMgr.isCellularUpstreamPermitted()); + assertNoPermissionChange(inOrder); } @Test public void testRunTetherProvisioning() { + final InOrder inOrder = inOrder(mPermissionChangeCallback); setupForRequiredProvisioning(); // 1. start ui provisioning, upstream is mobile mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; @@ -421,16 +453,22 @@ public final class EntitlementManagerTest { mLooper.dispatchAll(); assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + // Permitted: true -> true + assertNoPermissionChange(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); mEnMgr.reset(); + // 2. start no-ui provisioning mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false); mLooper.dispatchAll(); assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(1, mEnMgr.silentProvisionCount); + // Permitted: true -> true + assertNoPermissionChange(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); mEnMgr.reset(); + // 3. tear down mobile, then start ui provisioning mEnMgr.notifyUpstream(false); mLooper.dispatchAll(); @@ -438,44 +476,58 @@ public final class EntitlementManagerTest { mLooper.dispatchAll(); assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + assertNoPermissionChange(inOrder); mEnMgr.reset(); + // 4. switch upstream back to mobile mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.notifyUpstream(true); mLooper.dispatchAll(); assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + // Permitted: true -> true + assertNoPermissionChange(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); mEnMgr.reset(); + // 5. tear down mobile, then switch SIM mEnMgr.notifyUpstream(false); mLooper.dispatchAll(); mEnMgr.reevaluateSimCardProvisioning(mConfig); assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + assertNoPermissionChange(inOrder); mEnMgr.reset(); + // 6. switch upstream back to mobile again mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; mEnMgr.notifyUpstream(true); mLooper.dispatchAll(); assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(3, mEnMgr.silentProvisionCount); + // Permitted: true -> false + assertPermissionChangeCallback(inOrder); assertFalse(mEnMgr.isCellularUpstreamPermitted()); mEnMgr.reset(); + // 7. start ui provisioning, upstream is mobile, downstream is ethernet mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true); mLooper.dispatchAll(); assertEquals(1, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + // Permitted: false -> true + assertPermissionChangeCallback(inOrder); assertTrue(mEnMgr.isCellularUpstreamPermitted()); mEnMgr.reset(); + // 8. downstream is invalid mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true); mLooper.dispatchAll(); assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount); + assertNoPermissionChange(inOrder); mEnMgr.reset(); } @@ -492,31 +544,32 @@ public final class EntitlementManagerTest { verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); } - public class TestStateMachine extends StateMachine { - public final ArrayList<Message> messages = new ArrayList<>(); - private final State - mLoggingState = new EntitlementManagerTest.TestStateMachine.LoggingState(); + @Test + public void testsetExemptedDownstreamType() throws Exception { + setupForRequiredProvisioning(); + // Cellular upstream is not permitted when no entitlement result. + assertFalse(mEnMgr.isCellularUpstreamPermitted()); - class LoggingState extends State { - @Override public void enter() { - messages.clear(); - } + // If there is exempted downstream and no other non-exempted downstreams, cellular is + // permitted. + mEnMgr.setExemptedDownstreamType(TETHERING_WIFI); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); - @Override public void exit() { - messages.clear(); - } + // If second downstream run entitlement check fail, cellular upstream is not permitted. + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED; + mEnMgr.notifyUpstream(true); + mLooper.dispatchAll(); + mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); - @Override public boolean processMessage(Message msg) { - messages.add(msg); - return false; - } - } + // When second downstream is down, exempted downstream can use cellular upstream. + assertEquals(1, mEnMgr.uiProvisionCount); + verify(mEntitlementFailedListener).onUiEntitlementFailed(TETHERING_USB); + mEnMgr.stopProvisioningIfNeeded(TETHERING_USB); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); - public TestStateMachine() { - super("EntitlementManagerTest.TestStateMachine", mLooper.getLooper()); - addState(mLoggingState); - setInitialState(mLoggingState); - super.start(); - } + mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); } } diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java index 088a663190b8..b291438937c7 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java @@ -29,15 +29,15 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE; import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID; import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats; +import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; import static com.android.testutils.MiscAssertsKt.assertContainsAll; import static com.android.testutils.MiscAssertsKt.assertThrows; -import static com.android.testutils.NetworkStatsUtilsKt.orderInsensitiveEquals; +import static com.android.testutils.NetworkStatsUtilsKt.assertNetworkStatsEquals; import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; @@ -63,10 +63,10 @@ import android.net.LinkProperties; import android.net.NetworkStats; import android.net.NetworkStats.Entry; import android.net.RouteInfo; -import android.net.netstats.provider.INetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.net.util.SharedLog; import android.os.Handler; -import android.os.Looper; +import android.os.test.TestLooper; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.test.mock.MockContentResolver; @@ -75,7 +75,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; -import com.android.testutils.HandlerUtilsKt; +import com.android.testutils.TestableNetworkStatsProviderCbBinder; import org.junit.After; import org.junit.Before; @@ -109,17 +109,20 @@ public class OffloadControllerTest { @Mock private ApplicationInfo mApplicationInfo; @Mock private Context mContext; @Mock private NetworkStatsManager mStatsManager; - @Mock private INetworkStatsProviderCallback mTetherStatsProviderCb; + @Mock private TetheringConfiguration mTetherConfig; + // Late init since methods must be called by the thread that created this object. + private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb; private OffloadController.OffloadTetheringStatsProvider mTetherStatsProvider; private final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor = ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class); private MockContentResolver mContentResolver; + private final TestLooper mTestLooper = new TestLooper(); private OffloadController.Dependencies mDeps = new OffloadController.Dependencies() { @Override - int getPerformPollInterval() { - return 0; + public TetheringConfiguration getTetherConfig() { + return mTetherConfig; } }; @@ -131,6 +134,7 @@ public class OffloadControllerTest { mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mContext.getContentResolver()).thenReturn(mContentResolver); FakeSettingsProvider.clearSettingsProvider(); + when(mTetherConfig.getOffloadPollInterval()).thenReturn(-1); // Disabled. } @After public void tearDown() throws Exception { @@ -150,12 +154,16 @@ public class OffloadControllerTest { Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); } + private void setOffloadPollInterval(int interval) { + when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval); + } + private void waitForIdle() { - HandlerUtilsKt.waitForIdle(new Handler(Looper.getMainLooper()), WAIT_FOR_IDLE_TIMEOUT); + mTestLooper.dispatchAll(); } private OffloadController makeOffloadController() throws Exception { - OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()), + OffloadController offload = new OffloadController(new Handler(mTestLooper.getLooper()), mHardware, mContentResolver, mStatsManager, new SharedLog("test"), mDeps); final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider> tetherStatsProviderCaptor = @@ -164,6 +172,7 @@ public class OffloadControllerTest { tetherStatsProviderCaptor.capture()); mTetherStatsProvider = tetherStatsProviderCaptor.getValue(); assertNotNull(mTetherStatsProvider); + mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder(); mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb); return offload; } @@ -352,9 +361,9 @@ public class OffloadControllerTest { stacked.setInterfaceName("stacked"); stacked.addLinkAddress(new LinkAddress("192.0.2.129/25")); stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null, - RTN_UNICAST)); + RTN_UNICAST)); stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null, - RTN_UNICAST)); + RTN_UNICAST)); assertTrue(lp.addStackedLink(stacked)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). @@ -459,20 +468,12 @@ public class OffloadControllerTest { .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321)); - assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStats)); - assertTrue(orderInsensitiveEquals(expectedUidStats, uidStats)); - - final ArgumentCaptor<NetworkStats> ifaceStatsCaptor = ArgumentCaptor.forClass( - NetworkStats.class); - final ArgumentCaptor<NetworkStats> uidStatsCaptor = ArgumentCaptor.forClass( - NetworkStats.class); + assertNetworkStatsEquals(expectedIfaceStats, ifaceStats); + assertNetworkStatsEquals(expectedUidStats, uidStats); // Force pushing stats update to verify the stats reported. mTetherStatsProvider.pushTetherStats(); - verify(mTetherStatsProviderCb, times(1)) - .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture()); - assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStatsCaptor.getValue())); - assertTrue(orderInsensitiveEquals(expectedUidStats, uidStatsCaptor.getValue())); + mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStats, expectedUidStats); when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( new ForwardedStats(100000, 100000)); @@ -498,11 +499,10 @@ public class OffloadControllerTest { .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321)); - assertTrue(orderInsensitiveEquals(expectedIfaceStatsAccu, ifaceStatsAccu)); - assertTrue(orderInsensitiveEquals(expectedUidStatsAccu, uidStatsAccu)); + assertNetworkStatsEquals(expectedIfaceStatsAccu, ifaceStatsAccu); + assertNetworkStatsEquals(expectedUidStatsAccu, uidStatsAccu); // Verify that only diff of stats is reported. - reset(mTetherStatsProviderCb); mTetherStatsProvider.pushTetherStats(); final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2) .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0)) @@ -511,10 +511,8 @@ public class OffloadControllerTest { final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2) .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0)) .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000)); - verify(mTetherStatsProviderCb, times(1)) - .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture()); - assertTrue(orderInsensitiveEquals(expectedIfaceStatsDiff, ifaceStatsCaptor.getValue())); - assertTrue(orderInsensitiveEquals(expectedUidStatsDiff, uidStatsCaptor.getValue())); + mTetherStatsProviderCb.expectNotifyStatsUpdated(expectedIfaceStatsDiff, + expectedUidStatsDiff); } @Test @@ -591,7 +589,7 @@ public class OffloadControllerTest { OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); callback.onStoppedLimitReached(); - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); } @Test @@ -695,8 +693,8 @@ public class OffloadControllerTest { verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); // TODO: verify the exact stats reported. - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); - verifyNoMoreInteractions(mTetherStatsProviderCb); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); + mTetherStatsProviderCb.assertNoCallback(); verifyNoMoreInteractions(mHardware); } @@ -760,8 +758,8 @@ public class OffloadControllerTest { // Verify forwarded stats behaviour. verify(mHardware, times(1)).getForwardedStats(eq(RMNET0)); verify(mHardware, times(1)).getForwardedStats(eq(WLAN0)); - verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any()); - verifyNoMoreInteractions(mTetherStatsProviderCb); + mTetherStatsProviderCb.expectNotifyStatsUpdated(); + mTetherStatsProviderCb.assertNoCallback(); // TODO: verify local prefixes and downstreams are also pushed to the HAL. verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); @@ -780,4 +778,50 @@ public class OffloadControllerTest { verifyNoMoreInteractions(mHardware); } + @Test + public void testOnSetAlert() throws Exception { + setupFunctioningHardwareInterface(); + enableOffload(); + setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + final OffloadController offload = makeOffloadController(); + offload.start(); + + // Initialize with fake eth upstream. + final String ethernetIface = "eth1"; + InOrder inOrder = inOrder(mHardware); + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(ethernetIface); + offload.setUpstreamLinkProperties(lp); + // Previous upstream was null, so no stats are fetched. + inOrder.verify(mHardware, never()).getForwardedStats(any()); + + // Verify that set quota to 0 will immediately triggers an callback. + mTetherStatsProvider.onSetAlert(0); + waitForIdle(); + mTetherStatsProviderCb.expectNotifyAlertReached(); + + // Verify that notifyAlertReached never fired if quota is not yet reached. + when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( + new ForwardedStats(0, 0)); + mTetherStatsProvider.onSetAlert(100); + mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + waitForIdle(); + mTetherStatsProviderCb.assertNoCallback(); + + // Verify that notifyAlertReached fired when quota is reached. + when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn( + new ForwardedStats(50, 50)); + mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + waitForIdle(); + mTetherStatsProviderCb.expectNotifyAlertReached(); + + // Verify that set quota with UNLIMITED won't trigger any callback, and won't fetch + // any stats since the polling is stopped. + reset(mHardware); + mTetherStatsProvider.onSetAlert(NetworkStatsProvider.QUOTA_UNLIMITED); + mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + waitForIdle(); + mTetherStatsProviderCb.assertNoCallback(); + verify(mHardware, never()).getForwardedStats(any()); + } } diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java index 07ddea43f4e8..e8ba5b8168d7 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java @@ -115,6 +115,8 @@ public class TetheringConfigurationTest { when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn( new String[0]); + when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn( + TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); when(mResources.getStringArray(R.array.config_tether_usb_regexs)).thenReturn(new String[0]); when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) .thenReturn(new String[]{ "test_wlan\\d" }); @@ -314,6 +316,23 @@ public class TetheringConfigurationTest { } @Test + public void testOffloadIntervalByResource() { + final TetheringConfiguration intervalByDefault = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, + intervalByDefault.getOffloadPollInterval()); + + final int[] testOverrides = {0, 3000, -1}; + for (final int override : testOverrides) { + when(mResources.getInteger(R.integer.config_tether_offload_poll_interval)).thenReturn( + override); + final TetheringConfiguration overrideByRes = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(override, overrideByRes.getOffloadPollInterval()); + } + } + + @Test public void testGetResourcesBySubId() { setUpResourceForSubId(); final TetheringConfiguration cfg = new TetheringConfiguration( diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java index 4471f649691f..85c2f2b984ae 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -57,6 +57,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; @@ -150,6 +151,8 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.util.ArrayList; @@ -170,6 +173,8 @@ public class TetheringTest { private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0"; private static final String TEST_NCM_IFNAME = "test_ncm0"; private static final String TETHERING_NAME = "Tethering"; + private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; + private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; private static final int DHCPSERVER_START_TIMEOUT_MS = 1000; @@ -212,6 +217,9 @@ public class TetheringTest { private Tethering mTethering; private PhoneStateListener mPhoneStateListener; private InterfaceConfigurationParcel mInterfaceConfiguration; + private TetheringConfiguration mConfig; + private EntitlementManager mEntitleMgr; + private OffloadController mOffloadCtrl; private class TestContext extends BroadcastInterceptingContext { TestContext(Context base) { @@ -297,8 +305,9 @@ public class TetheringTest { } } - private class MockTetheringConfiguration extends TetheringConfiguration { - MockTetheringConfiguration(Context ctx, SharedLog log, int id) { + // MyTetheringConfiguration is used to override static method for testing. + private class MyTetheringConfiguration extends TetheringConfiguration { + MyTetheringConfiguration(Context ctx, SharedLog log, int id) { super(ctx, log, id); } @@ -328,6 +337,15 @@ public class TetheringTest { } @Override + public OffloadController getOffloadController(Handler h, SharedLog log, + OffloadController.Dependencies deps) { + mOffloadCtrl = spy(super.getOffloadController(h, log, deps)); + // Return real object here instead of mock because + // testReportFailCallbackIfOffloadNotSupported depend on real OffloadController object. + return mOffloadCtrl; + } + + @Override public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target, SharedLog log, int what) { mUpstreamNetworkMonitorMasterSM = target; @@ -352,6 +370,13 @@ public class TetheringTest { } @Override + public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log, + Runnable callback) { + mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback)); + return mEntitleMgr; + } + + @Override public boolean isTetheringSupported() { return true; } @@ -359,7 +384,8 @@ public class TetheringTest { @Override public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log, int subId) { - return new MockTetheringConfiguration(ctx, log, subId); + mConfig = spy(new MyTetheringConfiguration(ctx, log, subId)); + return mConfig; } @Override @@ -516,16 +542,16 @@ public class TetheringTest { } private TetheringRequestParcel createTetheringRequestParcel(final int type) { - return createTetheringRequestParcel(type, null, null); + return createTetheringRequestParcel(type, null, null, false); } private TetheringRequestParcel createTetheringRequestParcel(final int type, - final LinkAddress serverAddr, final LinkAddress clientAddr) { + final LinkAddress serverAddr, final LinkAddress clientAddr, final boolean exempt) { final TetheringRequestParcel request = new TetheringRequestParcel(); request.tetheringType = type; request.localIPv4Address = serverAddr; request.staticClientAddress = clientAddr; - request.exemptFromEntitlementCheck = false; + request.exemptFromEntitlementCheck = exempt; request.showProvisioningUi = false; return request; @@ -1636,7 +1662,7 @@ public class TetheringTest { // Enable USB tethering and check that Tethering starts USB. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null), firstResult); + null, null, false), firstResult); mLooper.dispatchAll(); firstResult.assertHasResult(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); @@ -1644,7 +1670,7 @@ public class TetheringTest { // Enable USB tethering again with the same request and expect no change to USB. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - null, null), secondResult); + null, null, false), secondResult); mLooper.dispatchAll(); secondResult.assertHasResult(); verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE); @@ -1653,7 +1679,7 @@ public class TetheringTest { // Enable USB tethering with a different request and expect that USB is stopped and // started. mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr), thirdResult); + serverLinkAddr, clientLinkAddr, false), thirdResult); mLooper.dispatchAll(); thirdResult.assertHasResult(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE); @@ -1677,7 +1703,7 @@ public class TetheringTest { final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor = ArgumentCaptor.forClass(DhcpServingParamsParcel.class); mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, - serverLinkAddr, clientLinkAddr), null); + serverLinkAddr, clientLinkAddr, false), null); mLooper.dispatchAll(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); @@ -1726,6 +1752,82 @@ public class TetheringTest { verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any()); } + @Test + public void testDumpTetheringLog() throws Exception { + final FileDescriptor mockFd = mock(FileDescriptor.class); + final PrintWriter mockPw = mock(PrintWriter.class); + runUsbTethering(null); + mLooper.startAutoDispatch(); + mTethering.dump(mockFd, mockPw, new String[0]); + verify(mConfig).dump(any()); + verify(mEntitleMgr).dump(any()); + verify(mOffloadCtrl).dump(any()); + mLooper.stopAutoDispatch(); + } + + @Test + public void testExemptFromEntitlementCheck() throws Exception { + setupForRequiredProvisioning(); + final TetheringRequestParcel wifiNotExemptRequest = + createTetheringRequestParcel(TETHERING_WIFI, null, null, false); + mTethering.startTethering(wifiNotExemptRequest, null); + mLooper.dispatchAll(); + verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false); + verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI); + assertFalse(mEntitleMgr.isCellularUpstreamPermitted()); + mTethering.stopTethering(TETHERING_WIFI); + mLooper.dispatchAll(); + verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); + reset(mEntitleMgr); + + setupForRequiredProvisioning(); + final TetheringRequestParcel wifiExemptRequest = + createTetheringRequestParcel(TETHERING_WIFI, null, null, true); + mTethering.startTethering(wifiExemptRequest, null); + mLooper.dispatchAll(); + verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false); + verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI); + assertTrue(mEntitleMgr.isCellularUpstreamPermitted()); + mTethering.stopTethering(TETHERING_WIFI); + mLooper.dispatchAll(); + verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); + reset(mEntitleMgr); + + // If one app enables tethering without provisioning check first, then another app enables + // tethering of the same type but does not disable the provisioning check. + setupForRequiredProvisioning(); + mTethering.startTethering(wifiExemptRequest, null); + mLooper.dispatchAll(); + verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false); + verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI); + assertTrue(mEntitleMgr.isCellularUpstreamPermitted()); + reset(mEntitleMgr); + setupForRequiredProvisioning(); + mTethering.startTethering(wifiNotExemptRequest, null); + mLooper.dispatchAll(); + verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false); + verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI); + assertFalse(mEntitleMgr.isCellularUpstreamPermitted()); + mTethering.stopTethering(TETHERING_WIFI); + mLooper.dispatchAll(); + verify(mEntitleMgr).stopProvisioningIfNeeded(TETHERING_WIFI); + reset(mEntitleMgr); + } + + private void setupForRequiredProvisioning() { + // Produce some acceptable looking provision app setting if requested. + when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) + .thenReturn(PROVISIONING_APP_NAME); + when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui)) + .thenReturn(PROVISIONING_NO_UI_APP_NAME); + // Act like the CarrierConfigManager is present and ready unless told otherwise. + when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) + .thenReturn(mCarrierConfigManager); + when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); + sendConfigurationChanged(); + } // TODO: Test that a request for hotspot mode doesn't interfere with an // already operating tethering mode interface. } diff --git a/services/Android.bp b/services/Android.bp index b4d8393683ba..0d221b930f5d 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -122,13 +122,13 @@ droidstubs { removed_api_file: "api/removed.txt", }, last_released: { - api_file: ":last-released-system-server-api", + api_file: ":android.api.system-server.latest", removed_api_file: "api/removed.txt", baseline_file: ":system-server-api-incompatibilities-with-last-released" }, api_lint: { enabled: true, - new_since: ":last-released-system-server-api", + new_since: ":android.api.system-server.latest", baseline_file: "api/lint-baseline.txt", }, }, diff --git a/services/core/Android.bp b/services/core/Android.bp index a2f73a6730b5..d9a534916da6 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -53,8 +53,8 @@ java_library_static { "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", - "dnsresolver_aidl_interface-V4-java", - "netd_event_listener_interface-java", + "dnsresolver_aidl_interface-java", + "netd_aidl_interfaces-platform-java", ], } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 58e06e00ef2d..08aab2aea6f9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7123,6 +7123,14 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); if (!createNativeNetwork(networkAgent)) return; + if (networkAgent.isVPN()) { + // Initialize the VPN capabilities to their starting values according to the + // underlying networks. This will avoid a spurious callback to + // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as + // the VPN would switch from its default, blank capabilities to those + // that reflect the capabilities of its underlying networks. + updateAllVpnsCapabilities(); + } networkAgent.created = true; } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0ba41736ce15..0ba6a5536cbf 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -842,6 +842,15 @@ public final class ActiveServices { } } + void killMisbehavingService(ServiceRecord r, + int appUid, int appPid, String localPackageName) { + synchronized (mAm) { + stopServiceLocked(r); + mAm.crashApplication(appUid, appPid, localPackageName, -1, + "Bad notification for startForeground", true /*force*/); + } + } + IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) { ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), @@ -3946,7 +3955,7 @@ public final class ActiveServices { void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) { mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId, "Context.startForegroundService() did not then call Service.startForeground(): " - + serviceRecord); + + serviceRecord, false /*force*/); } void scheduleServiceTimeoutLocked(ProcessRecord proc) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 39ea499f21d0..ece21f667418 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3597,7 +3597,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void crashApplication(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: crashApplication() from pid=" @@ -3609,7 +3609,8 @@ public class ActivityManagerService extends IActivityManager.Stub } synchronized(this) { - mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message); + mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, + message, force); } } @@ -4788,7 +4789,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @GuardedBy("this") - private final boolean attachApplicationLocked(IApplicationThread thread, + private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { // Find the application record that is being attached... either via @@ -5211,6 +5212,9 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public final void attachApplication(IApplicationThread thread, long startSeq) { + if (thread == null) { + throw new SecurityException("Invalid application interface"); + } synchronized (this) { int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 5078b8a14eb2..5ab18d95b84d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -1058,7 +1058,7 @@ final class ActivityManagerShellCommand extends ShellCommand { } catch (NumberFormatException e) { packageName = arg; } - mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash"); + mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false); return 0; } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index a4c695067139..bbd2d34e92a6 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -314,20 +314,24 @@ class AppErrors { } void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { - app.setCrashing(false); - app.crashingReport = null; - app.setNotResponding(false); - app.notRespondingReport = null; if (app.anrDialog == fromDialog) { app.anrDialog = null; } if (app.waitDialog == fromDialog) { app.waitDialog = null; } + killAppImmediateLocked(app, "user-terminated", "user request after error"); + } + + private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { + app.setCrashing(false); + app.crashingReport = null; + app.setNotResponding(false); + app.notRespondingReport = null; if (app.pid > 0 && app.pid != MY_PID) { - handleAppCrashLocked(app, "user-terminated" /*reason*/, + handleAppCrashLocked(app, reason, null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); - app.kill("user request after error", true); + app.kill(killReason, true); } } @@ -341,7 +345,7 @@ class AppErrors { * @param message */ void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { ProcessRecord proc = null; // Figure out which process to kill. We don't trust that initialPid @@ -374,6 +378,14 @@ class AppErrors { } proc.scheduleCrash(message); + if (force) { + // If the app is responsive, the scheduled crash will happen as expected + // and then the delayed summary kill will be a no-op. + final ProcessRecord p = proc; + mService.mHandler.postDelayed( + () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), + 5000L); + } } /** diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index dee8e3b285a7..c408695bcb66 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -798,6 +798,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN final String localPackageName = packageName; final int localForegroundId = foregroundId; final Notification _foregroundNoti = foregroundNoti; + final ServiceRecord record = this; ams.mHandler.post(new Runnable() { public void run() { NotificationManagerInternal nm = LocalServices.getService( @@ -896,10 +897,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN Slog.w(TAG, "Error showing notification for service", e); // If it gave us a garbage notification, it doesn't // get to be foreground. - ams.setServiceForeground(instanceName, ServiceRecord.this, - 0, null, 0, 0); - ams.crashApplication(appUid, appPid, localPackageName, -1, - "Bad notification for startForeground: " + e); + ams.mServices.killMisbehavingService(record, + appUid, appPid, localPackageName); } } }); diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java index 228966cbee5b..103f659cc258 100644 --- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java +++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java @@ -17,7 +17,6 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.NetworkCallback; -import static android.net.ipsec.ike.SaProposal.DH_GROUP_1024_BIT_MODP; import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12; @@ -85,6 +84,12 @@ import java.util.List; public class VpnIkev2Utils { private static final String TAG = VpnIkev2Utils.class.getSimpleName(); + // TODO: Use IKE library exposed constants when @SystemApi is updated. + /** IANA-defined 3072 group for use in IKEv2 */ + private static final int DH_GROUP_3072_BIT_MODP = 15; + /** IANA-defined 4096 group for use in IKEv2 */ + private static final int DH_GROUP_4096_BIT_MODP = 16; + static IkeSessionParams buildIkeSessionParams( @NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) { final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity()); @@ -177,8 +182,9 @@ public class VpnIkev2Utils { // Add dh, prf for both builders for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) { + builder.addDhGroup(DH_GROUP_4096_BIT_MODP); + builder.addDhGroup(DH_GROUP_3072_BIT_MODP); builder.addDhGroup(DH_GROUP_2048_BIT_MODP); - builder.addDhGroup(DH_GROUP_1024_BIT_MODP); builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC); builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1); } diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 3006ef41931f..d7bf37db6afd 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -306,49 +306,6 @@ final class Constants { static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "persist.sys.hdmi.addr.playback"; static final String PROPERTY_PREFERRED_ADDRESS_TV = "persist.sys.hdmi.addr.tv"; - - // TODO(OEM): Set this to false to keep the playback device in sleep upon hotplug event. - // True by default. - static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug"; - - // TODO(OEM): Set this to true to enable 'Set Menu Language' feature. False by default. - static final String PROPERTY_SET_MENU_LANGUAGE = "ro.hdmi.set_menu_language"; - - /** - * Property to save the ARC port id on system audio device. - * <p>When ARC is initiated, this port will be used to turn on ARC. - */ - static final String PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT = - "ro.hdmi.property_sytem_audio_device_arc_port"; - - /** - * Property to disable muting logic in System Audio Control handling. Default is true. - * - * <p>True means enabling muting logic. - * <p>False means never mute device. - */ - static final String PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE = - "ro.hdmi.property_system_audio_mode_muting_enable"; - - /** - * When set to true the HdmiControlService will never request a Logical Address for the - * playback device type. Default is false. - * - * <p> This is useful when HDMI CEC multiple device types is not supported by the cec driver - */ - static final String PROPERTY_HDMI_CEC_NEVER_CLAIM_PLAYBACK_LOGICAL_ADDRESS = - "ro.hdmi.property_hdmi_cec_never_claim_playback_logical_address"; - - /** - * A comma separated list of logical addresses that HdmiControlService - * will never assign local CEC devices to. - * - * <p> This is useful when HDMI CEC hardware module can't assign multiple logical addresses - * in the range same range of 0-7 or 8-15. - */ - static final String PROPERTY_HDMI_CEC_NEVER_ASSIGN_LOGICAL_ADDRESSES = - "ro.hdmi.property_hdmi_cec_never_assign_logical_addresses"; - // Set to false to allow playback device to go to suspend mode even // when it's an active source. True by default. static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake"; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 9e2fd4e9e91e..496273b6bf0e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -35,6 +35,7 @@ import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager.TvInputCallback; import android.os.SystemProperties; import android.provider.Settings.Global; +import android.sysprop.HdmiProperties; import android.util.Slog; import android.util.SparseArray; @@ -90,8 +91,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { // If the current device uses TvInput for ARC. We assume all other inputs also use TvInput // when ARC is using TvInput. - private boolean mArcIntentUsed = SystemProperties - .get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, "0").contains("tvinput"); + private boolean mArcIntentUsed = HdmiProperties.arc_port().orElse("0").contains("tvinput"); // Keeps the mapping (HDMI port ID to TV input URI) to keep track of the TV inputs ready to // accept input switching request from HDMI devices. @@ -823,7 +823,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { private void enableAudioReturnChannel(boolean enabled) { assertRunOnServiceThread(); mService.enableAudioReturnChannel( - SystemProperties.getInt(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, 0), + Integer.parseInt(HdmiProperties.arc_port().orElse("0")), enabled); } @@ -895,9 +895,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { boolean currentMuteStatus = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC); if (currentMuteStatus == newSystemAudioMode) { - if (mService.readBooleanSystemProperty( - Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true) - || newSystemAudioMode) { + if (HdmiProperties.system_audio_mode_muting().orElse(true) || newSystemAudioMode) { mService.getAudioManager() .adjustStreamVolume( AudioManager.STREAM_MUSIC, @@ -1133,7 +1131,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { if (portId == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) { switchToHomeTvInput(); } else if (portId == Constants.CEC_SWITCH_ARC) { - switchToTvInput(SystemProperties.get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT)); + switchToTvInput(HdmiProperties.arc_port().orElse("0")); setLocalActivePort(portId); return; } else { diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 560f7a03b20f..603dfafc6ff5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -24,6 +24,7 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemProperties; import android.provider.Settings.Global; +import android.sysprop.HdmiProperties; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -43,11 +44,10 @@ import java.util.Locale; public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { private static final String TAG = "HdmiCecLocalDevicePlayback"; - private static final boolean WAKE_ON_HOTPLUG = - SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true); + private static final boolean WAKE_ON_HOTPLUG = false; private static final boolean SET_MENU_LANGUAGE = - SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false); + HdmiProperties.set_menu_language_enabled().orElse(false); // Used to keep the device awake while it is the active source. For devices that // cannot wake up via CEC commands, this address the inconvenience of having to diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java index ae008b4bfa7a..eb6612fffc0c 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java @@ -16,12 +16,10 @@ package com.android.server.hdmi; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; - import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.IHdmiControlCallback; -import android.os.SystemProperties; +import android.sysprop.HdmiProperties; import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -44,8 +42,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice { // Device has cec switch functionality or not. // Default is false. - protected boolean mIsSwitchDevice = SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + protected boolean mIsSwitchDevice = HdmiProperties.is_switch().orElse(false); // Routing port number used for Routing Control. // This records the default routing port or the previous valid routing port. diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 6a0cc2661f3d..51d363a41116 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -19,7 +19,6 @@ package com.android.server.hdmi; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE; -import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH; import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static com.android.server.hdmi.Constants.DISABLED; import static com.android.server.hdmi.Constants.ENABLED; @@ -2520,8 +2519,7 @@ public class HdmiControlService extends SystemService { } boolean isSwitchDevice() { - return SystemProperties.getBoolean( - PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false); + return HdmiProperties.is_switch().orElse(false); } boolean isTvDeviceEnabled() { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 26808587437c..e21a01d2048f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -46,7 +46,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -67,9 +66,6 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; -import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; -import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -133,9 +129,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -184,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; private static final int MSG_UPDATE_IFACES = 3; + // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent + // deadlock. + private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -206,7 +203,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; - private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -352,6 +348,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Dependencies mDeps; + @NonNull + private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -390,6 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerGlobalAlert(); break; } + case MSG_BROADCAST_NETWORK_STATS_UPDATED: { + final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); + updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); + break; + } } } } @@ -401,8 +407,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), + final NetworkStatsService service = new NetworkStatsService(context, networkManager, + alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -416,16 +422,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir, @NonNull Dependencies deps) { + NetworkStatsSettings settings, NetworkStatsFactory factory, + NetworkStatsObservers statsObservers, File systemDir, File baseDir, + @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + "missing INetworkManagementService"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); - mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager"); mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); mStatsFactory = Objects.requireNonNull(factory, "missing factory"); mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); @@ -437,7 +442,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); - mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); + mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, + new HandlerExecutor(mHandler), this); } /** @@ -453,6 +459,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public HandlerThread makeHandlerThread() { return new HandlerThread(TAG); } + + /** + * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change + * event in NetworkStatsService. + */ + @NonNull + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, + @NonNull Executor executor, @NonNull NetworkStatsService service) { + // TODO: Update RatType passively in NSS, instead of querying into the monitor + // when forceUpdateIface. + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> + service.handleOnCollapsedRatTypeChanged()); + } } private void registerLocalService() { @@ -517,11 +536,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: 1. listen to changes from all subscriptions. - // 2. listen to settings changed to support dynamically enable/disable. + // TODO: listen to settings changed to support dynamically enable/disable. // watch for networkType changes if (!mSettings.getCombineSubtypeEnabled()) { - mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + mNetworkStatsSubscriptionsMonitor.start(); } registerGlobalAlert(); @@ -544,7 +562,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!mSettings.getCombineSubtypeEnabled()) { + mNetworkStatsSubscriptionsMonitor.stop(); + } final long currentTime = mClock.millis(); @@ -1197,35 +1217,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** - * Receiver that watches for {@link TelephonyManager} changes, such as - * transitioning between Radio Access Technology(RAT) types. + * Handle collapsed RAT type changed event. */ - @NonNull - private final NetworkTypeListener mPhoneListener; - - class NetworkTypeListener extends PhoneStateListener { - private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; - - NetworkTypeListener(@NonNull Executor executor) { - super(executor); - } - - @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); - final int collapsedRatType = getCollapsedRatType(networkType); - if (collapsedRatType == mLastCollapsedRatType) return; - - if (LOGD) { - Log.d(TAG, "subtype changed for mobile: " - + mLastCollapsedRatType + " -> " + collapsedRatType); - } - // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); - mLastCollapsedRatType = collapsedRatType; - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); - } + @VisibleForTesting + public void handleOnCollapsedRatTypeChanged() { + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } private void updateIfaces( @@ -1352,8 +1351,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return 0; } - // TODO: return different subType for different subscriptions. - return mPhoneListener.mLastCollapsedRatType; + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); } private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet( @@ -1520,10 +1518,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // finally, dispatch updated event to any listeners - final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); - updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, - READ_NETWORK_USAGE_HISTORY); + mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); Trace.traceEnd(TRACE_TAG_NETWORK); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index a2f191444b63..2d39e9169245 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -920,7 +920,7 @@ public class NotificationManagerService extends SystemService { () -> mAm.crashApplication(uid, initialPid, pkg, -1, "Bad notification(tag=" + tag + ", id=" + id + ") posted from package " + pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): " - + message)); + + message, true /* force */)); } } diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 0d7494cfbeab..6fdde7a196cc 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -30,7 +30,7 @@ per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google. per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com -per-file UserManagerService.java = omakoto@google.com, yamasani@google.com +per-file UserManagerService.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e82102f3379d..50bbfa96bfab 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3004,8 +3004,7 @@ public class PackageManagerService extends IPackageManager.Stub mWellbeingPackage = getWellbeingPackageName(); mDocumenterPackage = getDocumenterPackageName(); - mConfiguratorPackage = - mContext.getString(R.string.config_deviceConfiguratorPackageName); + mConfiguratorPackage = getDeviceConfiguratorPackageName(); mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); mTelephonyPackages = getTelephonyPackageNames(); @@ -20537,7 +20536,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getSystemTextClassifierPackageName() { - return mContext.getString(R.string.config_defaultTextClassifierPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_defaultTextClassifierPackage)); } @Override @@ -20547,7 +20547,7 @@ public class PackageManagerService extends IPackageManager.Stub if (flattenedComponentName != null) { ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName); if (componentName != null && componentName.getPackageName() != null) { - return componentName.getPackageName(); + return ensureSystemPackageName(componentName.getPackageName()); } } return null; @@ -20572,9 +20572,15 @@ public class PackageManagerService extends IPackageManager.Stub } } + @Nullable + private String getDeviceConfiguratorPackageName() { + return ensureSystemPackageName(mContext.getString( + R.string.config_deviceConfiguratorPackageName)); + } + @Override public String getWellbeingPackageName() { - return mContext.getString(R.string.config_defaultWellbeingPackage); + return ensureSystemPackageName(mContext.getString(R.string.config_defaultWellbeingPackage)); } @Override @@ -20589,7 +20595,7 @@ public class PackageManagerService extends IPackageManager.Stub if (appPredictionServiceComponentName == null) { return null; } - return appPredictionServiceComponentName.getPackageName(); + return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName()); } @Override @@ -20606,11 +20612,33 @@ public class PackageManagerService extends IPackageManager.Stub if (systemCaptionsServiceComponentName == null) { return null; } - return systemCaptionsServiceComponentName.getPackageName(); + return ensureSystemPackageName(systemCaptionsServiceComponentName.getPackageName()); } public String getIncidentReportApproverPackageName() { - return mContext.getString(R.string.config_incidentReportApproverPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_incidentReportApproverPackage)); + } + + @Nullable + private String ensureSystemPackageName(@Nullable String packageName) { + if (packageName == null) { + return null; + } + long token = Binder.clearCallingIdentity(); + try { + if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) { + PackageInfo packageInfo = getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM); + if (packageInfo != null) { + EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid, + ""); + } + return null; + } + } finally { + Binder.restoreCallingIdentity(token); + } + return packageName; } @Override diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index f78d2639df1a..add0b01f1879 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -19,8 +19,6 @@ package com.android.server.policy.keyguard; import android.app.ActivityManager; import android.content.Context; import android.os.RemoteException; -import android.os.ServiceManager; -import android.security.keystore.IKeystoreService; import android.util.Slog; import com.android.internal.policy.IKeyguardService; @@ -53,16 +51,11 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { private final LockPatternUtils mLockPatternUtils; private final StateCallback mCallback; - IKeystoreService mKeystoreService; - public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) { mLockPatternUtils = new LockPatternUtils(context); mCurrentUserId = ActivityManager.getCurrentUser(); mCallback = callback; - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - try { service.addStateMonitorCallback(this); } catch (RemoteException e) { @@ -95,23 +88,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mIsShowing = showing; mCallback.onShowingChanged(); - int retry = 2; - while (retry > 0) { - try { - mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId); - break; - } catch (RemoteException e) { - if (retry == 2) { - Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died" - + " -> refreshing service token and retrying"); - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - } else { - Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e); - } - --retry; - } - } } @Override // Binder interface @@ -123,10 +99,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mCurrentUserId = userId; } - private synchronized int getCurrentUser() { - return mCurrentUserId; - } - @Override // Binder interface public void onInputRestrictedStateChanged(boolean inputRestricted) { mInputRestricted = inputRestricted; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 7408dd40b5ca..5f5cd3c46117 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -53,6 +53,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.KeyStore; import android.service.trust.TrustAgentService; import android.text.TextUtils; import android.util.ArrayMap; @@ -135,6 +136,33 @@ public class TrustManagerService extends SystemService { @GuardedBy("mUserIsTrusted") private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray(); + /** + * Stores the locked state for users on the device. There are three different type of users + * which are handled slightly differently: + * <ul> + * <li> Users with real keyguard + * These are users who can be switched to ({@link UserInfo#supportsSwitchToByUser()}). Their + * locked state is derived by a combination of user secure state, keyguard state, trust agent + * decision and biometric authentication result. These are updated via + * {@link #refreshDeviceLockedForUser(int)} and result stored in {@link #mDeviceLockedForUser}. + * <li> Managed profiles with unified challenge + * Managed profile with unified challenge always shares the same locked state as their parent, + * so their locked state is not recorded in {@link #mDeviceLockedForUser}. Instead, + * {@link ITrustManager#isDeviceLocked(int)} always resolves their parent user handle and + * queries its locked state instead. + * <li> Managed profiles with separate challenge + * Locked state for profile with separate challenge is determined by other parts of the + * framework (mostly PowerManager) and pushed to TrustManagerService via + * {@link ITrustManager#setDeviceLockedForUser(int, boolean)}. Although in a corner case when + * the profile has a separate but empty challenge, setting its {@link #mDeviceLockedForUser} to + * {@code false} is actually done by {@link #refreshDeviceLockedForUser(int)}. + * </ul> + * TODO: Rename {@link ITrustManager#setDeviceLockedForUser(int, boolean)} to + * {@code setDeviceLockedForProfile} to better reflect its purpose. Unifying + * {@code setDeviceLockedForProfile} and {@link #setDeviceLockedForUser} would also be nice. + * At the moment they both update {@link #mDeviceLockedForUser} but have slightly different + * side-effects: one notifies trust agents while the other sends out a broadcast. + */ @GuardedBy("mDeviceLockedForUser") private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray(); @@ -601,6 +629,10 @@ public class TrustManagerService extends SystemService { } } + /** + * Update the user's locked state. Only applicable to users with a real keyguard + * ({@link UserInfo#supportsSwitchToByUser}) and unsecured managed profiles. + */ private void refreshDeviceLockedForUser(int userId) { if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) { Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle," @@ -661,6 +693,15 @@ public class TrustManagerService extends SystemService { } if (changed) { dispatchDeviceLocked(userId, locked); + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + // Also update the user's profiles who have unified challenge, since they + // share the same unlocked state (see {@link #isDeviceLocked(int)}) + for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) { + if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) { + KeyStore.getInstance().onUserLockedStateChanged(profileHandle, locked); + } + } } } @@ -1194,6 +1235,10 @@ public class TrustManagerService extends SystemService { return "0x" + Integer.toHexString(i); } + /** + * Changes the lock status for the given user. This is only applicable to managed profiles, + * other users should be handled by Keyguard. + */ @Override public void setDeviceLockedForUser(int userId, boolean locked) { enforceReportPermission(); @@ -1204,6 +1249,9 @@ public class TrustManagerService extends SystemService { synchronized (mDeviceLockedForUser) { mDeviceLockedForUser.put(userId, locked); } + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + if (locked) { try { ActivityManager.getService().notifyLockedProfile(userId); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 848971d3b044..1592f239fd2e 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4268,6 +4268,11 @@ class ActivityStack extends ConfigurationContainer { final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData) { + if (!srec.attachedToProcess()) { + // Nothing to do if the caller is not attached, because this method should be called + // from an alive activity. + return false; + } final TaskRecord task = srec.getTaskRecord(); final ArrayList<ActivityRecord> activities = task.mActivities; final int start = activities.indexOf(srec); @@ -4321,14 +4326,14 @@ class ActivityStack extends ConfigurationContainer { } if (parent != null && foundParentInTask) { + final int callingUid = srec.info.applicationInfo.uid; final int parentLaunchMode = parent.info.launchMode; final int destIntentFlags = destIntent.getFlags(); if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { - parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent, - srec.packageName); + parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName); } else { try { ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( @@ -4341,10 +4346,10 @@ class ActivityStack extends ConfigurationContainer { .setActivityInfo(aInfo) .setResultTo(parent.appToken) .setCallingPid(-1) - .setCallingUid(parent.launchedFromUid) - .setCallingPackage(parent.launchedFromPackage) + .setCallingUid(callingUid) + .setCallingPackage(srec.packageName) .setRealCallingPid(-1) - .setRealCallingUid(parent.launchedFromUid) + .setRealCallingUid(callingUid) .setComponentSpecified(true) .execute(); foundParentInTask = res == ActivityManager.START_SUCCESS; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5b697ee89602..f37698de34d5 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2763,6 +2763,11 @@ class ActivityStarter { return mRequest.intent; } + @VisibleForTesting + int getCallingUid() { + return mRequest.callingUid; + } + ActivityStarter setReason(String reason) { mRequest.reason = reason; return this; diff --git a/services/net/Android.bp b/services/net/Android.bp index bb5409b3e032..8b444b0fed41 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -12,8 +12,7 @@ java_library_static { ":services.net-sources", ], static_libs: [ - "dnsresolver_aidl_interface-V4-java", - "netd_aidl_interface-V3-java", + "netd_aidl_interfaces-platform-java", "netlink-client", "networkstack-client", "net-utils-services-common", @@ -44,7 +43,8 @@ java_library { "framework-wifi-util-lib", ], static_libs: [ - "dnsresolver_aidl_interface-V2-java", + // All the classes in netd_aidl_interface must be jarjar so they do not conflict with the + // classes generated by netd_aidl_interfaces-platform-java above. "netd_aidl_interface-V3-java", "netlink-client", "networkstack-client", diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index 163832983b5b..3465ea99bdae 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -73,7 +73,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { private static final int HDMI_3_PHYSICAL_ADDRESS = 0x2300; private int mInvokeDeviceEventState; private HdmiDeviceInfo mDeviceInfo; - private boolean mMutingEnabled; private boolean mArcSupport; private HdmiPortInfo[] mHdmiPortInfo; @@ -154,8 +153,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Override boolean readBooleanSystemProperty(String key, boolean defVal) { switch (key) { - case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE: - return mMutingEnabled; case Constants.PROPERTY_ARC_SUPPORT: return mArcSupport; default: @@ -209,7 +206,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); mNativeWrapper.clearResultMessages(); - mMutingEnabled = true; mArcSupport = true; mInvokeDeviceEventState = 0; mDeviceInfo = null; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index bde0ef6aa39e..ff27b9bb1c9e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -28,7 +28,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; @@ -54,8 +54,11 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import android.app.ActivityManager; +import android.app.IApplicationThread; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.os.UserHandle; @@ -82,8 +85,9 @@ public class ActivityStackTests extends ActivityTestsBase { @Before public void setUp() throws Exception { mDefaultDisplay = mRootActivityContainer.getDefaultDisplay(); - mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, - true /* onTop */)); + mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + spyOn(mStack); mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); } @@ -1078,6 +1082,37 @@ public class ActivityStackTests extends ActivityTestsBase { assertTrue(listener.mChanged); } + @Test + public void testNavigateUpTo() { + final ActivityStartController controller = mock(ActivityStartController.class); + final ActivityStarter starter = new ActivityStarter(controller, + mService, mService.mStackSupervisor, mock(ActivityStartInterceptor.class)); + doReturn(controller).when(mService).getActivityStartController(); + spyOn(starter); + doReturn(ActivityManager.START_SUCCESS).when(starter).execute(); + + final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); + final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask) + .setUid(firstActivity.getUid() + 1).build(); + doReturn(starter).when(controller).obtainStarter(eq(firstActivity.intent), anyString()); + + final IApplicationThread thread = secondActivity.app.getThread(); + secondActivity.app.setThread(null); + // This should do nothing from a non-attached caller. + assertFalse(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + + secondActivity.app.setThread(thread); + assertTrue(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + // The firstActivity uses default launch mode, so the activities between it and itself will + // be finished. + assertTrue(secondActivity.finishing); + assertTrue(firstActivity.finishing); + // The calling uid of the new activity should be the current real caller. + assertEquals(secondActivity.getUid(), starter.getCallingUid()); + } + private void verifyShouldSleepActivities(boolean focusedStack, boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { final ActivityDisplay display = mock(ActivityDisplay.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 84bdecb86826..f94f00203521 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -290,6 +290,7 @@ class ActivityTestsBase { aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; aInfo.packageName = mComponent.getPackageName(); + aInfo.name = mComponent.getClassName(); if (mTargetActivity != null) { aInfo.targetActivity = mTargetActivity; } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 8d53158b9f32..ce71511c0361 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -398,7 +398,7 @@ public class TelecomManager { * Optional extra for communicating the call network technology used by a * {@link android.telecom.Connection} to Telecom and InCallUI. * - * @see {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}. + * {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}. */ public static final String EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE"; diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 5149ad232705..41bab25af115 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3025,19 +3025,95 @@ public class CarrierConfigManager { public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string"; /** - * Timeout in seconds for displaying 5G icon, default value is 0 which means the timer is - * disabled. + * This configuration allows the system UI to determine how long to continue to display 5G icons + * when the device switches between different 5G scenarios. + * + * There are seven 5G scenarios: + * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using + * millimeter wave. + * 2. connected: device currently connected to 5G cell as the secondary cell but not using + * millimeter wave. + * 3. not_restricted_rrc_idle: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in IDLE state. + * 4. not_restricted_rrc_con: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in CONNECTED state. + * 5. restricted: device camped on a network that has 5G capability (not necessary to connect a + * 5G cell as a secondary cell) but the use of 5G is restricted. + * 6. legacy: device is not camped on a network that has 5G capability + * 7. any: any of the above scenarios + * + * The configured string contains various timer rules separated by a semicolon. + * Each rule will have three items: prior 5G scenario, current 5G scenario, and grace period + * in seconds before changing the icon. When the 5G state changes from the prior to the current + * 5G scenario, the system UI will continue to show the icon for the prior 5G scenario (defined + * in {@link #KEY_5G_ICON_CONFIGURATION_STRING}) for the amount of time specified by the grace + * period. If the prior 5G scenario is reestablished, the timer will reset and start again if + * the UE changes 5G scenarios again. Defined states (5G scenarios #1-5) take precedence over + * 'any' (5G scenario #6), and unspecified transitions have a default grace period of 0. + * The order of rules in the configuration determines the priority (the first applicable timer + * rule will be used). * - * System UI will show the 5G icon and start a timer with the timeout from this config when the - * device connects to a 5G cell. System UI stops displaying 5G icon when both the device - * disconnects from 5G cell and the timer is expired. + * Here is an example: "connected_mmwave,connected,30;connected_mmwave,any,10;connected,any,10" + * This configuration defines 3 timers: + * 1. When UE goes from 'connected_mmwave' to 'connected', system UI will continue to display + * the 5G icon for 'connected_mmwave' for 30 seconds. + * 2. When UE goes from 'connected_mmwave' to any other state (except for connected, since + * rule 1 would be used instead), system UI will continue to display the 5G icon for + * 'connected_mmwave' for 10 seconds. + * 3. When UE goes from 'connected' to any other state, system UI will continue to display the + * 5G icon for 'connected' for 10 seconds. * - * If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next - * lost. Allows us to momentarily lose 5G without blinking the icon. * @hide */ - public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = - "5g_icon_display_grace_period_sec_int"; + public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING = + "5g_icon_display_grace_period_string"; + + /** + * This configuration extends {@link #KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING} to allow the + * system UI to continue displaying 5G icons after the initial timer expires. + * + * There are seven 5G scenarios: + * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using + * millimeter wave. + * 2. connected: device currently connected to 5G cell as the secondary cell but not using + * millimeter wave. + * 3. not_restricted_rrc_idle: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in IDLE state. + * 4. not_restricted_rrc_con: device camped on a network that has 5G capability (not necessary + * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC + * currently in CONNECTED state. + * 5. restricted: device camped on a network that has 5G capability (not necessary to connect a + * 5G cell as a secondary cell) but the use of 5G is restricted. + * 6. legacy: device is not camped on a network that has 5G capability + * 7. any: any of the above scenarios + * + * The configured string contains various timer rules separated by a semicolon. + * Each rule will have three items: primary 5G scenario, secondary 5G scenario, and + * grace period in seconds before changing the icon. When the timer for the primary 5G timer + * expires, the system UI will continue to show the icon for the primary 5G scenario (defined + * in {@link #KEY_5G_ICON_CONFIGURATION_STRING}) for the amount of time specified by the grace + * period. If the primary 5G scenario is reestablished, the timers will reset and the system UI + * will continue to display the icon for the primary 5G scenario without interruption. If the + * secondary 5G scenario is lost, the timer will reset and the icon will reflect the true state. + * Defined states (5G scenarios #1-5) take precedence over 'any' (5G scenario #6), and + * unspecified transitions have a default grace period of 0. The order of rules in the + * configuration determines the priority (the first applicable timer rule will be used). + * + * Here is an example: "connected,not_restricted_rrc_idle,30" + * This configuration defines a secondary timer that extends the primary 'connected' timer. + * When the primary 'connected' timer expires while the UE is in the 'not_restricted_rrc_idle' + * 5G state, system UI will continue to display the 5G icon for 'connected' for 30 seconds. + * If the 5G state returns to 'connected', the timer will be reset without change to the icon, + * and if the 5G state changes to neither 'connected' not 'not_restricted_rrc_idle', the icon + * will change to reflect the true state. + * + * @hide + */ + public static final String KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING = + "5g_icon_display_secondary_grace_period_string"; /** * Controls time in milliseconds until DcTracker reevaluates 5G connection state. @@ -3629,6 +3705,17 @@ public class CarrierConfigManager { public static final String KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY = "missed_incoming_call_sms_originator_string_array"; + + /** + * String array of Apn Type configurations. + * The entries should be of form "APN_TYPE_NAME:priority". + * priority is an integer that is sorted from highest to lowest. + * example: cbs:5 + * + * @hide + */ + public static final String KEY_APN_PRIORITY_STRING_ARRAY = "apn_priority_string_array"; + /** * The patterns of missed incoming call sms. This is the regular expression used for * matching the missed incoming call's date, time, and caller id. The pattern should match @@ -4070,7 +4157,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_BANDWIDTH_STRING_ARRAY, new String[]{ "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA-IS95A:14,14", "CDMA-IS95B:14,14", "1xRTT:30,30", "EvDo-rev.0:750,48", "EvDo-rev.A:950,550", "HSDPA:4300,620", - "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550:", "eHRPD:750,48", + "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550", "eHRPD:750,48", "HSPAP:13000,3400", "TD-SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,15000", "NR_NSA_MMWAVE:145000,15000", "NR_SA:145000,15000"}); sDefaults.putBoolean(KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL, false); @@ -4089,7 +4176,8 @@ public class CarrierConfigManager { sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING, "connected_mmwave:5G,connected:5G,not_restricted_rrc_idle:5G," + "not_restricted_rrc_con:5G"); - sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0); + sDefaults.putString(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING, ""); + sDefaults.putString(KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING, ""); /* Default value is 1 hour. */ sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000); sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false); @@ -4159,6 +4247,10 @@ public class CarrierConfigManager { sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, TimeUnit.DAYS.toMillis(1)); sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY, new String[0]); + sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] { + "default:0", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2", + "ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3" + }); sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]); } diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java index 33a43c1e0319..1e5ce05ff28a 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -211,7 +211,7 @@ public abstract class CellIdentity implements Parcelable { } /** @hide */ - protected String getPlmn() { + public @Nullable String getPlmn() { if (mMccStr == null || mMncStr == null) return null; return mMccStr + mMncStr; } diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java index f21277cdd83c..68c833c37c99 100644 --- a/telephony/java/android/telephony/CellIdentityCdma.java +++ b/telephony/java/android/telephony/CellIdentityCdma.java @@ -279,6 +279,7 @@ public final class CellIdentityCdma extends CellIdentity { mLongitude = in.readInt(); mLatitude = in.readInt(); + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java index 1a913105db2e..849c613da748 100644 --- a/telephony/java/android/telephony/CellIdentityGsm.java +++ b/telephony/java/android/telephony/CellIdentityGsm.java @@ -323,6 +323,7 @@ public final class CellIdentityGsm extends CellIdentity { mBsic = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index 13a8273d64d4..1993550d52b8 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -403,6 +403,8 @@ public final class CellIdentityLte extends CellIdentity { mBandwidth = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index f0d878001bf4..8dd7bdd57841 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -273,6 +273,8 @@ public final class CellIdentityNr extends CellIdentity { mBands = in.createIntArray(); mNci = in.readLong(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); + + updateGlobalCellId(); } /** Implement the Parcelable interface */ diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java index 6dffe922ffd1..e74b70939d14 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -321,6 +321,8 @@ public final class CellIdentityTdscdma extends CellIdentity { mUarfcn = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java index eab174ade3b7..40cb27e95151 100644 --- a/telephony/java/android/telephony/CellIdentityWcdma.java +++ b/telephony/java/android/telephony/CellIdentityWcdma.java @@ -336,6 +336,8 @@ public final class CellIdentityWcdma extends CellIdentity { mUarfcn = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); + + updateGlobalCellId(); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index 45deea206cfc..3d96fc634d6a 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -231,6 +231,8 @@ public class MbmsDownloadSession implements AutoCloseable { private static final String DESTINATION_SANITY_CHECK_FILE_NAME = "destinationSanityCheckFile"; + private static final int MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE = 10 * 1024; // 10KB + private static AtomicBoolean sIsInitialized = new AtomicBoolean(false); private final Context mContext; @@ -318,6 +320,16 @@ public class MbmsDownloadSession implements AutoCloseable { return session; } + /** + * Returns the maximum size of the service announcement file that can be provided via + * {@link #addServiceAnnouncementFile} + * @return The maximum length of the byte array passed as an argument to + * {@link #addServiceAnnouncementFile}. + */ + public static int getMaximumServiceAnnouncementFileSize() { + return MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE; + } + private int bindAndInitialize() { mServiceConnection = new ServiceConnection() { @Override @@ -424,6 +436,60 @@ public class MbmsDownloadSession implements AutoCloseable { } /** + * Inform the middleware of a service announcement file received from a group communication + * server. + * + * When participating in a group call via the {@link MbmsGroupCallSession} API, applications may + * receive a service announcement file from the group call server that informs them of + * files that may be relevant to users communicating on the group call. + * + * After supplying the service announcement file received from the server to the middleware via + * this API, applications will receive information on the available files via + * {@link MbmsDownloadSessionCallback#onFileServicesUpdated}, and the available files will be + * downloadable via {@link MbmsDownloadSession#download} like other files published via + * {@link MbmsDownloadSessionCallback#onFileServicesUpdated}. + * + * Asynchronous error codes via the {@link MbmsDownloadSessionCallback#onError(int, String)} + * callback may include any of the errors that are not specific to the streaming use-case. + * + * May throw an {@link IllegalStateException} when the middleware has not yet been bound, + * or an {@link IllegalArgumentException} if the file is too large. + * + * @param fileContents The contents of the service announcement file received from the group + * call server. If the size of this array is greater than the value of + * {@link #getMaximumServiceAnnouncementFileSize()}, an + * {@link IllegalArgumentException} will be thrown. + */ + public void addServiceAnnouncementFile(@NonNull byte[] fileContents) { + IMbmsDownloadService downloadService = mService.get(); + if (downloadService == null) { + throw new IllegalStateException("Middleware not yet bound"); + } + + if (fileContents.length > MAX_SERVICE_ANNOUNCEMENT_FILE_SIZE) { + throw new IllegalArgumentException("File too large"); + } + + try { + int returnCode = downloadService.addServiceAnnouncementFile( + mSubscriptionId, fileContents); + if (returnCode == MbmsErrors.UNKNOWN) { + // Unbind and throw an obvious error + close(); + throw new IllegalStateException("Middleware must not return an unknown error code"); + } + if (returnCode != MbmsErrors.SUCCESS) { + sendErrorToApp(returnCode, null); + } + } catch (RemoteException e) { + Log.w(LOG_TAG, "Remote process died"); + mService.set(null); + sIsInitialized.set(false); + sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null); + } + } + + /** * Sets the temp file root for downloads. * All temp files created for the middleware to write to will be contained in the specified * directory. Applications that wish to specify a location only need to call this method once diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java index 2c4d5ae3b82b..3d5c6aad1042 100644 --- a/telephony/java/android/telephony/TelephonyDisplayInfo.java +++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java @@ -62,8 +62,6 @@ public final class TelephonyDisplayInfo implements Parcelable { * {@link TelephonyManager#NETWORK_TYPE_LTE} network and has E-UTRA-NR Dual Connectivity(EN-DC) * capability or is currently connected to the secondary * {@link TelephonyManager#NETWORK_TYPE_NR} cellular network on millimeter wave bands. - * - * @see AccessNetworkConstants.NgranBands#FREQUENCY_RANGE_GROUP_2 */ public static final int OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE = 4; @@ -154,7 +152,14 @@ public final class TelephonyDisplayInfo implements Parcelable { return Objects.hash(mNetworkType, mOverrideNetworkType); } - private static String overrideNetworkTypeToString(@OverrideNetworkType int type) { + /** + * Convert override network type to string. + * + * @param type Override network type + * @return Override network type in string format + * @hide + */ + public static String overrideNetworkTypeToString(@OverrideNetworkType int type) { switch (type) { case OVERRIDE_NETWORK_TYPE_NONE: return "NONE"; case OVERRIDE_NETWORK_TYPE_LTE_CA: return "LTE_CA"; @@ -168,6 +173,6 @@ public final class TelephonyDisplayInfo implements Parcelable { @Override public String toString() { return "TelephonyDisplayInfo {network=" + TelephonyManager.getNetworkTypeName(mNetworkType) - + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType); + + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType) + "}"; } } diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 44b0968eaa90..5500d635d2ff 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -269,10 +269,10 @@ public class EuiccManager { * only contains {@link #OPERATION_DOWNLOAD} and ErrorCode is 0 implies this is an unknown * Download error. * - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE} + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE */ public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; @@ -552,7 +552,7 @@ public class EuiccManager { /** * List of OperationCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}'s - * value, an integer. @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * value, an integer. @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE * * @hide */ @@ -575,44 +575,44 @@ public class EuiccManager { /** * Internal system error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SYSTEM = 1; /** * SIM slot error. Failed to switch slot, failed to access the physical slot etc. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SIM_SLOT = 2; /** * eUICC card error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_EUICC_CARD = 3; /** * Generic switching profile error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SWITCH = 4; /** * Download profile error. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_DOWNLOAD = 5; /** * Subscription's metadata error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_METADATA = 6; /** * eUICC returned an error defined in GSMA (SGP.22 v2.2) while running one of the ES10x * functions. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_EUICC_GSMA = 7; @@ -620,13 +620,13 @@ public class EuiccManager { * The exception of failing to execute an APDU command. It can be caused by an error * happening on opening the basic or logical channel, or the response of the APDU command is * not success (0x9000). - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_APDU = 8; /** * SMDX(SMDP/SMDS) error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SMDX = 9; @@ -655,19 +655,19 @@ public class EuiccManager { * Thus the integer stored in {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} is * 0xA8B1051(176885841) * - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10; /** * HTTP error - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int OPERATION_HTTP = 11; /** * List of ErrorCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -695,56 +695,56 @@ public class EuiccManager { /** * Operation such as downloading/switching to another profile failed due to device being * carrier locked. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CARRIER_LOCKED = 10000; /** * The activation code(SGP.22 v2.2 section[4.1]) is invalid. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_ACTIVATION_CODE = 10001; /** * The confirmation code(SGP.22 v2.2 section[4.7]) is invalid. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002; /** * The profile's carrier is incompatible with the LPA. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INCOMPATIBLE_CARRIER = 10003; /** * There is no more space available on the eUICC for new profiles. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004; /** * Timed out while waiting for an operation to complete. i.e restart, disable, * switch reset etc. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_TIME_OUT = 10005; /** * eUICC is missing or defective on the device. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_EUICC_MISSING = 10006; /** * The eUICC card(hardware) version is incompatible with the software - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_UNSUPPORTED_VERSION = 10007; /** * No SIM card is available in the device. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_SIM_MISSING = 10008; @@ -754,52 +754,52 @@ public class EuiccManager { * 2. GSMA(.22 v2.2) Profile Install Result - installFailedDueToDataMismatch * 3. operation was interrupted * 4. SIMalliance error in PEStatus(SGP.22 v2.2 section 2.5.6.1) - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INSTALL_PROFILE = 10009; /** * Failed to load profile onto eUICC due to Profile Poicly Rules. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_DISALLOWED_BY_PPR = 10010; /** * Address is missing e.g SMDS/SMDP address is missing. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_ADDRESS_MISSING = 10011; /** * Certificate needed for authentication is not valid or missing. E.g SMDP/SMDS authentication * failed. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CERTIFICATE_ERROR = 10012; /** * No profiles available. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_NO_PROFILES_AVAILABLE = 10013; /** * Failure to create a connection. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_CONNECTION_ERROR = 10014; /** * Response format is invalid. e.g SMDP/SMDS response contains invalid json, header or/and ASN1. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_INVALID_RESPONSE = 10015; /** * The operation is currently busy, try again later. - * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details + * @see #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE */ public static final int ERROR_OPERATION_BUSY = 10016; diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 95ebbf39e944..872f49d65d25 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -141,8 +141,7 @@ public class ImsMmTelManager implements RegistrationManager { } /** - * Receives IMS capability status updates from the ImsService. This information is also - * available via the {@see #isAvailable(int, int)} method below. + * Receives IMS capability status updates from the ImsService. * * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) @@ -195,8 +194,6 @@ public class ImsMmTelManager implements RegistrationManager { * If unavailable, the feature is not able to support the unavailable capability at this * time. * - * This information can also be queried using the {@see #isAvailable(int, int)} API. - * * @param capabilities The new availability of the capabilities. */ public void onCapabilitiesStatusChanged( @@ -497,8 +494,7 @@ public class ImsMmTelManager implements RegistrationManager { /** * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service * availability updates for the subscription specified in - * {@link ImsManager#getImsMmTelManager(int)}. The method {@see #isAvailable(int, int)} - * can also be used to query this information at any time. + * {@link ImsManager#getImsMmTelManager(int)}. * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call @@ -640,7 +636,6 @@ public class ImsMmTelManager implements RegistrationManager { * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL - * @see #setAdvancedCallingSettingEnabled(boolean) * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for advanced calling is enabled, false otherwise. @@ -859,7 +854,6 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user’s “Video Calling” setting is currently enabled. - * @see #setVtSettingEnabled(boolean) */ @RequiresPermission(anyOf = { android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, @@ -934,7 +928,6 @@ public class ImsMmTelManager implements RegistrationManager { * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. - * @see #setVoWiFiSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1012,7 +1005,6 @@ public class ImsMmTelManager implements RegistrationManager { * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for Voice over WiFi while roaming is enabled, false * if disabled. - * @see #setVoWiFiRoamingSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1131,7 +1123,6 @@ public class ImsMmTelManager implements RegistrationManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} - * @see #setVoWiFiSettingEnabled(boolean) */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(anyOf = { @@ -1316,7 +1307,6 @@ public class ImsMmTelManager implements RegistrationManager { * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. - * @see android.telecom.TelecomManager#getCurrentTtyMode * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index 1dbaff5df802..e085dec10546 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -270,7 +270,7 @@ public interface RegistrationManager { * inactive subscription, it will result in a no-op. * * @param c The {@link RegistrationCallback} to be removed. - * @see SubscriptionManager.OnSubscriptionsChangedListener + * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index a3ce1b585f76..9ec3f61ba6a7 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -218,13 +218,7 @@ public class MmTelFeature extends ImsFeature { * {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}. * - * The capabilities of this MmTelFeature will be set by the framework and can be queried with - * {@see #queryCapabilityStatus()}. - * - * This MmTelFeature can then return the status of each of these capabilities (enabled or not) - * by sending a {@see #notifyCapabilitiesStatusChanged} callback to the framework. The current - * status can also be queried using {@see #queryCapabilityStatus()}. - * @see #isCapable(int) + * The capabilities of this MmTelFeature will be set by the framework. */ public static class MmTelCapabilities extends Capabilities { diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java index ce9a73a21657..a9a33c0e1507 100644 --- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java @@ -403,8 +403,7 @@ public class ImsSmsImplBase { message.mWrappedSmsMessage.mMessageRef, STATUS_REPORT_STATUS_ERROR); } else { - Log.w(LOG_TAG, - "onSmsStatusReportReceivedWithoutMessageRef: Invalid pdu entered."); + Log.w(LOG_TAG, "onSmsStatusReportReceived: Invalid pdu entered."); acknowledgeSmsReport(token, 0, STATUS_REPORT_STATUS_ERROR); } } diff --git a/telephony/java/android/telephony/mbms/MbmsErrors.java b/telephony/java/android/telephony/mbms/MbmsErrors.java index 52e4d333b29d..8611d26bc85b 100644 --- a/telephony/java/android/telephony/mbms/MbmsErrors.java +++ b/telephony/java/android/telephony/mbms/MbmsErrors.java @@ -16,8 +16,12 @@ package android.telephony.mbms; +import android.annotation.IntDef; import android.telephony.MbmsStreamingSession; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public class MbmsErrors { /** * Indicates that the middleware has sent an error code that is not defined in the version of @@ -138,6 +142,13 @@ public class MbmsErrors { /** Indicates the the middleware has no record of the supplied {@link FileInfo} */ public static final int ERROR_UNKNOWN_FILE_INFO = 403; + + /** + * Indicates that the service announcement file passed via + * {@link android.telephony.MbmsDownloadSession#addServiceAnnouncementFile(byte[])} + * is malformed. + */ + public static final int ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE = 404; } /** @@ -156,5 +167,35 @@ public class MbmsErrors { public static final int ERROR_DUPLICATE_START_GROUP_CALL = 502; } + /** @hide */ + @IntDef(value = { + SUCCESS, + ERROR_NO_UNIQUE_MIDDLEWARE, + ERROR_MIDDLEWARE_NOT_BOUND, + ERROR_MIDDLEWARE_LOST, + InitializationErrors.ERROR_DUPLICATE_INITIALIZE, + InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED, + InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY, + GeneralErrors.ERROR_OUT_OF_MEMORY, + GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE, + GeneralErrors.ERROR_IN_E911, + GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE, + GeneralErrors.ERROR_UNABLE_TO_READ_SIM, + GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED, + StreamingErrors.ERROR_CONCURRENT_SERVICE_LIMIT_REACHED, + StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, + StreamingErrors.ERROR_DUPLICATE_START_STREAM, + DownloadErrors.ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT, + DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST, + DownloadErrors.ERROR_UNKNOWN_FILE_INFO, + DownloadErrors.ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE, + GroupCallErrors.ERROR_UNABLE_TO_START_SERVICE, + GroupCallErrors.ERROR_DUPLICATE_START_GROUP_CALL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MbmsError { + } + private MbmsErrors() {} } diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl index 445087fb78d5..36136ab280c4 100755 --- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl +++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl @@ -35,6 +35,8 @@ interface IMbmsDownloadService int setTempFileRootDirectory(int subId, String rootDirectoryPath); + int addServiceAnnouncementFile(int subId, in byte[] fileContents); + int download(in DownloadRequest downloadRequest); int addStatusListener(in DownloadRequest downloadRequest, diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java index 9f22d0a49806..3279ce66cd17 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java @@ -216,6 +216,28 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub { } /** + * Called when the client application wishes to receive file information according to a + * service announcement file received from a group call server. + * + * The service announcement file is in the format of a multipart MIME file with XML parts, + * though no validation is performed on the contents of the {@code fileContents} argument -- + * implementing middleware applications should perform their own validation and return + * {@link MbmsErrors.DownloadErrors#ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE} if the file is + * malformed. + * + * @param subscriptionId The subscription id the service announcement applies to. + * @param fileContents The contents of the service announcement file. + * @return {@link MbmsErrors#SUCCESS}, or + * {@link MbmsErrors.DownloadErrors#ERROR_MALFORMED_SERVICE_ANNOUNCEMENT_FILE} + */ + // TODO: are there any public specifications of what the file format is that I can link to? + @Override + public @MbmsErrors.MbmsError int addServiceAnnouncementFile( + int subscriptionId, @NonNull byte[] fileContents) { + return 0; + } + + /** * Issues a request to download a set of files. * * The middleware should expect that {@link #setTempFileRootDirectory(int, String)} has been diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 18e25921555a..76fc4f7d0519 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -109,11 +109,10 @@ public class DctConstants { public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49; public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50; public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51; - public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52; - public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53; - public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54; - public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55; - public static final int EVENT_SIM_STATE_UPDATED = BASE + 56; + public static final int EVENT_TELEPHONY_DISPLAY_INFO_CHANGED = BASE + 52; + public static final int EVENT_NR_TIMER_WATCHDOG = BASE + 53; + public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 54; + public static final int EVENT_SIM_STATE_UPDATED = BASE + 55; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index ff70f8ba3936..29286e8f429e 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -240,5 +240,5 @@ public interface TelephonyProperties * two. * Type: int */ - static final String PROPERTY_MAX_ACTIVE_MODEMS = "ro.telephony.max.active.modems"; + static final String PROPERTY_MAX_ACTIVE_MODEMS = "telephony.active_modems.max_count"; } diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt index ef15b668e24c..a50f0461fae6 100644 --- a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt +++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt @@ -39,12 +39,12 @@ class MatchAllNetworkSpecifierTest { } @Test(expected = IllegalStateException::class) - fun testSatisfiedBy() { + fun testCanBeSatisfiedBy() { val specifier = MatchAllNetworkSpecifier() val discoverySession = Mockito.mock(DiscoverySession::class.java) val peerHandle = Mockito.mock(PeerHandle::class.java) val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle).build() - specifier.satisfiedBy(wifiAwareNetworkSpecifier) + specifier.canBeSatisfiedBy(wifiAwareNetworkSpecifier) } } diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index eec3cdbe8d7f..8c2de4035d0b 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -52,7 +52,7 @@ class TestNetworkStackService : Service() { doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE) } - private class TestPermissionChecker : NetworkStackConnector.PermissionChecker() { + private class TestPermissionChecker : NetworkStackService.PermissionChecker() { override fun enforceNetworkStackCallingPermission() = Unit } @@ -62,8 +62,8 @@ class TestNetworkStackService : Service() { override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit } - private inner class TestNetworkStackConnector(context: Context) : - NetworkStackConnector(context, TestPermissionChecker()) { + private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector( + context, TestPermissionChecker(), NetworkStackService.Dependencies()) { private val network = Network(TEST_NETID) private val privateDnsBypassNetwork = TestNetwork(TEST_NETID) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 656fe489d8b8..bef682b2822f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5394,8 +5394,6 @@ public class ConnectivityServiceTest { // Even though the VPN is unvalidated, it becomes the default network for our app. callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); - // TODO: this looks like a spurious callback. - callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); callback.assertNoCallback(); assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore()); diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 1db90b71e2b1..a1bb0d586916 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -60,14 +60,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; import android.content.Context; @@ -95,8 +94,6 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.SimpleClock; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; @@ -126,6 +123,7 @@ import java.io.File; import java.time.Clock; import java.time.ZoneOffset; import java.util.Objects; +import java.util.concurrent.Executor; /** * Tests for {@link NetworkStatsService}. @@ -168,14 +166,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private @Mock NetworkStatsSettings mSettings; private @Mock IBinder mBinder; private @Mock AlarmManager mAlarmManager; - private @Mock TelephonyManager mTelephonyManager; + @Mock + private NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; private HandlerThread mHandlerThread; private NetworkStatsService mService; private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; - @Nullable - private PhoneStateListener mPhoneStateListener; private final Clock mClock = new SimpleClock(ZoneOffset.UTC) { @Override @@ -203,8 +200,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mHandlerThread = new HandlerThread("HandlerThread"); final NetworkStatsService.Dependencies deps = makeDependencies(); mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, - mClock, mTelephonyManager, mSettings, - mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps); + mClock, mSettings, mStatsFactory, new NetworkStatsObservers(), mStatsDir, + getBaseDir(mStatsDir), deps); mElapsedRealtime = 0L; @@ -224,12 +221,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { ArgumentCaptor.forClass(INetworkManagementEventObserver.class); verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - - // Capture the phone state listener that created by service. - final ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt()); - mPhoneStateListener = phoneStateListenerCaptor.getValue(); } @NonNull @@ -239,6 +230,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public HandlerThread makeHandlerThread() { return mHandlerThread; } + + @Override + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor( + @NonNull Context context, @NonNull Executor executor, + @NonNull NetworkStatsService service) { + + return mNetworkStatsSubscriptionsMonitor; + } }; } @@ -678,10 +677,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // TODO: support per IMSI state private void setMobileRatTypeAndWaitForIdle(int ratType) { - final ServiceState mockSs = mock(ServiceState.class); - when(mockSs.getDataNetworkType()).thenReturn(ratType); - mPhoneStateListener.onServiceStateChanged(mockSs); - + when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString())) + .thenReturn(ratType); + mService.handleOnCollapsedRatTypeChanged(); HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); } diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index f354bb610224..77e2a6bb21de 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1659,9 +1659,12 @@ class Linker { return 1; } - // First extract the Package name without modifying it (via --rename-manifest-package). - if (Maybe<AppInfo> maybe_app_info = + // Determine the package name under which to merge resources. + if (options_.rename_resources_package) { + context_->SetCompilationPackage(options_.rename_resources_package.value()); + } else if (Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) { + // Extract the package name from the manifest ignoring the value of --rename-manifest-package. const AppInfo& app_info = maybe_app_info.value(); context_->SetCompilationPackage(app_info.package); } diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index be4d474ebdf3..e62e0a6b9f62 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -43,6 +43,7 @@ struct LinkOptions { bool output_to_directory = false; bool auto_add_overlay = false; OutputFormat output_format = OutputFormat::kApk; + Maybe<std::string> rename_resources_package; // Java/Proguard options. Maybe<std::string> generate_java_class_path; @@ -244,6 +245,8 @@ class LinkCommand : public Command { &options_.auto_add_overlay); AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.", &options_.manifest_fixer_options.rename_manifest_package); + AddOptionalFlag("--rename-resources-package", "Renames the package in resources table", + &options_.rename_resources_package); AddOptionalFlag("--rename-instrumentation-target-package", "Changes the name of the target package for instrumentation. Most useful\n" "when used in conjunction with --rename-manifest-package.", diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 47d8f13bf9ef..29e09a11590b 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -892,7 +892,7 @@ public class WifiManager { * The RSSI (signal strength) has changed. * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE - * @see {@link #EXTRA_NEW_RSSI} + * @see #EXTRA_NEW_RSSI */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java index 00cb243efcaa..689ace5bf5b9 100644 --- a/wifi/java/android/net/wifi/WpsInfo.java +++ b/wifi/java/android/net/wifi/WpsInfo.java @@ -22,7 +22,7 @@ import android.os.Parcelable; /** * A class representing Wi-Fi Protected Setup * - * {@see WifiP2pConfig} + * {@see android.net.wifi.p2p.WifiP2pConfig} */ public class WpsInfo implements Parcelable { |