diff options
375 files changed, 6063 insertions, 3452 deletions
diff --git a/Android.bp b/Android.bp index a93a155089ce..c303f5490d57 100644 --- a/Android.bp +++ b/Android.bp @@ -456,6 +456,7 @@ java_library { "com.android.sysprop.apex", "com.android.sysprop.init", + "com.android.sysprop.localization", "PlatformProperties", ], sdk_version: "core_platform", @@ -717,7 +718,6 @@ filegroup { "core/java/com/android/internal/util/TrafficStatsConstants.java", "core/java/com/android/internal/util/WakeupMessage.java", "core/java/com/android/internal/util/TokenBucket.java", - "core/java/android/net/shared/*.java", ], } @@ -727,7 +727,6 @@ java_library { name: "framework-wifi-util-lib", sdk_version: "module_current", srcs: [ - "core/java/android/net/shared/Inet4AddressUtils.java", "core/java/com/android/internal/util/Preconditions.java", ], libs: [ @@ -744,7 +743,6 @@ filegroup { name: "framework-services-net-module-wifi-shared-srcs", srcs: [ "core/java/android/net/DhcpResults.java", - "core/java/android/net/shared/InetAddressUtils.java", "core/java/android/net/util/IpUtils.java", "core/java/android/util/LocalLog.java", ], @@ -761,7 +759,6 @@ filegroup { "core/java/com/android/internal/util/State.java", "core/java/com/android/internal/util/StateMachine.java", "core/java/com/android/internal/util/TrafficStatsConstants.java", - "core/java/android/net/shared/Inet4AddressUtils.java", ], } diff --git a/ApiDocs.bp b/ApiDocs.bp index 029699efe3b9..ca921ff97c35 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -150,12 +150,10 @@ doc_defaults { ":current-support-api", ":current-androidx-api", ], - create_stubs: false, } doc_defaults { name: "framework-dokka-docs-default", - create_stubs: false, } droiddoc { diff --git a/StubLibraries.bp b/StubLibraries.bp index 26478d3bad26..b999a10d0a3f 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -299,6 +299,15 @@ java_defaults { compile_dex: true, } +java_defaults { + name: "android_stubs_dists_default", + dist: { + targets: ["sdk", "win_sdk"], + tag: ".jar", + dest: "android.jar", + }, +} + java_library_static { name: "android_stubs_current", srcs: [ ":api-stubs-docs" ], @@ -308,20 +317,54 @@ java_library_static { java_library_static { name: "android_system_stubs_current", srcs: [ ":system-api-stubs-docs" ], - defaults: ["android_defaults_stubs_current"], + defaults: [ + "android_defaults_stubs_current", + "android_stubs_dists_default", + ], + dist: { + dir: "apistubs/android/system", + }, + dists: [ + { + // Legacy dist path + targets: ["sdk", "win_sdk"], + tag: ".jar", + dest: "android_system.jar", + }, + ], } java_library_static { name: "android_test_stubs_current", srcs: [ ":test-api-stubs-docs" ], - defaults: ["android_defaults_stubs_current"], + defaults: [ + "android_defaults_stubs_current", + "android_stubs_dists_default", + ], + dist: { + dir: "apistubs/android/test", + }, + dists: [ + { + // Legacy dist path + targets: ["sdk", "win_sdk"], + tag: ".jar", + dest: "android_test.jar", + }, + ], } java_library_static { name: "android_module_lib_stubs_current", srcs: [ ":module-lib-api-stubs-docs-non-updatable" ], - defaults: ["android_defaults_stubs_current"], + defaults: [ + "android_defaults_stubs_current", + "android_stubs_dists_default", + ], libs: ["sdk_system_29_android"], + dist: { + dir: "apistubs/android/module-lib", + }, } java_library_static { diff --git a/api/current.txt b/api/current.txt index 3f029a512dff..f51c3af110b9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -43556,6 +43556,7 @@ package android.system { package android.telecom { public final class Call { + method public void addConferenceParticipants(@NonNull java.util.List<android.net.Uri>); method public void answer(int); method public void conference(android.telecom.Call); method public void deflect(android.net.Uri); @@ -43664,6 +43665,7 @@ package android.telecom { method public static boolean hasProperty(int, int); method public boolean hasProperty(int); method public static String propertiesToString(int); + field public static final int CAPABILITY_ADD_PARTICIPANT = 33554432; // 0x2000000 field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 @@ -43693,6 +43695,7 @@ package android.telecom { field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000 field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800 field public static final int PROPERTY_RTT = 1024; // 0x400 @@ -43770,6 +43773,7 @@ package android.telecom { public abstract class Conference extends android.telecom.Conferenceable { ctor public Conference(android.telecom.PhoneAccountHandle); method public final boolean addConnection(android.telecom.Connection); + method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle); method public final void destroy(); method public final android.telecom.CallAudioState getCallAudioState(); method public final java.util.List<android.telecom.Connection> getConferenceableConnections(); @@ -43785,6 +43789,9 @@ package android.telecom { method public final android.telecom.StatusHints getStatusHints(); method public android.telecom.Connection.VideoProvider getVideoProvider(); method public int getVideoState(); + method public final boolean isRingbackRequested(); + method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>); + method public void onAnswer(int); method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onConnectionAdded(android.telecom.Connection); method public void onDisconnect(); @@ -43793,6 +43800,7 @@ package android.telecom { method public void onMerge(android.telecom.Connection); method public void onMerge(); method public void onPlayDtmfTone(char); + method public void onReject(); method public void onSeparate(android.telecom.Connection); method public void onStopDtmfTone(); method public void onSwap(); @@ -43813,6 +43821,8 @@ package android.telecom { method public final void setDisconnected(android.telecom.DisconnectCause); method public final void setExtras(@Nullable android.os.Bundle); method public final void setOnHold(); + method public final void setRingbackRequested(boolean); + method public final void setRinging(); method public final void setStatusHints(android.telecom.StatusHints); method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider); method public final void setVideoState(android.telecom.Connection, int); @@ -43849,6 +43859,7 @@ package android.telecom { method public final boolean isRingbackRequested(); method public final void notifyConferenceMergeFailed(); method public void onAbort(); + method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>); method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); @@ -43928,6 +43939,7 @@ package android.telecom { field public static final int AUDIO_CODEC_GSM_HR = 10; // 0xa field public static final int AUDIO_CODEC_NONE = 0; // 0x0 field public static final int AUDIO_CODEC_QCELP13K = 3; // 0x3 + field public static final int CAPABILITY_ADD_PARTICIPANT = 67108864; // 0x4000000 field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000 @@ -43971,6 +43983,7 @@ package android.telecom { field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4 + field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 4096; // 0x1000 field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int PROPERTY_IS_RTT = 256; // 0x100 field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400 @@ -44066,9 +44079,13 @@ package android.telecom { method public void onConference(android.telecom.Connection, android.telecom.Connection); method public void onConnectionServiceFocusGained(); method public void onConnectionServiceFocusLost(); + method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); @@ -44379,6 +44396,7 @@ package android.telecom { method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int); method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle); + method public void addNewIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.os.Bundle); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification(); method public android.content.Intent createManageBlockedNumbersIntent(); method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall(); @@ -44406,6 +44424,7 @@ package android.telecom { method public void registerPhoneAccount(android.telecom.PhoneAccount); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger(); + method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull java.util.List<android.net.Uri>, @NonNull android.os.Bundle); method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle); field public static final String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER"; field public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; @@ -44943,6 +44962,8 @@ package android.telephony { field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool"; field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool"; + field public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool"; + field public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool"; field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool"; field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool"; diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index 283af068a077..5bc10ece4db5 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -49,3 +49,17 @@ package android.net { } +package android.os { + + public class Binder implements android.os.IBinder { + method public final void markVintfStability(); + } + + public interface Parcelable { + method public default int getStability(); + field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0 + field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1 + } + +} + diff --git a/api/system-current.txt b/api/system-current.txt index a10880bee172..cbad95ab6835 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8932,10 +8932,10 @@ package android.telephony { public class SubscriptionManager { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription(); method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String); - method @NonNull public int[] getActiveAndHiddenSubscriptionIdList(); - method @NonNull public int[] getActiveSubscriptionIdList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String); method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int); method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int); diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 24fbf21f463f..e494ea3b03c2 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -118,7 +118,6 @@ cc_defaults { static_libs: [ "libhealthhalutils", - "libplatformprotos", ], shared_libs: [ diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp index af8b3af6ea61..05acef8b219d 100644 --- a/cmds/statsd/src/HashableDimensionKey.cpp +++ b/cmds/statsd/src/HashableDimensionKey.cpp @@ -16,8 +16,6 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" -#include <mutex> - #include "HashableDimensionKey.h" #include "FieldValue.h" diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index af4f67501ec6..a730a0de6b88 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -16,12 +16,12 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" -#include "statslog.h" + +#include "StatsLogProcessor.h" #include <android-base/file.h> -#include <dirent.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h> -#include "StatsLogProcessor.h" + #include "android-base/stringprintf.h" #include "atoms_info.h" #include "external/StatsPullerManager.h" @@ -29,12 +29,9 @@ #include "metrics/CountMetricProducer.h" #include "stats_log_util.h" #include "stats_util.h" +#include "statslog.h" #include "storage/StorageManager.h" -#include <log/log_event_list.h> -#include <utils/Errors.h> -#include <utils/SystemClock.h> - using namespace android; using android::base::StringPrintf; using android::util::FIELD_COUNT_REPEATED; @@ -45,8 +42,6 @@ using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; using android::util::FIELD_TYPE_STRING; using android::util::ProtoOutputStream; -using std::make_unique; -using std::unique_ptr; using std::vector; namespace android { diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index cb497fc4a79a..d21c10c6800b 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -27,13 +27,11 @@ #include "subscriber/SubscriberReporter.h" #include <android-base/file.h> -#include <android-base/stringprintf.h> #include <android-base/strings.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionController.h> #include <cutils/multiuser.h> -#include <dirent.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <frameworks/base/cmds/statsd/src/uid_data.pb.h> #include <private/android_filesystem_config.h> @@ -42,17 +40,13 @@ #include <stdlib.h> #include <sys/system_properties.h> #include <unistd.h> -#include <utils/Looper.h> #include <utils/String16.h> -#include <chrono> using namespace android; using android::base::StringPrintf; using android::util::FIELD_COUNT_REPEATED; -using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; -using android::util::ProtoReader; namespace android { namespace os { diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index f6ac6360723b..991a205e111d 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -36,11 +36,9 @@ #include <binder/ParcelFileDescriptor.h> #include <utils/Looper.h> -#include <deque> #include <mutex> using namespace android; -using namespace android::base; using namespace android::binder; using namespace android::frameworks::stats::V1_0; using namespace android::os; diff --git a/cmds/statsd/src/anomaly/AlarmMonitor.h b/cmds/statsd/src/anomaly/AlarmMonitor.h index bca858e67f13..219695ef5e43 100644 --- a/cmds/statsd/src/anomaly/AlarmMonitor.h +++ b/cmds/statsd/src/anomaly/AlarmMonitor.h @@ -21,8 +21,6 @@ #include <android/os/IStatsCompanionService.h> #include <utils/RefBase.h> -#include <queue> -#include <set> #include <unordered_set> #include <vector> diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h index e9414735b82b..794ee988ef55 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.h +++ b/cmds/statsd/src/anomaly/AnomalyTracker.h @@ -16,8 +16,6 @@ #pragma once -#include <memory> // unique_ptr - #include <stdlib.h> #include <gtest/gtest_prod.h> diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp index 4c30c4cb223c..5a4a41d01de6 100644 --- a/cmds/statsd/src/anomaly/subscriber_util.cpp +++ b/cmds/statsd/src/anomaly/subscriber_util.cpp @@ -17,10 +17,6 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" -#include <android/os/IIncidentManager.h> -#include <android/os/IncidentReportArgs.h> -#include <binder/IServiceManager.h> - #include "external/Perfetto.h" #include "subscriber/IncidentdReporter.h" #include "subscriber/SubscriberReporter.h" diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index c8f2efab3783..b8de3f0eff75 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -60,7 +60,7 @@ import "frameworks/base/core/proto/android/view/enums.proto"; import "frameworks/base/core/proto/android/wifi/enums.proto"; /** - * The master atom class. This message defines all of the available + * The primary atom class. This message defines all of the available * raw stats log events from the Android system, also known as "atoms." * * This field contains a single oneof with all of the available messages. @@ -365,6 +365,7 @@ message Atom { NetworkDhcpRenewReported network_dhcp_renew_reported = 291 [(log_from_module) = "network_stack"]; NetworkValidationReported network_validation_reported = 292 [(log_from_module) = "network_stack"]; NetworkStackQuirkReported network_stack_quirk_reported = 293 [(log_from_module) = "network_stack"]; + KeystoreKeyEventReported keystore_key_event_reported = 302; NetworkTetheringReported network_tethering_reported = 303 [(log_from_module) = "network_tethering"]; } @@ -7903,3 +7904,111 @@ message SupportedRadioAccessFamily { // See android.telephony.TelephonyManager.NetworkTypeBitMask. optional int64 network_type_bitmask = 1; } + +/** + * Logs: i) creation of different types of cryptographic keys in the keystore, + * ii) operations performed using the keys, + * iii) attestation of the keys + * Logged from: system/security/keystore/key_event_log_handler.cpp + */ +message KeystoreKeyEventReported { + + enum Algorithm { + /** Asymmetric algorithms. */ + RSA = 1; + // 2 removed, do not reuse. + EC = 3; + /** Block cipher algorithms */ + AES = 32; + TRIPLE_DES = 33; + /** MAC algorithms */ + HMAC = 128; + }; + /** Algorithm associated with the key */ + optional Algorithm algorithm = 1; + + /** Size of the key */ + optional int32 key_size = 2; + + enum KeyOrigin { + /** Generated in keymaster. Should not exist outside the TEE. */ + GENERATED = 0; + /** Derived inside keymaster. Likely exists off-device. */ + DERIVED = 1; + /** Imported into keymaster. Existed as cleartext in Android. */ + IMPORTED = 2; + /** Keymaster did not record origin. */ + UNKNOWN = 3; + /** Securely imported into Keymaster. */ + SECURELY_IMPORTED = 4; + }; + /* Logs whether the key was generated, imported, securely imported, or derived.*/ + optional KeyOrigin key_origin = 3; + + enum HardwareAuthenticatorType { + NONE = 0; + PASSWORD = 1; + FINGERPRINT = 2; + // Additional entries must be powers of 2. + }; + /** + * What auth types does this key require? If none, + * then no auth required. + */ + optional HardwareAuthenticatorType user_auth_type = 4; + + /** + * If user authentication is required, is the requirement time based? If it + * is not time based then this field will not be used and the key is per + * operation. Per operation keys must be user authenticated on each usage. + */ + optional int32 user_auth_key_timeout_secs = 5; + + /** + * padding mode, digest, block_mode and purpose should ideally be repeated + * fields. However, since statsd does not support repeated fields in + * pushed atoms, they are represented using bitmaps. + */ + + /** Track which padding mode is being used.*/ + optional int32 padding_mode_bitmap = 6; + + /** Track which digest is being used. */ + optional int32 digest_bitmap = 7; + + /** Track what block mode is being used (for encryption). */ + optional int32 block_mode_bitmap = 8; + + /** Track what purpose is this key serving. */ + optional int32 purpose_bitmap = 9; + + enum EcCurve { + P_224 = 0; + P_256 = 1; + P_384 = 2; + P_521 = 3; + }; + /** Which ec curve was selected if elliptic curve cryptography is in use **/ + optional EcCurve ec_curve = 10; + + enum KeyBlobUsageRequirements { + STANDALONE = 0; + REQUIRES_FILE_SYSTEM = 1; + }; + /** Standalone or is a file system required */ + optional KeyBlobUsageRequirements key_blob_usage_reqs = 11; + + enum Type { + KEY_OPERATION = 0; + KEY_CREATION = 1; + KEY_ATTESTATION = 2; + } + /** Key creation event, operation event or attestation event? */ + optional Type type = 12; + + /** Was the key creation, operation, or attestation successful? */ + optional bool was_successful = 13; + + /** Response code or error code */ + optional int32 error_code = 14; +} diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index 60a4b236df11..cf0cc3d59d86 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -18,15 +18,10 @@ #include "Log.h" #include "CombinationConditionTracker.h" -#include <log/logprint.h> - namespace android { namespace os { namespace statsd { -using std::map; -using std::string; -using std::unique_ptr; using std::unordered_map; using std::vector; diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index 1f4266b61cdf..5ff0e1d5a885 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -21,10 +21,8 @@ #include "matchers/LogMatchingTracker.h" #include "matchers/matcher_util.h" -#include <log/logprint.h> #include <utils/RefBase.h> -#include <unordered_set> #include <unordered_map> namespace android { diff --git a/cmds/statsd/src/condition/ConditionWizard.cpp b/cmds/statsd/src/condition/ConditionWizard.cpp index 23a9d371145e..f371316a1420 100644 --- a/cmds/statsd/src/condition/ConditionWizard.cpp +++ b/cmds/statsd/src/condition/ConditionWizard.cpp @@ -14,14 +14,11 @@ * limitations under the License. */ #include "ConditionWizard.h" -#include <unordered_set> namespace android { namespace os { namespace statsd { -using std::map; -using std::string; using std::vector; ConditionState ConditionWizard::query(const int index, const ConditionKey& parameters, diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index 87104a34c009..12ff184a2608 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -24,11 +24,7 @@ namespace android { namespace os { namespace statsd { -using std::map; -using std::string; -using std::unique_ptr; using std::unordered_map; -using std::vector; SimpleConditionTracker::SimpleConditionTracker( const ConfigKey& key, const int64_t& id, const int index, diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp index 35e03e45c785..60b8c53e91e1 100644 --- a/cmds/statsd/src/condition/condition_util.cpp +++ b/cmds/statsd/src/condition/condition_util.cpp @@ -18,11 +18,6 @@ #include "condition_util.h" -#include <log/event_tag_map.h> -#include <log/log_event_list.h> -#include <log/logprint.h> -#include <utils/Errors.h> -#include <unordered_map> #include "../matchers/matcher_util.h" #include "ConditionTracker.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" @@ -32,9 +27,6 @@ namespace android { namespace os { namespace statsd { -using std::set; -using std::string; -using std::unordered_map; using std::vector; diff --git a/cmds/statsd/src/config/ConfigListener.h b/cmds/statsd/src/config/ConfigListener.h index 54e77701b7dc..dcd5e52feefd 100644 --- a/cmds/statsd/src/config/ConfigListener.h +++ b/cmds/statsd/src/config/ConfigListener.h @@ -19,14 +19,12 @@ #include "config/ConfigKey.h" #include <utils/RefBase.h> -#include <string> namespace android { namespace os { namespace statsd { using android::RefBase; -using std::string; /** * Callback for different subsystems inside statsd to implement to find out diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp index fc949b494194..13d251ab7736 100644 --- a/cmds/statsd/src/config/ConfigManager.cpp +++ b/cmds/statsd/src/config/ConfigManager.cpp @@ -25,8 +25,6 @@ #include "stats_util.h" #include "stats_log_util.h" -#include <android-base/file.h> -#include <dirent.h> #include <stdio.h> #include <vector> #include "android-base/stringprintf.h" @@ -35,9 +33,7 @@ namespace android { namespace os { namespace statsd { -using std::map; using std::pair; -using std::set; using std::string; using std::vector; @@ -61,7 +57,7 @@ void ConfigManager::Startup() { } void ConfigManager::StartupForTest() { - // Dummy function to avoid reading configs from disks for tests. + // No-op function to avoid reading configs from disks for tests. } void ConfigManager::AddListener(const sp<ConfigListener>& listener) { diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h index c064a519f597..1fdec316e499 100644 --- a/cmds/statsd/src/config/ConfigManager.h +++ b/cmds/statsd/src/config/ConfigManager.h @@ -22,7 +22,6 @@ #include <map> #include <mutex> -#include <set> #include <string> #include <stdio.h> @@ -45,7 +44,7 @@ public: void Startup(); /* - * Dummy initializer for tests. + * No-op initializer for tests. */ void StartupForTest(); diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp index 0c4c3301e61e..85b660efc956 100644 --- a/cmds/statsd/src/external/Perfetto.cpp +++ b/cmds/statsd/src/external/Perfetto.cpp @@ -21,12 +21,8 @@ #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert #include <android-base/unique_fd.h> -#include <errno.h> -#include <fcntl.h> #include <inttypes.h> -#include <sys/types.h> #include <sys/wait.h> -#include <unistd.h> #include <string> diff --git a/cmds/statsd/src/external/PullDataReceiver.h b/cmds/statsd/src/external/PullDataReceiver.h index d2193f41b80a..dd5c0cfa04c1 100644 --- a/cmds/statsd/src/external/PullDataReceiver.h +++ b/cmds/statsd/src/external/PullDataReceiver.h @@ -15,8 +15,6 @@ */ #pragma once -#include <utils/String16.h> -#include <unordered_map> #include <utils/RefBase.h> #include "StatsPuller.h" #include "logd/LogEvent.h" diff --git a/cmds/statsd/src/external/StatsCallbackPuller.h b/cmds/statsd/src/external/StatsCallbackPuller.h index c4bfa89ba9a7..03e78be4d474 100644 --- a/cmds/statsd/src/external/StatsCallbackPuller.h +++ b/cmds/statsd/src/external/StatsCallbackPuller.h @@ -17,7 +17,7 @@ #pragma once #include <android/os/IStatsPullerCallback.h> -#include <utils/String16.h> + #include "StatsPuller.h" namespace android { diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 1c9d7763bc83..0b0e4f6ee230 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -38,14 +38,8 @@ #include "TrainInfoPuller.h" #include "statslog.h" -#include <iostream> - -using std::make_shared; -using std::map; using std::shared_ptr; -using std::string; using std::vector; -using std::list; namespace android { namespace os { diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 4ea1386bf78a..6791f6656f09 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -22,8 +22,6 @@ #include <utils/RefBase.h> #include <utils/threads.h> #include <list> -#include <string> -#include <unordered_map> #include <vector> #include "PullDataReceiver.h" #include "StatsPuller.h" diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index a836bd14c012..3054b6d2204b 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -36,7 +36,6 @@ using android::util::FIELD_TYPE_MESSAGE; using android::util::FIELD_TYPE_STRING; using android::util::ProtoOutputStream; using std::lock_guard; -using std::map; using std::shared_ptr; using std::string; using std::vector; diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index b46802af3dd8..e1b5a0b8f0f5 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -20,10 +20,8 @@ #include <android/os/StatsLogEventWrapper.h> #include <android/util/ProtoOutputStream.h> -#include <log/log_event_list.h> #include <log/log_read.h> #include <private/android_logger.h> -#include <utils/Errors.h> #include <string> #include <vector> @@ -239,4 +237,3 @@ void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::v } // namespace statsd } // namespace os } // namespace android - diff --git a/cmds/statsd/src/logd/LogEventQueue.h b/cmds/statsd/src/logd/LogEventQueue.h index b4fd63f119e6..9dda3d24c571 100644 --- a/cmds/statsd/src/logd/LogEventQueue.h +++ b/cmds/statsd/src/logd/LogEventQueue.h @@ -19,10 +19,8 @@ #include "LogEvent.h" #include <condition_variable> -#include <memory> #include <mutex> #include <queue> -#include <thread> namespace android { namespace os { diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp index 0e669287111d..739c5977a2d0 100644 --- a/cmds/statsd/src/main.cpp +++ b/cmds/statsd/src/main.cpp @@ -20,16 +20,11 @@ #include "StatsService.h" #include "socket/StatsSocketListener.h" -#include <binder/IInterface.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> -#include <binder/Status.h> #include <hidl/HidlTransportSupport.h> #include <utils/Looper.h> -#include <utils/StrongPointer.h> - -#include <memory> #include <stdio.h> #include <sys/stat.h> diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp index 15c067ee936d..b94a9572113e 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp @@ -24,8 +24,6 @@ namespace os { namespace statsd { using std::set; -using std::string; -using std::unique_ptr; using std::unordered_map; using std::vector; diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h index 2a3f08da7b96..55bc46059fc1 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h @@ -16,9 +16,6 @@ #ifndef COMBINATION_LOG_MATCHING_TRACKER_H #define COMBINATION_LOG_MATCHING_TRACKER_H -#include <log/log_read.h> -#include <log/logprint.h> -#include <set> #include <unordered_map> #include <vector> #include "LogMatchingTracker.h" diff --git a/cmds/statsd/src/matchers/EventMatcherWizard.cpp b/cmds/statsd/src/matchers/EventMatcherWizard.cpp index 8418e9833509..025c9a87b16b 100644 --- a/cmds/statsd/src/matchers/EventMatcherWizard.cpp +++ b/cmds/statsd/src/matchers/EventMatcherWizard.cpp @@ -14,14 +14,11 @@ * limitations under the License. */ #include "EventMatcherWizard.h" -#include <unordered_set> namespace android { namespace os { namespace statsd { -using std::map; -using std::string; using std::vector; MatchingState EventMatcherWizard::matchLogEvent(const LogEvent& event, int matcher_index) { diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp index 31b3db524e80..082daf5a1916 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp @@ -23,8 +23,6 @@ namespace android { namespace os { namespace statsd { -using std::string; -using std::unique_ptr; using std::unordered_map; using std::vector; diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h index 28b339caa466..a0f6a888bd44 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h @@ -17,9 +17,6 @@ #ifndef SIMPLE_LOG_MATCHING_TRACKER_H #define SIMPLE_LOG_MATCHING_TRACKER_H -#include <log/log_read.h> -#include <log/logprint.h> -#include <set> #include <unordered_map> #include <vector> #include "LogMatchingTracker.h" diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index 8dc5cef988b0..2cbe2e96f142 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -23,7 +23,6 @@ using std::set; using std::string; -using std::unordered_map; using std::vector; namespace android { diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index 15b4a9799a93..1ab3e87b5fed 100644 --- a/cmds/statsd/src/matchers/matcher_util.h +++ b/cmds/statsd/src/matchers/matcher_util.h @@ -18,11 +18,6 @@ #include "logd/LogEvent.h" -#include <log/log_read.h> -#include <log/logprint.h> -#include <set> -#include <string> -#include <unordered_map> #include <vector> #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "packages/UidMap.h" diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index a64bbc1056e0..4f437d1af51a 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -21,8 +21,6 @@ #include "GaugeMetricProducer.h" #include "../stats_log_util.h" -#include <cutils/log.h> - using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_BOOL; using android::util::FIELD_TYPE_FLOAT; diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 92752b29ecda..36434eb7ceb4 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -29,7 +29,6 @@ namespace android { namespace os { namespace statsd { -using std::map; // for ActiveMetric const int FIELD_ID_ACTIVE_METRIC_ID = 1; diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index a0c82246d3e0..c77bc0135d86 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -17,9 +17,11 @@ #ifndef METRIC_PRODUCER_H #define METRIC_PRODUCER_H -#include <shared_mutex> - #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h> +#include <utils/RefBase.h> + +#include <unordered_map> + #include "HashableDimensionKey.h" #include "anomaly/AnomalyTracker.h" #include "condition/ConditionWizard.h" @@ -27,10 +29,6 @@ #include "matchers/matcher_util.h" #include "packages/PackageInfoListener.h" -#include <log/logprint.h> -#include <utils/RefBase.h> -#include <unordered_map> - namespace android { namespace os { namespace statsd { diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 760e800455f0..1fb2b1ce5e14 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -15,8 +15,10 @@ */ #define DEBUG false // STOPSHIP if true #include "Log.h" + #include "MetricsManager.h" -#include "statslog.h" + +#include <private/android_filesystem_config.h> #include "CountMetricProducer.h" #include "atoms_info.h" @@ -28,10 +30,9 @@ #include "metrics_manager_util.h" #include "stats_util.h" #include "stats_log_util.h" +#include "statslog.h" -#include <log/logprint.h> #include <private/android_filesystem_config.h> -#include <utils/SystemClock.h> using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_INT32; @@ -40,10 +41,8 @@ using android::util::FIELD_TYPE_MESSAGE; using android::util::FIELD_TYPE_STRING; using android::util::ProtoOutputStream; -using std::make_unique; using std::set; using std::string; -using std::unordered_map; using std::vector; namespace android { diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 0e33a0f9f29b..fa310dc707ec 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -21,7 +21,6 @@ #include "../guardrail/StatsdStats.h" #include "../stats_log_util.h" -#include <cutils/log.h> #include <limits.h> #include <stdlib.h> @@ -33,12 +32,8 @@ using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; using android::util::FIELD_TYPE_STRING; using android::util::ProtoOutputStream; -using std::list; -using std::make_pair; -using std::make_shared; using std::map; using std::shared_ptr; -using std::unique_ptr; using std::unordered_map; namespace android { diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 739f6ef07cc4..784ac64880a3 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -17,8 +17,6 @@ #pragma once #include <gtest/gtest_prod.h> -#include <utils/threads.h> -#include <list> #include "anomaly/AnomalyTracker.h" #include "condition/ConditionTimer.h" #include "condition/ConditionTracker.h" diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h index 8e73256d4a01..e46616969116 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h @@ -19,7 +19,6 @@ #include "DurationTracker.h" -#include <set> namespace android { namespace os { namespace statsd { diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index f5f2479f4faa..45c3c69b04b2 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -38,7 +38,6 @@ #include <inttypes.h> using std::set; -using std::string; using std::unordered_map; using std::vector; diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h index 028231ff908c..ece986b7fcc9 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/metrics_manager_util.h @@ -16,7 +16,6 @@ #pragma once -#include <memory> #include <set> #include <unordered_map> #include <vector> diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h index fcdbe69dbbd1..6c50a8c41770 100644 --- a/cmds/statsd/src/packages/PackageInfoListener.h +++ b/cmds/statsd/src/packages/PackageInfoListener.h @@ -17,7 +17,6 @@ #ifndef STATSD_PACKAGE_INFO_LISTENER_H #define STATSD_PACKAGE_INFO_LISTENER_H -#include <utils/RefBase.h> #include <string> namespace android { diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index 7e63bbff2d0a..ab0e86e24b02 100644 --- a/cmds/statsd/src/packages/UidMap.cpp +++ b/cmds/statsd/src/packages/UidMap.cpp @@ -21,10 +21,6 @@ #include "guardrail/StatsdStats.h" #include "packages/UidMap.h" -#include <android/os/IStatsCompanionService.h> -#include <binder/IServiceManager.h> -#include <utils/Errors.h> - #include <inttypes.h> using namespace android; diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h index 2d3f6ee9c2e8..bfac6e3431b0 100644 --- a/cmds/statsd/src/packages/UidMap.h +++ b/cmds/statsd/src/packages/UidMap.h @@ -21,10 +21,8 @@ #include "packages/PackageInfoListener.h" #include "stats_util.h" -#include <binder/IResultReceiver.h> #include <binder/IShellCallback.h> #include <gtest/gtest_prod.h> -#include <log/logprint.h> #include <stdio.h> #include <utils/RefBase.h> #include <list> diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp index f7e32d4aed26..d6a04336bc46 100644 --- a/cmds/statsd/src/shell/ShellSubscriber.cpp +++ b/cmds/statsd/src/shell/ShellSubscriber.cpp @@ -18,7 +18,6 @@ #include "ShellSubscriber.h" -#include <android-base/file.h> #include "matchers/matcher_util.h" #include "stats_log_util.h" diff --git a/cmds/statsd/src/shell/ShellSubscriber.h b/cmds/statsd/src/shell/ShellSubscriber.h index 8e54a8b00091..86d85901083a 100644 --- a/cmds/statsd/src/shell/ShellSubscriber.h +++ b/cmds/statsd/src/shell/ShellSubscriber.h @@ -22,7 +22,6 @@ #include <binder/IResultReceiver.h> #include <condition_variable> #include <mutex> -#include <string> #include <thread> #include "external/StatsPullerManager.h" #include "frameworks/base/cmds/statsd/src/shell/shell_config.pb.h" diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp index b59d88dc1cea..bedfa7dec7a4 100755 --- a/cmds/statsd/src/socket/StatsSocketListener.cpp +++ b/cmds/statsd/src/socket/StatsSocketListener.cpp @@ -27,9 +27,6 @@ #include <unistd.h> #include <cutils/sockets.h> -#include <private/android_filesystem_config.h> -#include <private/android_logger.h> -#include <unordered_map> #include "StatsSocketListener.h" #include "guardrail/StatsdStats.h" diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp index 67625eb82454..a7b681014292 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -17,12 +17,8 @@ #include "hash.h" #include "stats_log_util.h" -#include <logd/LogEvent.h> #include <private/android_filesystem_config.h> -#include <utils/Log.h> #include <set> -#include <stack> -#include <utils/Log.h> #include <utils/SystemClock.h> using android::util::AtomsInfo; diff --git a/cmds/statsd/src/statscompanion_util.h b/cmds/statsd/src/statscompanion_util.h index ff702f23f6d1..dc4f28361214 100644 --- a/cmds/statsd/src/statscompanion_util.h +++ b/cmds/statsd/src/statscompanion_util.h @@ -18,12 +18,6 @@ #include "StatsLogProcessor.h" -using namespace android; -using namespace android::base; -using namespace android::binder; -using namespace android::os; -using namespace std; - namespace android { namespace os { namespace statsd { diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 9b48a02c7f78..507297c6c401 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -23,10 +23,8 @@ #include "stats_log_util.h" #include <android-base/file.h> -#include <dirent.h> #include <private/android_filesystem_config.h> #include <fstream> -#include <iostream> namespace android { namespace os { diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp index f2c6f1ad6759..ba5e66761528 100644 --- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp +++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp @@ -24,7 +24,6 @@ #include <android/os/IIncidentManager.h> #include <android/os/IncidentReportArgs.h> #include <android/util/ProtoOutputStream.h> -#include <binder/IBinder.h> #include <binder/IServiceManager.h> #include <vector> diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp index 25d2257c752b..d4f44780b0bc 100644 --- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp +++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp @@ -21,7 +21,6 @@ using android::IBinder; using std::lock_guard; -using std::unordered_map; namespace android { namespace os { diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp index 2b9528f7d1de..2cbcf28ef7d6 100644 --- a/cmds/statsd/tests/LogEntryMatcher_test.cpp +++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp @@ -18,9 +18,6 @@ #include "stats_util.h" #include <gtest/gtest.h> -#include <log/log_event_list.h> -#include <log/log_read.h> -#include <log/logprint.h> #include <stdio.h> diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java index 35f4add46d77..24d65fb125ec 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -65,6 +65,7 @@ public final class Telecom extends BaseCommand { private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer"; private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer"; private static final String COMMAND_STOP_BLOCK_SUPPRESSION = "stop-block-suppression"; + private static final String COMMAND_CLEANUP_STUCK_CALLS = "cleanup-stuck-calls"; /** * Change the system dialer package name if a package name was specified, @@ -115,6 +116,8 @@ public final class Telecom extends BaseCommand { + "usage: telecom get-max-phones\n" + "usage: telecom stop-block-suppression: Stop suppressing the blocked number" + " provider after a call to emergency services.\n" + + "usage: telecom cleanup-stuck-calls: Clear any disconnected calls that have" + + " gotten wedged in Telecom.\n" + "usage: telecom set-emer-phone-account-filter <PACKAGE>\n" + "\n" + "telecom set-phone-account-enabled: Enables the given phone account, if it has" @@ -210,6 +213,9 @@ public final class Telecom extends BaseCommand { case COMMAND_STOP_BLOCK_SUPPRESSION: runStopBlockSuppression(); break; + case COMMAND_CLEANUP_STUCK_CALLS: + runCleanupStuckCalls(); + break; case COMMAND_SET_DEFAULT_DIALER: runSetDefaultDialer(); break; @@ -331,6 +337,10 @@ public final class Telecom extends BaseCommand { mTelecomService.stopBlockSuppression(); } + private void runCleanupStuckCalls() throws RemoteException { + mTelecomService.cleanupStuckCalls(); + } + private void runSetDefaultDialer() throws RemoteException { String packageName = nextArg(); if ("default".equals(packageName)) packageName = null; diff --git a/cmds/uiautomator/api/current.txt b/cmds/uiautomator/api/current.txt index 489c2eadfd91..bf87d091934e 100644 --- a/cmds/uiautomator/api/current.txt +++ b/cmds/uiautomator/api/current.txt @@ -1,221 +1,222 @@ +// Signature format: 2.0 package com.android.uiautomator.core { - public final deprecated class Configurator { - method public long getActionAcknowledgmentTimeout(); - method public static com.android.uiautomator.core.Configurator getInstance(); - method public long getKeyInjectionDelay(); - method public long getScrollAcknowledgmentTimeout(); - method public long getWaitForIdleTimeout(); - method public long getWaitForSelectorTimeout(); - method public com.android.uiautomator.core.Configurator setActionAcknowledgmentTimeout(long); - method public com.android.uiautomator.core.Configurator setKeyInjectionDelay(long); - method public com.android.uiautomator.core.Configurator setScrollAcknowledgmentTimeout(long); - method public com.android.uiautomator.core.Configurator setWaitForIdleTimeout(long); - method public com.android.uiautomator.core.Configurator setWaitForSelectorTimeout(long); + @Deprecated public final class Configurator { + method @Deprecated public long getActionAcknowledgmentTimeout(); + method @Deprecated public static com.android.uiautomator.core.Configurator getInstance(); + method @Deprecated public long getKeyInjectionDelay(); + method @Deprecated public long getScrollAcknowledgmentTimeout(); + method @Deprecated public long getWaitForIdleTimeout(); + method @Deprecated public long getWaitForSelectorTimeout(); + method @Deprecated public com.android.uiautomator.core.Configurator setActionAcknowledgmentTimeout(long); + method @Deprecated public com.android.uiautomator.core.Configurator setKeyInjectionDelay(long); + method @Deprecated public com.android.uiautomator.core.Configurator setScrollAcknowledgmentTimeout(long); + method @Deprecated public com.android.uiautomator.core.Configurator setWaitForIdleTimeout(long); + method @Deprecated public com.android.uiautomator.core.Configurator setWaitForSelectorTimeout(long); } - public deprecated class UiCollection extends com.android.uiautomator.core.UiObject { - ctor public UiCollection(com.android.uiautomator.core.UiSelector); - method public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getChildByInstance(com.android.uiautomator.core.UiSelector, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public int getChildCount(com.android.uiautomator.core.UiSelector); + @Deprecated public class UiCollection extends com.android.uiautomator.core.UiObject { + ctor @Deprecated public UiCollection(com.android.uiautomator.core.UiSelector); + method @Deprecated public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, String) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getChildByInstance(com.android.uiautomator.core.UiSelector, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, String) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public int getChildCount(com.android.uiautomator.core.UiSelector); } - public deprecated class UiDevice { - method public void clearLastTraversedText(); - method public boolean click(int, int); - method public boolean drag(int, int, int, int, int); - method public void dumpWindowHierarchy(java.lang.String); - method public void freezeRotation() throws android.os.RemoteException; - method public deprecated java.lang.String getCurrentActivityName(); - method public java.lang.String getCurrentPackageName(); - method public int getDisplayHeight(); - method public int getDisplayRotation(); - method public android.graphics.Point getDisplaySizeDp(); - method public int getDisplayWidth(); - method public static com.android.uiautomator.core.UiDevice getInstance(); - method public java.lang.String getLastTraversedText(); - method public java.lang.String getProductName(); - method public boolean hasAnyWatcherTriggered(); - method public boolean hasWatcherTriggered(java.lang.String); - method public boolean isNaturalOrientation(); - method public boolean isScreenOn() throws android.os.RemoteException; - method public boolean openNotification(); - method public boolean openQuickSettings(); - method public boolean pressBack(); - method public boolean pressDPadCenter(); - method public boolean pressDPadDown(); - method public boolean pressDPadLeft(); - method public boolean pressDPadRight(); - method public boolean pressDPadUp(); - method public boolean pressDelete(); - method public boolean pressEnter(); - method public boolean pressHome(); - method public boolean pressKeyCode(int); - method public boolean pressKeyCode(int, int); - method public boolean pressMenu(); - method public boolean pressRecentApps() throws android.os.RemoteException; - method public boolean pressSearch(); - method public void registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher); - method public void removeWatcher(java.lang.String); - method public void resetWatcherTriggers(); - method public void runWatchers(); - method public void setCompressedLayoutHeirarchy(boolean); - method public void setOrientationLeft() throws android.os.RemoteException; - method public void setOrientationNatural() throws android.os.RemoteException; - method public void setOrientationRight() throws android.os.RemoteException; - method public void sleep() throws android.os.RemoteException; - method public boolean swipe(int, int, int, int, int); - method public boolean swipe(android.graphics.Point[], int); - method public boolean takeScreenshot(java.io.File); - method public boolean takeScreenshot(java.io.File, float, int); - method public void unfreezeRotation() throws android.os.RemoteException; - method public void waitForIdle(); - method public void waitForIdle(long); - method public boolean waitForWindowUpdate(java.lang.String, long); - method public void wakeUp() throws android.os.RemoteException; + @Deprecated public class UiDevice { + method @Deprecated public void clearLastTraversedText(); + method @Deprecated public boolean click(int, int); + method @Deprecated public boolean drag(int, int, int, int, int); + method @Deprecated public void dumpWindowHierarchy(String); + method @Deprecated public void freezeRotation() throws android.os.RemoteException; + method @Deprecated public String getCurrentActivityName(); + method @Deprecated public String getCurrentPackageName(); + method @Deprecated public int getDisplayHeight(); + method @Deprecated public int getDisplayRotation(); + method @Deprecated public android.graphics.Point getDisplaySizeDp(); + method @Deprecated public int getDisplayWidth(); + method @Deprecated public static com.android.uiautomator.core.UiDevice getInstance(); + method @Deprecated public String getLastTraversedText(); + method @Deprecated public String getProductName(); + method @Deprecated public boolean hasAnyWatcherTriggered(); + method @Deprecated public boolean hasWatcherTriggered(String); + method @Deprecated public boolean isNaturalOrientation(); + method @Deprecated public boolean isScreenOn() throws android.os.RemoteException; + method @Deprecated public boolean openNotification(); + method @Deprecated public boolean openQuickSettings(); + method @Deprecated public boolean pressBack(); + method @Deprecated public boolean pressDPadCenter(); + method @Deprecated public boolean pressDPadDown(); + method @Deprecated public boolean pressDPadLeft(); + method @Deprecated public boolean pressDPadRight(); + method @Deprecated public boolean pressDPadUp(); + method @Deprecated public boolean pressDelete(); + method @Deprecated public boolean pressEnter(); + method @Deprecated public boolean pressHome(); + method @Deprecated public boolean pressKeyCode(int); + method @Deprecated public boolean pressKeyCode(int, int); + method @Deprecated public boolean pressMenu(); + method @Deprecated public boolean pressRecentApps() throws android.os.RemoteException; + method @Deprecated public boolean pressSearch(); + method @Deprecated public void registerWatcher(String, com.android.uiautomator.core.UiWatcher); + method @Deprecated public void removeWatcher(String); + method @Deprecated public void resetWatcherTriggers(); + method @Deprecated public void runWatchers(); + method @Deprecated public void setCompressedLayoutHeirarchy(boolean); + method @Deprecated public void setOrientationLeft() throws android.os.RemoteException; + method @Deprecated public void setOrientationNatural() throws android.os.RemoteException; + method @Deprecated public void setOrientationRight() throws android.os.RemoteException; + method @Deprecated public void sleep() throws android.os.RemoteException; + method @Deprecated public boolean swipe(int, int, int, int, int); + method @Deprecated public boolean swipe(android.graphics.Point[], int); + method @Deprecated public boolean takeScreenshot(java.io.File); + method @Deprecated public boolean takeScreenshot(java.io.File, float, int); + method @Deprecated public void unfreezeRotation() throws android.os.RemoteException; + method @Deprecated public void waitForIdle(); + method @Deprecated public void waitForIdle(long); + method @Deprecated public boolean waitForWindowUpdate(String, long); + method @Deprecated public void wakeUp() throws android.os.RemoteException; } - public deprecated class UiObject { - ctor public UiObject(com.android.uiautomator.core.UiSelector); - method public void clearTextField() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean click() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean clickAndWaitForNewWindow() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean clickAndWaitForNewWindow(long) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean clickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean clickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean dragTo(com.android.uiautomator.core.UiObject, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean dragTo(int, int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean exists(); - method protected android.view.accessibility.AccessibilityNodeInfo findAccessibilityNodeInfo(long); - method public android.graphics.Rect getBounds() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getChild(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public int getChildCount() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public java.lang.String getClassName() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public java.lang.String getContentDescription() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getFromParent(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public java.lang.String getPackageName() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public final com.android.uiautomator.core.UiSelector getSelector(); - method public java.lang.String getText() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public android.graphics.Rect getVisibleBounds() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isCheckable() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isChecked() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isClickable() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isEnabled() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isFocusable() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isFocused() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isLongClickable() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isScrollable() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean isSelected() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean longClick() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean longClickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean longClickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean performMultiPointerGesture(android.view.MotionEvent.PointerCoords...); - method public boolean performTwoPointerGesture(android.graphics.Point, android.graphics.Point, android.graphics.Point, android.graphics.Point, int); - method public boolean pinchIn(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean pinchOut(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean setText(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean swipeDown(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean swipeLeft(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean swipeRight(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean swipeUp(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean waitForExists(long); - method public boolean waitUntilGone(long); - field protected static final int FINGER_TOUCH_HALF_WIDTH = 20; // 0x14 - field protected static final int SWIPE_MARGIN_LIMIT = 5; // 0x5 - field protected static final deprecated long WAIT_FOR_EVENT_TMEOUT = 3000L; // 0xbb8L - field protected static final long WAIT_FOR_SELECTOR_POLL = 1000L; // 0x3e8L - field protected static final deprecated long WAIT_FOR_SELECTOR_TIMEOUT = 10000L; // 0x2710L - field protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500L; // 0x157cL + @Deprecated public class UiObject { + ctor @Deprecated public UiObject(com.android.uiautomator.core.UiSelector); + method @Deprecated public void clearTextField() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean click() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean clickAndWaitForNewWindow() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean clickAndWaitForNewWindow(long) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean clickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean clickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean dragTo(com.android.uiautomator.core.UiObject, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean dragTo(int, int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean exists(); + method @Deprecated protected android.view.accessibility.AccessibilityNodeInfo findAccessibilityNodeInfo(long); + method @Deprecated public android.graphics.Rect getBounds() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getChild(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public int getChildCount() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public String getClassName() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public String getContentDescription() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getFromParent(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public String getPackageName() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public final com.android.uiautomator.core.UiSelector getSelector(); + method @Deprecated public String getText() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public android.graphics.Rect getVisibleBounds() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isCheckable() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isChecked() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isClickable() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isEnabled() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isFocusable() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isFocused() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isLongClickable() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isScrollable() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean isSelected() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean longClick() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean longClickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean longClickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean performMultiPointerGesture(android.view.MotionEvent.PointerCoords[]...); + method @Deprecated public boolean performTwoPointerGesture(android.graphics.Point, android.graphics.Point, android.graphics.Point, android.graphics.Point, int); + method @Deprecated public boolean pinchIn(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean pinchOut(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean setText(String) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean swipeDown(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean swipeLeft(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean swipeRight(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean swipeUp(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean waitForExists(long); + method @Deprecated public boolean waitUntilGone(long); + field @Deprecated protected static final int FINGER_TOUCH_HALF_WIDTH = 20; // 0x14 + field @Deprecated protected static final int SWIPE_MARGIN_LIMIT = 5; // 0x5 + field @Deprecated protected static final long WAIT_FOR_EVENT_TMEOUT = 3000L; // 0xbb8L + field @Deprecated protected static final long WAIT_FOR_SELECTOR_POLL = 1000L; // 0x3e8L + field @Deprecated protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10000L; // 0x2710L + field @Deprecated protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500L; // 0x157cL } - public deprecated class UiObjectNotFoundException extends java.lang.Exception { - ctor public UiObjectNotFoundException(java.lang.String); - ctor public UiObjectNotFoundException(java.lang.String, java.lang.Throwable); - ctor public UiObjectNotFoundException(java.lang.Throwable); + @Deprecated public class UiObjectNotFoundException extends java.lang.Exception { + ctor @Deprecated public UiObjectNotFoundException(String); + ctor @Deprecated public UiObjectNotFoundException(String, Throwable); + ctor @Deprecated public UiObjectNotFoundException(Throwable); } - public deprecated class UiScrollable extends com.android.uiautomator.core.UiCollection { - ctor public UiScrollable(com.android.uiautomator.core.UiSelector); - method protected boolean exists(com.android.uiautomator.core.UiSelector); - method public boolean flingBackward() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean flingForward() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean flingToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean flingToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public int getMaxSearchSwipes(); - method public double getSwipeDeadZonePercentage(); - method public boolean scrollBackward() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollBackward(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollDescriptionIntoView(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollForward() throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollForward(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollIntoView(com.android.uiautomator.core.UiObject) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollIntoView(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollTextIntoView(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollToBeginning(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollToEnd(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public boolean scrollToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException; - method public com.android.uiautomator.core.UiScrollable setAsHorizontalList(); - method public com.android.uiautomator.core.UiScrollable setAsVerticalList(); - method public com.android.uiautomator.core.UiScrollable setMaxSearchSwipes(int); - method public com.android.uiautomator.core.UiScrollable setSwipeDeadZonePercentage(double); + @Deprecated public class UiScrollable extends com.android.uiautomator.core.UiCollection { + ctor @Deprecated public UiScrollable(com.android.uiautomator.core.UiSelector); + method @Deprecated protected boolean exists(com.android.uiautomator.core.UiSelector); + method @Deprecated public boolean flingBackward() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean flingForward() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean flingToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean flingToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public int getMaxSearchSwipes(); + method @Deprecated public double getSwipeDeadZonePercentage(); + method @Deprecated public boolean scrollBackward() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollBackward(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollDescriptionIntoView(String) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollForward() throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollForward(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollIntoView(com.android.uiautomator.core.UiObject) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollIntoView(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollTextIntoView(String) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollToBeginning(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollToEnd(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public boolean scrollToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException; + method @Deprecated public com.android.uiautomator.core.UiScrollable setAsHorizontalList(); + method @Deprecated public com.android.uiautomator.core.UiScrollable setAsVerticalList(); + method @Deprecated public com.android.uiautomator.core.UiScrollable setMaxSearchSwipes(int); + method @Deprecated public com.android.uiautomator.core.UiScrollable setSwipeDeadZonePercentage(double); } - public deprecated class UiSelector { - ctor public UiSelector(); - method public com.android.uiautomator.core.UiSelector checkable(boolean); - method public com.android.uiautomator.core.UiSelector checked(boolean); - method public com.android.uiautomator.core.UiSelector childSelector(com.android.uiautomator.core.UiSelector); - method public com.android.uiautomator.core.UiSelector className(java.lang.String); - method public <T> com.android.uiautomator.core.UiSelector className(java.lang.Class<T>); - method public com.android.uiautomator.core.UiSelector classNameMatches(java.lang.String); - method public com.android.uiautomator.core.UiSelector clickable(boolean); - method protected com.android.uiautomator.core.UiSelector cloneSelector(); - method public com.android.uiautomator.core.UiSelector description(java.lang.String); - method public com.android.uiautomator.core.UiSelector descriptionContains(java.lang.String); - method public com.android.uiautomator.core.UiSelector descriptionMatches(java.lang.String); - method public com.android.uiautomator.core.UiSelector descriptionStartsWith(java.lang.String); - method public com.android.uiautomator.core.UiSelector enabled(boolean); - method public com.android.uiautomator.core.UiSelector focusable(boolean); - method public com.android.uiautomator.core.UiSelector focused(boolean); - method public com.android.uiautomator.core.UiSelector fromParent(com.android.uiautomator.core.UiSelector); - method public com.android.uiautomator.core.UiSelector index(int); - method public com.android.uiautomator.core.UiSelector instance(int); - method public com.android.uiautomator.core.UiSelector longClickable(boolean); - method public com.android.uiautomator.core.UiSelector packageName(java.lang.String); - method public com.android.uiautomator.core.UiSelector packageNameMatches(java.lang.String); - method public com.android.uiautomator.core.UiSelector resourceId(java.lang.String); - method public com.android.uiautomator.core.UiSelector resourceIdMatches(java.lang.String); - method public com.android.uiautomator.core.UiSelector scrollable(boolean); - method public com.android.uiautomator.core.UiSelector selected(boolean); - method public com.android.uiautomator.core.UiSelector text(java.lang.String); - method public com.android.uiautomator.core.UiSelector textContains(java.lang.String); - method public com.android.uiautomator.core.UiSelector textMatches(java.lang.String); - method public com.android.uiautomator.core.UiSelector textStartsWith(java.lang.String); + @Deprecated public class UiSelector { + ctor @Deprecated public UiSelector(); + method @Deprecated public com.android.uiautomator.core.UiSelector checkable(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector checked(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector childSelector(com.android.uiautomator.core.UiSelector); + method @Deprecated public com.android.uiautomator.core.UiSelector className(String); + method @Deprecated public <T> com.android.uiautomator.core.UiSelector className(Class<T>); + method @Deprecated public com.android.uiautomator.core.UiSelector classNameMatches(String); + method @Deprecated public com.android.uiautomator.core.UiSelector clickable(boolean); + method @Deprecated protected com.android.uiautomator.core.UiSelector cloneSelector(); + method @Deprecated public com.android.uiautomator.core.UiSelector description(String); + method @Deprecated public com.android.uiautomator.core.UiSelector descriptionContains(String); + method @Deprecated public com.android.uiautomator.core.UiSelector descriptionMatches(String); + method @Deprecated public com.android.uiautomator.core.UiSelector descriptionStartsWith(String); + method @Deprecated public com.android.uiautomator.core.UiSelector enabled(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector focusable(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector focused(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector fromParent(com.android.uiautomator.core.UiSelector); + method @Deprecated public com.android.uiautomator.core.UiSelector index(int); + method @Deprecated public com.android.uiautomator.core.UiSelector instance(int); + method @Deprecated public com.android.uiautomator.core.UiSelector longClickable(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector packageName(String); + method @Deprecated public com.android.uiautomator.core.UiSelector packageNameMatches(String); + method @Deprecated public com.android.uiautomator.core.UiSelector resourceId(String); + method @Deprecated public com.android.uiautomator.core.UiSelector resourceIdMatches(String); + method @Deprecated public com.android.uiautomator.core.UiSelector scrollable(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector selected(boolean); + method @Deprecated public com.android.uiautomator.core.UiSelector text(String); + method @Deprecated public com.android.uiautomator.core.UiSelector textContains(String); + method @Deprecated public com.android.uiautomator.core.UiSelector textMatches(String); + method @Deprecated public com.android.uiautomator.core.UiSelector textStartsWith(String); } - public abstract deprecated interface UiWatcher { - method public abstract boolean checkForCondition(); + @Deprecated public interface UiWatcher { + method @Deprecated public boolean checkForCondition(); } } package com.android.uiautomator.testrunner { - public abstract deprecated interface IAutomationSupport { - method public abstract void sendStatus(int, android.os.Bundle); + @Deprecated public interface IAutomationSupport { + method @Deprecated public void sendStatus(int, android.os.Bundle); } - public deprecated class UiAutomatorTestCase extends junit.framework.TestCase { - ctor public UiAutomatorTestCase(); - method public com.android.uiautomator.testrunner.IAutomationSupport getAutomationSupport(); - method public android.os.Bundle getParams(); - method public com.android.uiautomator.core.UiDevice getUiDevice(); - method public void sleep(long); + @Deprecated public class UiAutomatorTestCase extends junit.framework.TestCase { + ctor @Deprecated public UiAutomatorTestCase(); + method @Deprecated public com.android.uiautomator.testrunner.IAutomationSupport getAutomationSupport(); + method @Deprecated public android.os.Bundle getParams(); + method @Deprecated public com.android.uiautomator.core.UiDevice getUiDevice(); + method @Deprecated public void sleep(long); } } diff --git a/cmds/uiautomator/api/removed.txt b/cmds/uiautomator/api/removed.txt index e69de29bb2d1..d802177e249b 100644 --- a/cmds/uiautomator/api/removed.txt +++ b/cmds/uiautomator/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp index c33d31f576a3..14b74da0c616 100644 --- a/cmds/uiautomator/library/Android.bp +++ b/cmds/uiautomator/library/Android.bp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -droiddoc { - name: "uiautomator-stubs-docs", +droidstubs { + name: "uiautomator-stubs", srcs: [ "core-src/**/*.java", "testrunner-src/**/*.java", @@ -24,10 +24,10 @@ droiddoc { "android.test.base", "unsupportedappusage", ], - custom_template: "droiddoc-templates-sdk", installable: false, - args: "-stubpackages com.android.uiautomator.core:" + - "com.android.uiautomator.testrunner", + flags: [ + "-stubpackages com.android.uiautomator.core:com.android.uiautomator.testrunner", + ], check_api: { current: { @@ -41,15 +41,31 @@ droiddoc { }, } +droiddoc { + name: "uiautomator-stubs-docs", + srcs: [ + ":uiautomator-stubs", + ], + libs: [ + "android.test.runner", + "junit", + "android.test.base", + "unsupportedappusage", + ], + installable: false, + custom_template: "droiddoc-templates-sdk", +} + java_library_static { name: "android_uiautomator", srcs: [ - ":uiautomator-stubs-docs", + ":uiautomator-stubs", ], libs: [ "android.test.runner", "junit", ], + java_version: "1.8", } java_library_static { @@ -64,7 +80,7 @@ java_library_static { ], static_libs: [ "junit", - ] + ], } java_library_static { diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java index 71561c3c7023..39248730802f 100644 --- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java +++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java @@ -49,7 +49,7 @@ public class UiAutomationShellWrapper { } try { if (isSet) { - am.setActivityController(new DummyActivityController(), true); + am.setActivityController(new NoOpActivityController(), true); } else { am.setActivityController(null, true); } @@ -80,9 +80,9 @@ public class UiAutomationShellWrapper { } /** - * Dummy, no interference, activity controller. + * No-op, no interference, activity controller. */ - private class DummyActivityController extends IActivityController.Stub { + private class NoOpActivityController extends IActivityController.Stub { @Override public boolean activityStarting(Intent intent, String pkg) throws RemoteException { /* do nothing and let activity proceed normally */ diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java index d862e1c2babb..e6fb7aa76e58 100644 --- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java +++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java @@ -45,7 +45,7 @@ import java.util.List; public class UiAutomatorTestCase extends TestCase { private static final String DISABLE_IME = "disable_ime"; - private static final String DUMMY_IME_PACKAGE = "com.android.testing.dummyime"; + private static final String STUB_IME_PACKAGE = "com.android.testing.stubime"; private static final int NOT_A_SUBTYPE_ID = -1; private UiDevice mUiDevice; @@ -58,7 +58,7 @@ public class UiAutomatorTestCase extends TestCase { super.setUp(); mShouldDisableIme = "true".equals(mParams.getString(DISABLE_IME)); if (mShouldDisableIme) { - setDummyIme(); + setStubIme(); } } @@ -128,7 +128,7 @@ public class UiAutomatorTestCase extends TestCase { SystemClock.sleep(ms); } - private void setDummyIme() { + private void setStubIme() { Context context = ActivityThread.currentApplication(); if (context == null) { throw new RuntimeException("ActivityThread.currentApplication() is null."); @@ -138,13 +138,13 @@ public class UiAutomatorTestCase extends TestCase { List<InputMethodInfo> infos = im.getInputMethodList(); String id = null; for (InputMethodInfo info : infos) { - if (DUMMY_IME_PACKAGE.equals(info.getComponent().getPackageName())) { + if (STUB_IME_PACKAGE.equals(info.getComponent().getPackageName())) { id = info.getId(); } } if (id == null) { throw new RuntimeException(String.format( - "Required testing fixture missing: IME package (%s)", DUMMY_IME_PACKAGE)); + "Required testing fixture missing: IME package (%s)", STUB_IME_PACKAGE)); } if (context.checkSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) != PackageManager.PERMISSION_GRANTED) { diff --git a/config/hiddenapi-force-blacklist.txt b/config/hiddenapi-force-blocked.txt index b328f2ac1955..b328f2ac1955 100644 --- a/config/hiddenapi-force-blacklist.txt +++ b/config/hiddenapi-force-blocked.txt diff --git a/config/hiddenapi-greylist-max-o.txt b/config/hiddenapi-max-target-o.txt index 2889b7c66e7a..2889b7c66e7a 100644 --- a/config/hiddenapi-greylist-max-o.txt +++ b/config/hiddenapi-max-target-o.txt diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-max-target-p.txt index 351e71dd9538..351e71dd9538 100644 --- a/config/hiddenapi-greylist-max-p.txt +++ b/config/hiddenapi-max-target-p.txt diff --git a/config/hiddenapi-greylist-max-q.txt b/config/hiddenapi-max-target-q.txt index f4656044bb72..f4656044bb72 100644 --- a/config/hiddenapi-greylist-max-q.txt +++ b/config/hiddenapi-max-target-q.txt diff --git a/config/hiddenapi-greylist-packages.txt b/config/hiddenapi-unsupported-packages.txt index 986d2591a007..986d2591a007 100644 --- a/config/hiddenapi-greylist-packages.txt +++ b/config/hiddenapi-unsupported-packages.txt diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-unsupported.txt index 52caa421201f..52caa421201f 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-unsupported.txt diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 35cf39f1b056..bc8db029e06d 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -183,7 +183,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim // This is to work around a bug in b/34736819. This needs to be removed once app team // fixes their side. - private AnimatorListenerAdapter mDummyListener = new AnimatorListenerAdapter() { + private AnimatorListenerAdapter mAnimationEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (mNodeMap.get(animation) == null) { @@ -1186,7 +1186,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } private void startAnimation() { - addDummyListener(); + addAnimationEndListener(); // Register animation callback addAnimationCallback(0); @@ -1243,15 +1243,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim // This is to work around the issue in b/34736819, as the old behavior in AnimatorSet had // masked a real bug in play movies. TODO: remove this and below once the root cause is fixed. - private void addDummyListener() { + private void addAnimationEndListener() { for (int i = 1; i < mNodes.size(); i++) { - mNodes.get(i).mAnimation.addListener(mDummyListener); + mNodes.get(i).mAnimation.addListener(mAnimationEndListener); } } - private void removeDummyListener() { + private void removeAnimationEndListener() { for (int i = 1; i < mNodes.size(); i++) { - mNodes.get(i).mAnimation.removeListener(mDummyListener); + mNodes.get(i).mAnimation.removeListener(mAnimationEndListener); } } @@ -1301,7 +1301,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim tmpListeners.get(i).onAnimationEnd(this, mReversing); } } - removeDummyListener(); + removeAnimationEndListener(); mSelfPulse = true; mReversing = false; } @@ -1346,7 +1346,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); anim.mEvents = new ArrayList<AnimationEvent>(); - anim.mDummyListener = new AnimatorListenerAdapter() { + anim.mAnimationEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (anim.mNodeMap.get(animation) == null) { @@ -1369,7 +1369,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim final Node node = mNodes.get(n); Node nodeClone = node.clone(); // Remove the old internal listener from the cloned child - nodeClone.mAnimation.removeListener(mDummyListener); + nodeClone.mAnimation.removeListener(mAnimationEndListener); clonesMap.put(node, nodeClone); anim.mNodes.add(nodeClone); anim.mNodeMap.put(nodeClone.mAnimation, nodeClone); @@ -2087,7 +2087,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim * animation starts. */ public Builder after(long delay) { - // setup dummy ValueAnimator just to run the clock + // setup a ValueAnimator just to run the clock ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setDuration(delay); after(anim); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 925586feaf1d..7bcd6e1cced7 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -679,8 +679,8 @@ public class NotificationManager { * * <p>The name and description should only be changed if the locale changes * or in response to the user renaming this channel. For example, if a user has a channel - * named 'John Doe' that represents messages from a 'John Doe', and 'John Doe' changes his name - * to 'John Smith,' the channel can be renamed to match. + * named 'Messages' and the user changes their locale, this channel's name should be updated + * with the translation of 'Messages' in the new locale. * * <p>The importance of an existing channel will only be changed if the new importance is lower * than the current value and the user has not altered any settings on this channel. diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java index 138578ef6654..7a18b8120d7e 100644 --- a/core/java/android/app/Presentation.java +++ b/core/java/android/app/Presentation.java @@ -19,6 +19,7 @@ package android.app; import static android.content.Context.DISPLAY_SERVICE; import static android.content.Context.WINDOW_SERVICE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; +import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -26,18 +27,18 @@ import android.content.res.Resources; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; +import android.os.Message; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.Display; import android.view.Gravity; import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerImpl; -import android.os.Handler; -import android.os.Message; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; /** * Base class for presentations. @@ -116,7 +117,9 @@ import android.util.TypedValue; * The display manager keeps track of all displays in the system. However, not all * displays are appropriate for showing presentations. For example, if an activity * attempted to show a presentation on the main display it might obscure its own content - * (it's like opening a dialog on top of your activity). + * (it's like opening a dialog on top of your activity). Creating a presentation on the main + * display will result in {@link android.view.WindowManager.InvalidDisplayException} being thrown + * when invoking {@link #show()}. * </p><p> * Here's how to identify suitable displays for showing presentations using * {@link DisplayManager#getDisplays(String)} and the @@ -189,12 +192,16 @@ public class Presentation extends Dialog { mDisplay = display; mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE); + final int windowType = + (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION + : TYPE_PRESENTATION; + final Window w = getWindow(); final WindowManager.LayoutParams attr = w.getAttributes(); attr.token = mToken; w.setAttributes(attr); w.setGravity(Gravity.FILL); - w.setType(TYPE_PRESENTATION); + w.setType(windowType); setCanceledOnTouchOutside(false); } @@ -243,7 +250,7 @@ public class Presentation extends Dialog { /** * Inherited from {@link Dialog#show}. Will throw * {@link android.view.WindowManager.InvalidDisplayException} if the specified secondary - * {@link Display} can't be found. + * {@link Display} can't be found or if it does not have {@link Display#FLAG_PRESENTATION} set. */ @Override public void show() { diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 24580b40aa29..2e17ec8d56d4 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -894,7 +894,7 @@ public abstract class BackupAgent extends ContextWrapper { /** * Only specialized platform agents should overload this entry point to support - * restores to crazy non-app locations. + * restores to non-app locations. * @hide */ protected void onRestoreFile(ParcelFileDescriptor data, long size, diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index 102a08d17deb..bdf3e1a4679c 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -107,7 +107,7 @@ public final class UsageStatsManager { /** - * The app is whitelisted for some reason and the bucket cannot be changed. + * The app is exempted for some reason and the bucket cannot be changed. * {@hide} */ @SystemApi diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index a2cf7d9cc248..8d68cdb14343 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1450,7 +1450,7 @@ public final class BluetoothDevice implements Parcelable { * present in the cache. Clients should use the {@link #getUuids} to get UUIDs * if service discovery is not to be performed. * - * @return False if the sanity check fails, True if the process of initiating an ACL connection + * @return False if the check fails, True if the process of initiating an ACL connection * to the remote device was started. */ @RequiresPermission(Manifest.permission.BLUETOOTH) @@ -1484,7 +1484,7 @@ public final class BluetoothDevice implements Parcelable { * The object type will match one of the SdpXxxRecord types, depending on the UUID searched * for. * - * @return False if the sanity check fails, True if the process + * @return False if the check fails, True if the process * of initiating an ACL connection to the remote device * was started. */ diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 137faea5121f..56ccbb6bfb0d 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1421,13 +1421,12 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * Implementation when a caller has performed an insert on the content * provider, but that call has been rejected for the operation given * to {@link #setAppOps(int, int)}. The default implementation simply - * returns a dummy URI that is the base URI with a 0 path element - * appended. + * returns a URI that is the base URI with a 0 path element appended. */ public Uri rejectInsert(Uri uri, ContentValues values) { // If not allowed, we need to return some reasonable URI. Maybe the // content provider should be responsible for this, but for now we - // will just return the base URI with a dummy '0' tagged on to it. + // will just return the base URI with a '0' tagged on to it. // You shouldn't be able to read if you can't write, anyway, so it // shouldn't matter much what is returned. return uri.buildUpon().appendPath("0").build(); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index a50831fd0193..d1a7eb803d92 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -594,7 +594,7 @@ public abstract class ContentResolver implements ContentInterface { /** * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the - * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away. + * temp allowlist for 10 minutes, so that even RARE apps can run syncs right away. * @hide */ public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2; diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java index 620fdb7deec4..60fc0d8fa27a 100644 --- a/core/java/android/content/SyncStatusInfo.java +++ b/core/java/android/content/SyncStatusInfo.java @@ -270,7 +270,7 @@ public class SyncStatusInfo implements Parcelable { totalStats.numSyncs - totalStats.numSourceLocal - totalStats.numSourcePoll - totalStats.numSourceOther - totalStats.numSourceUser; - if (totalStats.numSourcePeriodic < 0) { // Sanity check. + if (totalStats.numSourcePeriodic < 0) { // Consistency check. totalStats.numSourcePeriodic = 0; } } else { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 62669e019558..9b46afab9e40 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -921,7 +921,7 @@ public class PackageParser { * Automatically detects if the package is a monolithic style (single APK * file) or cluster style (directory of APKs). * <p> - * This performs sanity checking on cluster style packages, such as + * This performs checking on cluster style packages, such as * requiring identical package name and version codes, a single base APK, * and unique split names. * @@ -1038,7 +1038,7 @@ public class PackageParser { * package is a monolithic style (single APK file) or cluster style * (directory of APKs). * <p> - * This performs sanity checking on cluster style packages, such as + * This performs checking on cluster style packages, such as * requiring identical package name and version codes, a single base APK, * and unique split names. * <p> @@ -1255,7 +1255,7 @@ public class PackageParser { /** * Parse all APKs contained in the given directory, treating them as a - * single package. This also performs sanity checking, such as requiring + * single package. This also performs checking, such as requiring * identical package name and version codes, a single base APK, and unique * split names. * <p> diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java index 5d10b8826b00..42b8753f50c1 100644 --- a/core/java/android/content/pm/dex/DexMetadataHelper.java +++ b/core/java/android/content/pm/dex/DexMetadataHelper.java @@ -170,7 +170,7 @@ public class DexMetadataHelper { /** * Validate that the given file is a dex metadata archive. - * This is just a sanity validation that the file is a zip archive. + * This is just a validation that the file is a zip archive. * * @throws PackageParserException if the file is not a .dm file. */ @@ -196,7 +196,7 @@ public class DexMetadataHelper { * (for any foo.dm there should be either a 'foo' of a 'foo.apk' file). * If that's not the case it throws {@code IllegalStateException}. * - * This is used to perform a basic sanity check during adb install commands. + * This is used to perform a basic check during adb install commands. * (The installer does not support stand alone .dm files) */ public static void validateDexPaths(String[] paths) { diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index cec6382cf559..5e1a92b8bd49 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1772,7 +1772,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ public boolean isOtherSeqNewer(Configuration other) { if (other == null) { - // Sanity check. + // Validation check. return false; } if (other.seq == 0) { diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 7a0e183c03fe..56fdd1757d73 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -216,7 +216,7 @@ public final class SQLiteDatabase extends SQLiteClosable { * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly. * The denial of service problem only comes into play when the pattern length gets * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns - * are at most a few dozen bytes in length, paranoid application developers may + * are at most a few dozen bytes in length, cautious application developers may * want to reduce this parameter to something in the range of a few hundred * if they know that external users are able to generate arbitrary patterns. */ diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java index 5496e17206d9..d8a2082f4eae 100644 --- a/core/java/android/metrics/LogMaker.java +++ b/core/java/android/metrics/LogMaker.java @@ -39,7 +39,7 @@ public class LogMaker { /** * Min required eventlog line length. * See: android/util/cts/EventLogTest.java - * Size checks enforced here are intended only as sanity checks; + * Size limits enforced here are intended only as a precaution; * your logs may be truncated earlier. Please log responsibly. * * @hide diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 9c994eb7383a..8b9b0c1f8511 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -608,7 +608,7 @@ public class ConnectivityManager { public static final int TYPE_BLUETOOTH = 7; /** - * Dummy data connection. This should not be used on shipping devices. + * Fake data connection. This should not be used on shipping devices. * @deprecated This is not used any more. */ @Deprecated @@ -1084,9 +1084,9 @@ public class ConnectivityManager { * to remove an existing always-on VPN configuration. * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or * {@code false} otherwise. - * @param lockdownWhitelist The list of packages that are allowed to access network directly + * @param lockdownAllowlist The list of packages that are allowed to access network directly * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so - * this method must be called when a package that should be whitelisted is installed or + * this method must be called when a package that should be allowed is installed or * uninstalled. * @return {@code true} if the package is set as always-on VPN controller; * {@code false} otherwise. @@ -1094,10 +1094,10 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist) { + boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) { try { return mService.setAlwaysOnVpnPackage( - userId, vpnPackage, lockdownEnabled, lockdownWhitelist); + userId, vpnPackage, lockdownEnabled, lockdownAllowlist); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java index 5ab035496a43..1ef4f1741e3a 100644 --- a/core/java/android/net/DhcpResults.java +++ b/core/java/android/net/DhcpResults.java @@ -18,12 +18,13 @@ package android.net; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; -import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; +import com.android.net.module.util.InetAddressUtils; + import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java index e44961528708..713b6888376e 100644 --- a/core/java/android/net/NetworkState.java +++ b/core/java/android/net/NetworkState.java @@ -28,7 +28,7 @@ import android.util.Slog; * @hide */ public class NetworkState implements Parcelable { - private static final boolean SANITY_CHECK_ROAMING = false; + private static final boolean VALIDATE_ROAMING_STATE = false; public static final NetworkState EMPTY = new NetworkState(null, null, null, null, null, null); @@ -52,7 +52,7 @@ public class NetworkState implements Parcelable { // This object is an atomic view of a network, so the various components // should always agree on roaming state. - if (SANITY_CHECK_ROAMING && networkInfo != null && networkCapabilities != null) { + if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) { if (networkInfo.isRoaming() == networkCapabilities .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) { Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index c82c28822232..897b67cbafdf 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -26,6 +26,7 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray; import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; +import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; @@ -364,11 +365,12 @@ public class NetworkStatsHistory implements Parcelable { if (overlap <= 0) continue; // integer math each time is faster than floating point - final long fracRxBytes = rxBytes * overlap / duration; - final long fracRxPackets = rxPackets * overlap / duration; - final long fracTxBytes = txBytes * overlap / duration; - final long fracTxPackets = txPackets * overlap / duration; - final long fracOperations = operations * overlap / duration; + final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration); + final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration); + final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration); + final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration); + final long fracOperations = multiplySafeByRational(operations, overlap, duration); + addLong(activeTime, i, overlap); addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes; @@ -568,12 +570,24 @@ public class NetworkStatsHistory implements Parcelable { if (overlap <= 0) continue; // integer math each time is faster than floating point - if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan; - if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan; - if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan; - if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan; - if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan; - if (operations != null) entry.operations += operations[i] * overlap / bucketSpan; + if (activeTime != null) { + entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan); + } + if (rxBytes != null) { + entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan); + } + if (rxPackets != null) { + entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan); + } + if (txBytes != null) { + entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan); + } + if (txPackets != null) { + entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan); + } + if (operations != null) { + entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan); + } } return entry; } diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 0b92b95128d3..1e5b6d5ab5c0 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -21,13 +21,14 @@ import static android.system.OsConstants.AF_INET6; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; -import android.net.shared.Inet4AddressUtils; import android.os.Build; import android.system.ErrnoException; import android.system.Os; import android.util.Log; import android.util.Pair; +import com.android.net.module.util.Inet4AddressUtils; + import java.io.FileDescriptor; import java.math.BigInteger; import java.net.Inet4Address; @@ -476,4 +477,35 @@ public class NetworkUtils { return true; } + + /** + * Safely multiple a value by a rational. + * <p> + * Internally it uses integer-based math whenever possible, but switches + * over to double-based math if values would overflow. + * @hide + */ + public static long multiplySafeByRational(long value, long num, long den) { + if (den == 0) { + throw new ArithmeticException("Invalid Denominator"); + } + long x = value; + long y = num; + + // Logic shamelessly borrowed from Math.multiplyExact() + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || + (x == Long.MIN_VALUE && y == -1)) { + // Use double math to avoid overflowing + return (long) (((double) num / den) * value); + } + } + return r / den; + } } diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java index 8c6faf6d9970..f6852e681439 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -25,6 +25,7 @@ import com.android.internal.util.TrafficStatsConstants; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Arrays; /** @@ -86,21 +87,26 @@ public class SntpClient { * Sends an SNTP request to the given host and processes the response. * * @param host host name of the server. - * @param timeout network timeout in milliseconds. + * @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup + * time, and it applies to each individual query to the resolved addresses of + * the NTP server. * @param network network over which to send the request. * @return true if the transaction was successful. */ public boolean requestTime(String host, int timeout, Network network) { final Network networkForResolv = network.getPrivateDnsBypassingCopy(); - InetAddress address = null; try { - address = networkForResolv.getByName(host); - } catch (Exception e) { + final InetAddress[] addresses = networkForResolv.getAllByName(host); + for (int i = 0; i < addresses.length; i++) { + if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true; + } + } catch (UnknownHostException e) { + Log.w(TAG, "Unknown host: " + host); EventLogTags.writeNtpFailure(host, e.toString()); - if (DBG) Log.d(TAG, "request time failed: " + e); - return false; } - return requestTime(address, NTP_PORT, timeout, networkForResolv); + + if (DBG) Log.d(TAG, "request time failed"); + return false; } public boolean requestTime(InetAddress address, int port, int timeout, Network network) { @@ -139,10 +145,11 @@ public class SntpClient { final long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET); final long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); final long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); + final long referenceTime = readTimeStamp(buffer, REFERENCE_TIME_OFFSET); - /* do sanity check according to RFC */ + /* Do validation according to RFC */ // TODO: validate originateTime == requestTime. - checkValidServerReply(leap, mode, stratum, transmitTime); + checkValidServerReply(leap, mode, stratum, transmitTime, referenceTime); long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime); // receiveTime = originateTime + transit + skew @@ -218,7 +225,7 @@ public class SntpClient { } private static void checkValidServerReply( - byte leap, byte mode, int stratum, long transmitTime) + byte leap, byte mode, int stratum, long transmitTime, long referenceTime) throws InvalidServerReplyException { if (leap == NTP_LEAP_NOSYNC) { throw new InvalidServerReplyException("unsynchronized server"); @@ -232,6 +239,9 @@ public class SntpClient { if (transmitTime == 0) { throw new InvalidServerReplyException("zero transmitTime"); } + if (referenceTime == 0) { + throw new InvalidServerReplyException("zero reference timestamp"); + } } /** diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index f24a9bd53039..a973455baa04 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -21,11 +21,11 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; -import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.util.Preconditions; +import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; import java.util.ArrayList; diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 9c2c5b839302..8e90a119fe21 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -119,7 +119,7 @@ import java.util.Set; * <p> The Android system starts a VPN in the background by calling * {@link android.content.Context#startService startService()}. In Android 8.0 * (API level 26) and higher, the system places VPN apps on the temporary - * whitelist for a short period so the app can start in the background. The VPN + * allowlist for a short period so the app can start in the background. The VPN * app must promote itself to the foreground after it's launched or the system * will shut down the app. * diff --git a/core/java/android/net/network-policy-restrictions.md b/core/java/android/net/network-policy-restrictions.md index 63ce1a244643..04c658c39ad3 100644 --- a/core/java/android/net/network-policy-restrictions.md +++ b/core/java/android/net/network-policy-restrictions.md @@ -1,11 +1,11 @@ # Data Saver vs Battery Saver -The tables below show whether an app has network access while on background depending on the status of Data Saver mode, Battery Saver mode, and the app's whitelist on those restricted modes. +The tables below show whether an app has network access while on background depending on the status of Data Saver mode, Battery Saver mode, and the app's allowlist on those restricted modes. ### How to read the tables -The 2 topmost rows define the Battery Saver mode and whether the app is whitelisted or not for it. -The 2 leftmost columns define the Data Saver mode and whether the app is whitelisted, not whitelisted, or blacklisted for it. +The 2 topmost rows define the Battery Saver mode and whether the app is allowlisted or not for it. +The 2 leftmost columns define the Data Saver mode and whether the app is allowlisted, not allowlisted, or denylisted for it. The cells define the network status when the app is on background. More specifically: @@ -14,9 +14,9 @@ More specifically: * **DS OFF**: Data Saver Mode is off * **BS ON**: Battery Saver Mode is on * **BS OFF**: Battery Saver Mode is off -* **WL**: app is whitelisted -* **!WL**: app is not whitelisted -* **BL**: app is blacklisted +* **AL**: app is allowlisted +* **!AL**: app is not allowlisted +* **DL**: app is denylisted * **ok**: network access granted while app on background (NetworkInfo's state/detailed state should be `CONNECTED` / `CONNECTED`) * **blk**: network access blocked while app on background (NetworkInfo's state/detailed state should be `DISCONNECTED` / `BLOCKED`) @@ -25,23 +25,23 @@ More specifically: | | | BS | ON | BS | OFF | |:-------:|-------|------|-------|------|-------| -| | | *WL* | *!WL* | *WL* | *!WL* | -| **DS** | *WL* | ok | blk | ok | ok | -| **ON** | *!WL* | blk | blk | blk | blk | -| | *BL* | blk | blk | blk | blk | -| **DS** | *WL* | blk | blk | ok | ok | -| **OFF** | *!WL* | blk | blk | ok | ok | -| | *BL* | blk | blk | blk | blk | +| | | *AL* | *!AL* | *AL* | *!AL* | +| **DS** | *AL* | ok | blk | ok | ok | +| **ON** | *!AL* | blk | blk | blk | blk | +| | *DL* | blk | blk | blk | blk | +| **DS** | *AL* | blk | blk | ok | ok | +| **OFF** | *!AL* | blk | blk | ok | ok | +| | *DL* | blk | blk | blk | blk | ## On non-metered networks | | | BS | ON | BS | OFF | |:-------:|-------|------|-------|------|-------| -| | | *WL* | *!WL* | *WL* | *!WL* | -| **DS** | *WL* | ok | blk | ok | ok | -| **ON** | *!WL* | ok | blk | ok | ok | -| | *BL* | ok | blk | ok | ok | -| **DS** | *WL* | ok | blk | ok | ok | -| **OFF** | *!WL* | ok | blk | ok | ok | -| | *BL* | ok | blk | ok | ok | +| | | *AL* | *!AL* | *AL* | *!AL* | +| **DS** | *AL* | ok | blk | ok | ok | +| **ON** | *!AL* | ok | blk | ok | ok | +| | *DL* | ok | blk | ok | ok | +| **DS** | *AL* | ok | blk | ok | ok | +| **OFF** | *!AL* | ok | blk | ok | ok | +| | *DL* | ok | blk | ok | ok | diff --git a/core/java/android/net/shared/Inet4AddressUtils.java b/core/java/android/net/shared/Inet4AddressUtils.java deleted file mode 100644 index bec0c84fa689..000000000000 --- a/core/java/android/net/shared/Inet4AddressUtils.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.shared; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Collection of utilities to work with IPv4 addresses. - * @hide - */ -public class Inet4AddressUtils { - - /** - * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4) - * - * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes, - * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead. - * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is - * lower-order IPv4 address byte - */ - public static Inet4Address intToInet4AddressHTL(int hostAddress) { - return intToInet4AddressHTH(Integer.reverseBytes(hostAddress)); - } - - /** - * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4) - * @param hostAddress an int coding for an IPv4 address - */ - public static Inet4Address intToInet4AddressHTH(int hostAddress) { - byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)), - (byte) (0xff & (hostAddress >> 16)), - (byte) (0xff & (hostAddress >> 8)), - (byte) (0xff & hostAddress) }; - - try { - return (Inet4Address) InetAddress.getByAddress(addressBytes); - } catch (UnknownHostException e) { - throw new AssertionError(); - } - } - - /** - * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304) - * - * <p>This conversion can help order IP addresses: considering the ordering - * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned - * integers with {@link Integer#toUnsignedLong}. - * @param inetAddr is an InetAddress corresponding to the IPv4 address - * @return the IP address as integer - */ - public static int inet4AddressToIntHTH(Inet4Address inetAddr) - throws IllegalArgumentException { - byte [] addr = inetAddr.getAddress(); - return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16) - | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff); - } - - /** - * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201) - * - * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, - * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead. - * @param inetAddr is an InetAddress corresponding to the IPv4 address - * @return the IP address as integer - */ - public static int inet4AddressToIntHTL(Inet4Address inetAddr) { - return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr)); - } - - /** - * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000) - * @return the IPv4 netmask as an integer - */ - public static int prefixLengthToV4NetmaskIntHTH(int prefixLength) - throws IllegalArgumentException { - if (prefixLength < 0 || prefixLength > 32) { - throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)"); - } - // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1) - return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength); - } - - /** - * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff). - * - * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, - * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead. - * @return the IPv4 netmask as an integer - */ - public static int prefixLengthToV4NetmaskIntHTL(int prefixLength) - throws IllegalArgumentException { - return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength)); - } - - /** - * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous. - * @param netmask as a {@code Inet4Address}. - * @return the network prefix length - * @throws IllegalArgumentException the specified netmask was not contiguous. - * @hide - */ - public static int netmaskToPrefixLength(Inet4Address netmask) { - // inetAddressToInt returns an int in *network* byte order. - int i = inet4AddressToIntHTH(netmask); - int prefixLength = Integer.bitCount(i); - int trailingZeros = Integer.numberOfTrailingZeros(i); - if (trailingZeros != 32 - prefixLength) { - throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i)); - } - return prefixLength; - } - - /** - * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. - */ - public static int getImplicitNetmask(Inet4Address address) { - int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value. - if (firstByte < 128) { - return 8; - } else if (firstByte < 192) { - return 16; - } else if (firstByte < 224) { - return 24; - } else { - return 32; // Will likely not end well for other reasons. - } - } - - /** - * Get the broadcast address for a given prefix. - * - * <p>For example 192.168.0.1/24 -> 192.168.0.255 - */ - public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength) - throws IllegalArgumentException { - final int intBroadcastAddr = inet4AddressToIntHTH(addr) - | ~prefixLengthToV4NetmaskIntHTH(prefixLength); - return intToInet4AddressHTH(intBroadcastAddr); - } - - /** - * Get a prefix mask as Inet4Address for a given prefix length. - * - * <p>For example 20 -> 255.255.240.0 - */ - public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength) - throws IllegalArgumentException { - return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength)); - } -} diff --git a/core/java/android/net/shared/InetAddressUtils.java b/core/java/android/net/shared/InetAddressUtils.java deleted file mode 100644 index c9ee3a7cce4b..000000000000 --- a/core/java/android/net/shared/InetAddressUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.shared; - -import android.os.Parcel; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Collection of utilities to interact with {@link InetAddress} - * @hide - */ -public class InetAddressUtils { - - /** - * Writes an InetAddress to a parcel. The address may be null. This is likely faster than - * calling writeSerializable. - * @hide - */ - public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) { - byte[] addressArray = (address != null) ? address.getAddress() : null; - parcel.writeByteArray(addressArray); - } - - /** - * Reads an InetAddress from a parcel. Returns null if the address that was written was null - * or if the data is invalid. - * @hide - */ - public static InetAddress unparcelInetAddress(Parcel in) { - byte[] addressArray = in.createByteArray(); - if (addressArray == null) { - return null; - } - try { - return InetAddress.getByAddress(addressArray); - } catch (UnknownHostException e) { - return null; - } - } - - private InetAddressUtils() {} -} diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java index 92574968e965..74b814ea4159 100644 --- a/core/java/android/os/AppZygote.java +++ b/core/java/android/os/AppZygote.java @@ -92,10 +92,9 @@ public class AppZygote { @GuardedBy("mLock") private void stopZygoteLocked() { if (mZygote != null) { - // Close the connection and kill the zygote process. This will not cause - // child processes to be killed by itself. mZygote.close(); - Process.killProcess(mZygote.getPid()); + // use killProcessGroup() here, so we kill all untracked children as well. + Process.killProcessGroup(mZygoteUid, mZygote.getPid()); mZygote = null; } } diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index f2cf4e3981d3..bf6284347e93 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -505,15 +505,17 @@ public class Binder implements IBinder { /** * Mark as being built with VINTF-level stability promise. This API should - * only ever be invoked by the build system. It means that the interface - * represented by this binder is guaranteed to be kept stable for several - * years, and the build system also keeps snapshots of these APIs and - * invokes the AIDL compiler to make sure that these snapshots are - * backwards compatible. Instead of using this API, use an @VintfStability - * interface. + * only ever be invoked by generated code from the aidl compiler. It means + * that the interface represented by this binder is guaranteed to be kept + * stable for several years, according to the VINTF compatibility lifecycle, + * and the build system also keeps snapshots of these APIs and invokes the + * AIDL compiler to make sure that these snapshots are backwards compatible. + * Instead of using this API, use the @VintfStability annotation on your + * AIDL interface. * * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final native void markVintfStability(); /** diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java index 18ba5a8a4a34..fd576c94b194 100644 --- a/core/java/android/os/DropBoxManager.java +++ b/core/java/android/os/DropBoxManager.java @@ -276,7 +276,7 @@ public class DropBoxManager { } /** - * Create a dummy instance for testing. All methods will fail unless + * Create an instance for testing. All methods will fail unless * overridden with an appropriate mock implementation. To obtain a * functional instance, use {@link android.content.Context#getSystemService}. */ diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index a47fbbaab9dd..d3a0820a838b 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1302,7 +1302,7 @@ public final class FileUtils { /** {@hide} */ public static int translateModeStringToPosix(String mode) { - // Sanity check for invalid chars + // Quick check for invalid chars for (int i = 0; i < mode.length(); i++) { switch (mode.charAt(i)) { case 'r': diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index e371df001151..ac51e7ef9e64 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -1,4 +1,4 @@ # Zygote -per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com +per-file ZygoteProcess.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 9b360edb7238..f14f66b07630 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -17,6 +17,7 @@ package android.os; import android.annotation.IntDef; +import android.annotation.SystemApi; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -99,6 +100,37 @@ public interface Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface ContentsFlags {} + /** @hide */ + @IntDef(flag = true, prefix = { "PARCELABLE_STABILITY_" }, value = { + PARCELABLE_STABILITY_LOCAL, + PARCELABLE_STABILITY_VINTF, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Stability {} + + /** + * Something that is not meant to cross compilation boundaries. + * + * Note: unlike binder/Stability.h which uses bitsets to detect stability, + * since we don't currently have a notion of different local locations, + * higher stability levels are formed at higher levels. + * + * For instance, contained entirely within system partitions. + * @see #getStability() + * @see ParcelableHolder + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int PARCELABLE_STABILITY_LOCAL = 0x0000; + /** + * Something that is meant to be used between system and vendor. + * @see #getStability() + * @see ParcelableHolder + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int PARCELABLE_STABILITY_VINTF = 0x0001; + /** * Descriptor bit used with {@link #describeContents()}: indicates that * the Parcelable object's flattened representation includes a file descriptor. @@ -129,8 +161,9 @@ public interface Parcelable { * @return true if this parcelable is stable. * @hide */ - default boolean isStable() { - return false; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + default @Stability int getStability() { + return PARCELABLE_STABILITY_LOCAL; } /** diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java index c37a2ff1112c..181f94b39841 100644 --- a/core/java/android/os/ParcelableHolder.java +++ b/core/java/android/os/ParcelableHolder.java @@ -37,10 +37,10 @@ public final class ParcelableHolder implements Parcelable { * if {@link ParcelableHolder} contains value, otherwise, both are null. */ private Parcel mParcel; - private boolean mIsStable = false; + private @Parcelable.Stability int mStability = Parcelable.PARCELABLE_STABILITY_LOCAL; - public ParcelableHolder(boolean isStable) { - mIsStable = isStable; + public ParcelableHolder(@Parcelable.Stability int stability) { + mStability = stability; } private ParcelableHolder() { @@ -50,11 +50,11 @@ public final class ParcelableHolder implements Parcelable { /** * {@link ParcelableHolder}'s stability is determined by the parcelable * which contains this ParcelableHolder. - * For more detail refer to {@link Parcelable#isStable}. + * For more detail refer to {@link Parcelable#getStability}. */ @Override - public boolean isStable() { - return mIsStable; + public @Parcelable.Stability int getStability() { + return mStability; } @NonNull @@ -81,7 +81,8 @@ public final class ParcelableHolder implements Parcelable { * @return {@code false} if the parcelable's stability is more unstable ParcelableHolder. */ public synchronized boolean setParcelable(@Nullable Parcelable p) { - if (p != null && this.isStable() && !p.isStable()) { + // a ParcelableHolder can only hold things at its stability or higher + if (p != null && this.getStability() > p.getStability()) { return false; } mParcelable = p; @@ -123,7 +124,7 @@ public final class ParcelableHolder implements Parcelable { * Read ParcelableHolder from a parcel. */ public synchronized void readFromParcel(@NonNull Parcel parcel) { - this.mIsStable = parcel.readBoolean(); + this.mStability = parcel.readInt(); mParcelable = null; @@ -145,7 +146,7 @@ public final class ParcelableHolder implements Parcelable { @Override public synchronized void writeToParcel(@NonNull Parcel parcel, int flags) { - parcel.writeBoolean(this.mIsStable); + parcel.writeInt(this.mStability); if (mParcel != null) { parcel.writeInt(mParcel.dataSize()); diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 6334e7bf9c5a..f71f98a45284 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -249,11 +249,11 @@ public class ZygoteProcess { private final Object mLock = new Object(); /** - * List of exemptions to the API blacklist. These are prefix matches on the runtime format + * List of exemptions to the API deny list. These are prefix matches on the runtime format * symbol signature. Any matching symbol is treated by the runtime as being on the light grey * list. */ - private List<String> mApiBlacklistExemptions = Collections.emptyList(); + private List<String> mApiDenylistExemptions = Collections.emptyList(); /** * Proportion of hidden API accesses that should be logged to the event log; 0 - 0x10000. @@ -545,7 +545,7 @@ public class ZygoteProcess { "--preload-package", "--preload-app", "--start-child-zygote", - "--set-api-blacklist-exemptions", + "--set-api-denylist-exemptions", "--hidden-api-log-sampling-rate", "--hidden-api-statslog-sampling-rate", "--invoke-with" @@ -857,20 +857,20 @@ public class ZygoteProcess { } /** - * Push hidden API blacklisting exemptions into the zygote process(es). + * Push hidden API denylisting exemptions into the zygote process(es). * * <p>The list of exemptions will take affect for all new processes forked from the zygote after * this call. * * @param exemptions List of hidden API exemption prefixes. Any matching members are treated as - * whitelisted/public APIs (i.e. allowed, no logging of usage). + * allowlisted/public APIs (i.e. allowed, no logging of usage). */ - public boolean setApiBlacklistExemptions(List<String> exemptions) { + public boolean setApiDenylistExemptions(List<String> exemptions) { synchronized (mLock) { - mApiBlacklistExemptions = exemptions; - boolean ok = maybeSetApiBlacklistExemptions(primaryZygoteState, true); + mApiDenylistExemptions = exemptions; + boolean ok = maybeSetApiDenylistExemptions(primaryZygoteState, true); if (ok) { - ok = maybeSetApiBlacklistExemptions(secondaryZygoteState, true); + ok = maybeSetApiDenylistExemptions(secondaryZygoteState, true); } return ok; } @@ -907,32 +907,32 @@ public class ZygoteProcess { } @GuardedBy("mLock") - private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) { + private boolean maybeSetApiDenylistExemptions(ZygoteState state, boolean sendIfEmpty) { if (state == null || state.isClosed()) { - Slog.e(LOG_TAG, "Can't set API blacklist exemptions: no zygote connection"); + Slog.e(LOG_TAG, "Can't set API denylist exemptions: no zygote connection"); return false; - } else if (!sendIfEmpty && mApiBlacklistExemptions.isEmpty()) { + } else if (!sendIfEmpty && mApiDenylistExemptions.isEmpty()) { return true; } try { - state.mZygoteOutputWriter.write(Integer.toString(mApiBlacklistExemptions.size() + 1)); + state.mZygoteOutputWriter.write(Integer.toString(mApiDenylistExemptions.size() + 1)); state.mZygoteOutputWriter.newLine(); - state.mZygoteOutputWriter.write("--set-api-blacklist-exemptions"); + state.mZygoteOutputWriter.write("--set-api-denylist-exemptions"); state.mZygoteOutputWriter.newLine(); - for (int i = 0; i < mApiBlacklistExemptions.size(); ++i) { - state.mZygoteOutputWriter.write(mApiBlacklistExemptions.get(i)); + for (int i = 0; i < mApiDenylistExemptions.size(); ++i) { + state.mZygoteOutputWriter.write(mApiDenylistExemptions.get(i)); state.mZygoteOutputWriter.newLine(); } state.mZygoteOutputWriter.flush(); int status = state.mZygoteInputStream.readInt(); if (status != 0) { - Slog.e(LOG_TAG, "Failed to set API blacklist exemptions; status " + status); + Slog.e(LOG_TAG, "Failed to set API denylist exemptions; status " + status); } return true; } catch (IOException ioe) { - Slog.e(LOG_TAG, "Failed to set API blacklist exemptions", ioe); - mApiBlacklistExemptions = Collections.emptyList(); + Slog.e(LOG_TAG, "Failed to set API denylist exemptions", ioe); + mApiDenylistExemptions = Collections.emptyList(); return false; } } @@ -989,7 +989,7 @@ public class ZygoteProcess { primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); - maybeSetApiBlacklistExemptions(primaryZygoteState, false); + maybeSetApiDenylistExemptions(primaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState); maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState); } @@ -1005,7 +1005,7 @@ public class ZygoteProcess { ZygoteState.connect(mZygoteSecondarySocketAddress, mUsapPoolSecondarySocketAddress); - maybeSetApiBlacklistExemptions(secondaryZygoteState, false); + maybeSetApiDenylistExemptions(secondaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState); maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState); } diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java index 2143a0deb723..643df6970560 100644 --- a/core/java/android/provider/DocumentsProvider.java +++ b/core/java/android/provider/DocumentsProvider.java @@ -1260,6 +1260,7 @@ public abstract class DocumentsProvider extends ContentProvider { out.putParcelable(DocumentsContract.EXTRA_RESULT, path); } else if (METHOD_GET_DOCUMENT_METADATA.equals(method)) { + enforceReadPermissionInner(documentUri, getCallingPackage(), null); return getDocumentMetadata(documentId); } else { throw new UnsupportedOperationException("Method not supported " + method); diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java index 57068fa2eb63..00872fb3b62d 100644 --- a/core/java/android/security/net/config/NetworkSecurityConfig.java +++ b/core/java/android/security/net/config/NetworkSecurityConfig.java @@ -216,7 +216,7 @@ public final class NetworkSecurityConfig { * in {@link Builder#build()}, recursively if needed. */ public Builder setParent(Builder parent) { - // Sanity check to avoid adding loops. + // Quick check to avoid adding loops. Builder current = parent; while (current != null) { if (current == this) { diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 3611d924b904..7b50b7044e0e 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -108,7 +108,6 @@ public class TelephonyRegistryManager { IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { @Override public void onSubscriptionsChanged () { - Log.d(TAG, "onSubscriptionsChangedListener callback received."); executor.execute(() -> listener.onSubscriptionsChanged()); } }; diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 55af087ca5b8..8da92e38213e 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -549,7 +549,7 @@ public class Html { out.append(((ImageSpan) style[j]).getSource()); out.append("\">"); - // Don't output the dummy character underlying the image. + // Don't output the placeholder character underlying the image. i = next; } if (style[j] instanceof AbsoluteSizeSpan) { diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 683c74737a2d..38e3b39f8cfc 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -19,14 +19,13 @@ package android.text.format; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.icu.text.DateFormatSymbols; import android.icu.text.DateTimePatternGenerator; import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.SpannedString; -import libcore.icu.LocaleData; - import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -286,8 +285,10 @@ public class DateFormat { */ @UnsupportedAppUsage public static String getTimeFormatString(Context context, int userHandle) { - final LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); - return is24HourFormat(context, userHandle) ? d.timeFormat_Hm : d.timeFormat_hm; + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance( + context.getResources().getConfiguration().locale); + return is24HourFormat(context, userHandle) ? dtpg.getBestPattern("Hm") + : dtpg.getBestPattern("hm"); } /** @@ -474,7 +475,8 @@ public class DateFormat { SpannableStringBuilder s = new SpannableStringBuilder(inFormat); int count; - LocaleData localeData = LocaleData.get(Locale.getDefault()); + DateFormatSymbols dfs = getIcuDateFormatSymbols(Locale.getDefault()); + String[] amPm = dfs.getAmPmStrings(); int len = inFormat.length(); @@ -496,14 +498,14 @@ public class DateFormat { switch (c) { case 'A': case 'a': - replacement = localeData.amPm[inDate.get(Calendar.AM_PM) - Calendar.AM]; + replacement = amPm[inDate.get(Calendar.AM_PM) - Calendar.AM]; break; case 'd': replacement = zeroPad(inDate.get(Calendar.DATE), count); break; case 'c': case 'E': - replacement = getDayOfWeekString(localeData, + replacement = getDayOfWeekString(dfs, inDate.get(Calendar.DAY_OF_WEEK), count, c); break; case 'K': // hour in am/pm (0-11) @@ -531,8 +533,7 @@ public class DateFormat { break; case 'L': case 'M': - replacement = getMonthString(localeData, - inDate.get(Calendar.MONTH), count, c); + replacement = getMonthString(dfs, inDate.get(Calendar.MONTH), count, c); break; case 'm': replacement = zeroPad(inDate.get(Calendar.MINUTE), count); @@ -565,25 +566,29 @@ public class DateFormat { } } - private static String getDayOfWeekString(LocaleData ld, int day, int count, int kind) { + private static String getDayOfWeekString(DateFormatSymbols dfs, int day, int count, int kind) { boolean standalone = (kind == 'c'); + int context = standalone ? DateFormatSymbols.STANDALONE : DateFormatSymbols.FORMAT; + final int width; if (count == 5) { - return standalone ? ld.tinyStandAloneWeekdayNames[day] : ld.tinyWeekdayNames[day]; + width = DateFormatSymbols.NARROW; } else if (count == 4) { - return standalone ? ld.longStandAloneWeekdayNames[day] : ld.longWeekdayNames[day]; + width = DateFormatSymbols.WIDE; } else { - return standalone ? ld.shortStandAloneWeekdayNames[day] : ld.shortWeekdayNames[day]; + width = DateFormatSymbols.ABBREVIATED; } + return dfs.getWeekdays(context, width)[day]; } - private static String getMonthString(LocaleData ld, int month, int count, int kind) { + private static String getMonthString(DateFormatSymbols dfs, int month, int count, int kind) { boolean standalone = (kind == 'L'); + int monthContext = standalone ? DateFormatSymbols.STANDALONE : DateFormatSymbols.FORMAT; if (count == 5) { - return standalone ? ld.tinyStandAloneMonthNames[month] : ld.tinyMonthNames[month]; + return dfs.getMonths(monthContext, DateFormatSymbols.NARROW)[month]; } else if (count == 4) { - return standalone ? ld.longStandAloneMonthNames[month] : ld.longMonthNames[month]; + return dfs.getMonths(monthContext, DateFormatSymbols.WIDE)[month]; } else if (count == 3) { - return standalone ? ld.shortStandAloneMonthNames[month] : ld.shortMonthNames[month]; + return dfs.getMonths(monthContext, DateFormatSymbols.ABBREVIATED)[month]; } else { // Calendar.JANUARY == 0, so add 1 to month. return zeroPad(month+1, count); @@ -678,4 +683,16 @@ public class DateFormat { private static String zeroPad(int inValue, int inMinDigits) { return String.format(Locale.getDefault(), "%0" + inMinDigits + "d", inValue); } + + /** + * We use Gregorian calendar for date formats in android.text.format and various UI widget + * historically. It's a utility method to get an {@link DateFormatSymbols} instance. Note that + * {@link DateFormatSymbols} has cache, and external cache is not needed unless same instance is + * requested repeatedly in the performance critical code. + * + * @hide + */ + public static DateFormatSymbols getIcuDateFormatSymbols(Locale locale) { + return new DateFormatSymbols(android.icu.util.GregorianCalendar.class, locale); + } } diff --git a/core/java/android/text/format/DateIntervalFormat.java b/core/java/android/text/format/DateIntervalFormat.java new file mode 100644 index 000000000000..e8236fda42b6 --- /dev/null +++ b/core/java/android/text/format/DateIntervalFormat.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text.format; + +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_UTC; + +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; + +import android.icu.util.Calendar; +import android.icu.util.ULocale; +import android.util.LruCache; + +import com.android.internal.annotations.VisibleForTesting; + +import java.text.FieldPosition; +import java.util.TimeZone; + +/** + * A wrapper of {@link android.icu.text.DateIntervalFormat} used by {@link DateUtilsBridge}. + * + * @hide + */ +@VisibleForTesting(visibility = PACKAGE) +public final class DateIntervalFormat { + + private static final LruCache<String, android.icu.text.DateIntervalFormat> CACHED_FORMATTERS = + new LruCache<>(8); + + private DateIntervalFormat() { + } + + /** + * Format a date range. + */ + @VisibleForTesting(visibility = PACKAGE) + public static String formatDateRange(long startMs, long endMs, int flags, String olsonId) { + if ((flags & FORMAT_UTC) != 0) { + olsonId = "UTC"; + } + // We create a java.util.TimeZone here to use libcore's data and libcore's olson ID / + // pseudo-tz logic. + TimeZone tz = (olsonId != null) ? TimeZone.getTimeZone(olsonId) : TimeZone.getDefault(); + android.icu.util.TimeZone icuTimeZone = DateUtilsBridge.icuTimeZone(tz); + ULocale icuLocale = ULocale.getDefault(); + return formatDateRange(icuLocale, icuTimeZone, startMs, endMs, flags); + } + + /** + * Format a date range. This is our slightly more sensible internal API. + * A truly reasonable replacement would take a skeleton instead of int flags. + */ + @VisibleForTesting(visibility = PACKAGE) + public static String formatDateRange(ULocale icuLocale, android.icu.util.TimeZone icuTimeZone, + long startMs, long endMs, int flags) { + Calendar startCalendar = DateUtilsBridge.createIcuCalendar(icuTimeZone, icuLocale, startMs); + Calendar endCalendar; + if (startMs == endMs) { + endCalendar = startCalendar; + } else { + endCalendar = DateUtilsBridge.createIcuCalendar(icuTimeZone, icuLocale, endMs); + } + + // Special handling when the range ends at midnight: + // - If we're not showing times, and the range is non-empty, we fudge the end date so we + // don't count the day that's about to start. + // - If we are showing times, and the range ends at exactly 00:00 of the day following + // its start (which can be thought of as 24:00 the same day), we fudge the end date so we + // don't show the dates --- unless the start is anything displayed as 00:00, in which case + // we include both dates to disambiguate. + // This is not the behavior of icu4j's DateIntervalFormat, but it's the required behavior + // of Android's DateUtils.formatDateRange. + if (isExactlyMidnight(endCalendar)) { + boolean showTime = (flags & FORMAT_SHOW_TIME) == FORMAT_SHOW_TIME; + boolean endsDayAfterStart = DateUtilsBridge.dayDistance(startCalendar, endCalendar) + == 1; + if ((!showTime && startMs != endMs) + || (endsDayAfterStart + && !DateUtilsBridge.isDisplayMidnightUsingSkeleton(startCalendar))) { + endCalendar.add(Calendar.DAY_OF_MONTH, -1); + } + } + + String skeleton = DateUtilsBridge.toSkeleton(startCalendar, endCalendar, flags); + synchronized (CACHED_FORMATTERS) { + android.icu.text.DateIntervalFormat formatter = + getFormatter(skeleton, icuLocale, icuTimeZone); + return formatter.format(startCalendar, endCalendar, new StringBuffer(), + new FieldPosition(0)).toString(); + } + } + + private static android.icu.text.DateIntervalFormat getFormatter(String skeleton, ULocale locale, + android.icu.util.TimeZone icuTimeZone) { + String key = skeleton + "\t" + locale + "\t" + icuTimeZone; + android.icu.text.DateIntervalFormat formatter = CACHED_FORMATTERS.get(key); + if (formatter != null) { + return formatter; + } + formatter = android.icu.text.DateIntervalFormat.getInstance(skeleton, locale); + formatter.setTimeZone(icuTimeZone); + CACHED_FORMATTERS.put(key, formatter); + return formatter; + } + + private static boolean isExactlyMidnight(Calendar c) { + return c.get(Calendar.HOUR_OF_DAY) == 0 + && c.get(Calendar.MINUTE) == 0 + && c.get(Calendar.SECOND) == 0 + && c.get(Calendar.MILLISECOND) == 0; + } +} diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java index b0253a0af7a7..31464575186b 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -20,6 +20,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.icu.text.DateFormatSymbols; import android.icu.text.MeasureFormat; import android.icu.text.MeasureFormat.FormatWidth; import android.icu.util.Measure; @@ -27,9 +28,6 @@ import android.icu.util.MeasureUnit; import com.android.internal.R; -import libcore.icu.DateIntervalFormat; -import libcore.icu.LocaleData; - import java.io.IOException; import java.util.Calendar; import java.util.Date; @@ -201,17 +199,23 @@ public class DateUtils */ @Deprecated public static String getDayOfWeekString(int dayOfWeek, int abbrev) { - LocaleData d = LocaleData.get(Locale.getDefault()); - String[] names; + DateFormatSymbols dfs = DateFormatSymbols.getInstance(); + final int width; switch (abbrev) { - case LENGTH_LONG: names = d.longWeekdayNames; break; - case LENGTH_MEDIUM: names = d.shortWeekdayNames; break; - case LENGTH_SHORT: names = d.shortWeekdayNames; break; // TODO - case LENGTH_SHORTER: names = d.shortWeekdayNames; break; // TODO - case LENGTH_SHORTEST: names = d.tinyWeekdayNames; break; - default: names = d.shortWeekdayNames; break; + case LENGTH_LONG: + width = DateFormatSymbols.WIDE; + break; + case LENGTH_SHORTEST: + width = DateFormatSymbols.NARROW; + break; + case LENGTH_MEDIUM: + case LENGTH_SHORT: // TODO + case LENGTH_SHORTER: // TODO + default: + width = DateFormatSymbols.ABBREVIATED; + break; } - return names[dayOfWeek]; + return dfs.getWeekdays(DateFormatSymbols.FORMAT, width)[dayOfWeek]; } /** @@ -223,7 +227,8 @@ public class DateUtils */ @Deprecated public static String getAMPMString(int ampm) { - return LocaleData.get(Locale.getDefault()).amPm[ampm - Calendar.AM]; + String[] amPm = DateFormat.getIcuDateFormatSymbols(Locale.getDefault()).getAmPmStrings(); + return amPm[ampm - Calendar.AM]; } /** @@ -239,17 +244,23 @@ public class DateUtils */ @Deprecated public static String getMonthString(int month, int abbrev) { - LocaleData d = LocaleData.get(Locale.getDefault()); - String[] names; + DateFormatSymbols dfs = DateFormat.getIcuDateFormatSymbols(Locale.getDefault()); + final int width; switch (abbrev) { - case LENGTH_LONG: names = d.longMonthNames; break; - case LENGTH_MEDIUM: names = d.shortMonthNames; break; - case LENGTH_SHORT: names = d.shortMonthNames; break; - case LENGTH_SHORTER: names = d.shortMonthNames; break; - case LENGTH_SHORTEST: names = d.tinyMonthNames; break; - default: names = d.shortMonthNames; break; + case LENGTH_LONG: + width = DateFormatSymbols.WIDE; + break; + case LENGTH_SHORTEST: + width = DateFormatSymbols.NARROW; + break; + case LENGTH_MEDIUM: + case LENGTH_SHORT: + case LENGTH_SHORTER: + default: + width = DateFormatSymbols.ABBREVIATED; + break; } - return names[month]; + return dfs.getMonths(DateFormatSymbols.FORMAT, width)[month]; } /** diff --git a/core/java/android/text/format/DateUtilsBridge.java b/core/java/android/text/format/DateUtilsBridge.java index 370d999abf3e..92ec9cf6d736 100644 --- a/core/java/android/text/format/DateUtilsBridge.java +++ b/core/java/android/text/format/DateUtilsBridge.java @@ -16,6 +16,20 @@ package android.text.format; +import static android.text.format.DateUtils.FORMAT_12HOUR; +import static android.text.format.DateUtils.FORMAT_24HOUR; +import static android.text.format.DateUtils.FORMAT_ABBREV_ALL; +import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; +import static android.text.format.DateUtils.FORMAT_ABBREV_TIME; +import static android.text.format.DateUtils.FORMAT_ABBREV_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_NO_MONTH_DAY; +import static android.text.format.DateUtils.FORMAT_NO_YEAR; +import static android.text.format.DateUtils.FORMAT_NUMERIC_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; + import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import android.icu.util.Calendar; @@ -33,24 +47,6 @@ import com.android.internal.annotations.VisibleForTesting; */ @VisibleForTesting(visibility = PACKAGE) public final class DateUtilsBridge { - // These are all public API in DateUtils. There are others, but they're either for use with - // other methods (like FORMAT_ABBREV_RELATIVE), don't internationalize (like FORMAT_CAP_AMPM), - // or have never been implemented anyway. - public static final int FORMAT_SHOW_TIME = 0x00001; - public static final int FORMAT_SHOW_WEEKDAY = 0x00002; - public static final int FORMAT_SHOW_YEAR = 0x00004; - public static final int FORMAT_NO_YEAR = 0x00008; - public static final int FORMAT_SHOW_DATE = 0x00010; - public static final int FORMAT_NO_MONTH_DAY = 0x00020; - public static final int FORMAT_12HOUR = 0x00040; - public static final int FORMAT_24HOUR = 0x00080; - public static final int FORMAT_UTC = 0x02000; - public static final int FORMAT_ABBREV_TIME = 0x04000; - public static final int FORMAT_ABBREV_WEEKDAY = 0x08000; - public static final int FORMAT_ABBREV_MONTH = 0x10000; - public static final int FORMAT_NUMERIC_DATE = 0x20000; - public static final int FORMAT_ABBREV_RELATIVE = 0x40000; - public static final int FORMAT_ABBREV_ALL = 0x80000; /** * Creates an immutable ICU timezone backed by the specified libcore timezone data. At the time diff --git a/core/java/android/text/format/OWNERS b/core/java/android/text/format/OWNERS new file mode 100644 index 000000000000..32adc12bb901 --- /dev/null +++ b/core/java/android/text/format/OWNERS @@ -0,0 +1,3 @@ +# Inherits OWNERS from parent directory, plus the following + +vichang@google.com diff --git a/core/java/android/text/format/RelativeDateTimeFormatter.java b/core/java/android/text/format/RelativeDateTimeFormatter.java index c5bca172873a..9096469699c1 100644 --- a/core/java/android/text/format/RelativeDateTimeFormatter.java +++ b/core/java/android/text/format/RelativeDateTimeFormatter.java @@ -16,14 +16,14 @@ package android.text.format; -import static android.text.format.DateUtilsBridge.FORMAT_ABBREV_ALL; -import static android.text.format.DateUtilsBridge.FORMAT_ABBREV_MONTH; -import static android.text.format.DateUtilsBridge.FORMAT_ABBREV_RELATIVE; -import static android.text.format.DateUtilsBridge.FORMAT_NO_YEAR; -import static android.text.format.DateUtilsBridge.FORMAT_NUMERIC_DATE; -import static android.text.format.DateUtilsBridge.FORMAT_SHOW_DATE; -import static android.text.format.DateUtilsBridge.FORMAT_SHOW_TIME; -import static android.text.format.DateUtilsBridge.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.FORMAT_ABBREV_ALL; +import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; +import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE; +import static android.text.format.DateUtils.FORMAT_NO_YEAR; +import static android.text.format.DateUtils.FORMAT_NUMERIC_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index e7339380df69..fb8dd0eaee12 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -361,7 +361,7 @@ public class Time { */ @Override public String toString() { - // toString() uses its own TimeCalculator rather than the shared one. Otherwise crazy stuff + // toString() uses its own TimeCalculator rather than the shared one. Otherwise weird stuff // happens during debugging when the debugger calls toString(). TimeCalculator calculator = new TimeCalculator(this.timezone); calculator.copyFieldsFromTime(this); diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java index cd541f2b829f..c71dfbbafd40 100644 --- a/core/java/android/text/format/TimeFormatter.java +++ b/core/java/android/text/format/TimeFormatter.java @@ -21,11 +21,11 @@ package android.text.format; import android.content.res.Resources; +import android.icu.text.DateFormatSymbols; +import android.icu.text.DecimalFormatSymbols; import com.android.i18n.timezone.ZoneInfoData; -import libcore.icu.LocaleData; - import java.nio.CharBuffer; import java.time.Instant; import java.time.LocalDateTime; @@ -52,15 +52,17 @@ class TimeFormatter { private static final int DAYSPERNYEAR = 365; /** - * The Locale for which the cached LocaleData and formats have been loaded. + * The Locale for which the cached symbols and formats have been loaded. */ private static Locale sLocale; - private static LocaleData sLocaleData; + private static DateFormatSymbols sDateFormatSymbols; + private static DecimalFormatSymbols sDecimalFormatSymbols; private static String sTimeOnlyFormat; private static String sDateOnlyFormat; private static String sDateTimeFormat; - private final LocaleData localeData; + private final DateFormatSymbols dateFormatSymbols; + private final DecimalFormatSymbols decimalFormatSymbols; private final String dateTimeFormat; private final String timeOnlyFormat; private final String dateOnlyFormat; @@ -74,7 +76,8 @@ class TimeFormatter { if (sLocale == null || !(locale.equals(sLocale))) { sLocale = locale; - sLocaleData = LocaleData.get(locale); + sDateFormatSymbols = DateFormat.getIcuDateFormatSymbols(locale); + sDecimalFormatSymbols = DecimalFormatSymbols.getInstance(locale); Resources r = Resources.getSystem(); sTimeOnlyFormat = r.getString(com.android.internal.R.string.time_of_day); @@ -82,10 +85,11 @@ class TimeFormatter { sDateTimeFormat = r.getString(com.android.internal.R.string.date_and_time); } + this.dateFormatSymbols = sDateFormatSymbols; + this.decimalFormatSymbols = sDecimalFormatSymbols; this.dateTimeFormat = sDateTimeFormat; this.timeOnlyFormat = sTimeOnlyFormat; this.dateOnlyFormat = sDateOnlyFormat; - localeData = sLocaleData; } } @@ -167,12 +171,12 @@ class TimeFormatter { } private String localizeDigits(String s) { - if (localeData.zeroDigit == '0') { + if (decimalFormatSymbols.getZeroDigit() == '0') { return s; } int length = s.length(); - int offsetToLocalizedDigits = localeData.zeroDigit - '0'; + int offsetToLocalizedDigits = decimalFormatSymbols.getZeroDigit() - '0'; StringBuilder result = new StringBuilder(length); for (int i = 0; i < length; ++i) { char ch = s.charAt(i); @@ -215,35 +219,44 @@ class TimeFormatter { char currentChar = formatBuffer.get(formatBuffer.position()); switch (currentChar) { case 'A': - modifyAndAppend((wallTime.getWeekDay() < 0 - || wallTime.getWeekDay() >= DAYSPERWEEK) - ? "?" : localeData.longWeekdayNames[wallTime.getWeekDay() + 1], + modifyAndAppend( + (wallTime.getWeekDay() < 0 || wallTime.getWeekDay() >= DAYSPERWEEK) + ? "?" + : dateFormatSymbols.getWeekdays(DateFormatSymbols.FORMAT, + DateFormatSymbols.WIDE)[wallTime.getWeekDay() + 1], modifier); return false; case 'a': - modifyAndAppend((wallTime.getWeekDay() < 0 - || wallTime.getWeekDay() >= DAYSPERWEEK) - ? "?" : localeData.shortWeekdayNames[wallTime.getWeekDay() + 1], + modifyAndAppend( + (wallTime.getWeekDay() < 0 || wallTime.getWeekDay() >= DAYSPERWEEK) + ? "?" + : dateFormatSymbols.getWeekdays(DateFormatSymbols.FORMAT, + DateFormatSymbols.ABBREVIATED)[wallTime.getWeekDay() + 1], modifier); return false; case 'B': if (modifier == '-') { - modifyAndAppend((wallTime.getMonth() < 0 - || wallTime.getMonth() >= MONSPERYEAR) - ? "?" - : localeData.longStandAloneMonthNames[wallTime.getMonth()], + modifyAndAppend( + (wallTime.getMonth() < 0 || wallTime.getMonth() >= MONSPERYEAR) + ? "?" + : dateFormatSymbols.getMonths(DateFormatSymbols.STANDALONE, + DateFormatSymbols.WIDE)[wallTime.getMonth()], modifier); } else { - modifyAndAppend((wallTime.getMonth() < 0 - || wallTime.getMonth() >= MONSPERYEAR) - ? "?" : localeData.longMonthNames[wallTime.getMonth()], + modifyAndAppend( + (wallTime.getMonth() < 0 || wallTime.getMonth() >= MONSPERYEAR) + ? "?" + : dateFormatSymbols.getMonths(DateFormatSymbols.FORMAT, + DateFormatSymbols.WIDE)[wallTime.getMonth()], modifier); } return false; case 'b': case 'h': modifyAndAppend((wallTime.getMonth() < 0 || wallTime.getMonth() >= MONSPERYEAR) - ? "?" : localeData.shortMonthNames[wallTime.getMonth()], + ? "?" + : dateFormatSymbols.getMonths(DateFormatSymbols.FORMAT, + DateFormatSymbols.ABBREVIATED)[wallTime.getMonth()], modifier); return false; case 'C': @@ -310,12 +323,14 @@ class TimeFormatter { outputBuilder.append('\n'); return false; case 'p': - modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1] - : localeData.amPm[0], modifier); + modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) + ? dateFormatSymbols.getAmPmStrings()[1] + : dateFormatSymbols.getAmPmStrings()[0], modifier); return false; case 'P': - modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1] - : localeData.amPm[0], FORCE_LOWER_CASE); + modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) + ? dateFormatSymbols.getAmPmStrings()[1] + : dateFormatSymbols.getAmPmStrings()[0], FORCE_LOWER_CASE); return false; case 'R': formatInternal("%H:%M", wallTime, zoneInfoData); diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java index d40015ee17a8..2b038dd11348 100644 --- a/core/java/android/text/method/NumberKeyListener.java +++ b/core/java/android/text/method/NumberKeyListener.java @@ -29,8 +29,6 @@ import android.text.format.DateFormat; import android.view.KeyEvent; import android.view.View; -import libcore.icu.LocaleData; - import java.util.Collection; import java.util.Locale; @@ -228,7 +226,7 @@ public abstract class NumberKeyListener extends BaseKeyListener if (locale == null) { return false; } - final String[] amPm = LocaleData.get(locale).amPm; + final String[] amPm = DateFormat.getIcuDateFormatSymbols(locale).getAmPmStrings(); for (int i = 0; i < amPm.length; i++) { for (int j = 0; j < amPm[i].length(); j++) { final char ch = amPm[i].charAt(j); diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java index c290dffc42c9..927680bbfab5 100644 --- a/core/java/android/util/proto/ProtoInputStream.java +++ b/core/java/android/util/proto/ProtoInputStream.java @@ -96,7 +96,7 @@ public final class ProtoInputStream extends ProtoStream { private byte mState = 0; /** - * Keeps track of the currently read nested Objects, for end object sanity checking and debug + * Keeps track of the currently read nested Objects, for end object checking and debug */ private ArrayList<Long> mExpectedObjectTokenStack = null; @@ -511,7 +511,7 @@ public final class ProtoInputStream extends ProtoStream { (int) fieldId, getOffset() + messageSize)); } - // Sanity check + // Validation check if (mDepth > 0 && getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth)) > getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth - 1))) { @@ -534,7 +534,7 @@ public final class ProtoInputStream extends ProtoStream { * @param token - token */ public void end(long token) { - // Sanity check to make sure user is keeping track of their embedded messages + // Make sure user is keeping track of their embedded messages if (mExpectedObjectTokenStack.get(mDepth) != token) { throw new ProtoParseException( "end token " + token + " does not match current message token " diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java index 7b24ba997307..f22c64578c8e 100644 --- a/core/java/android/util/proto/ProtoOutputStream.java +++ b/core/java/android/util/proto/ProtoOutputStream.java @@ -59,10 +59,10 @@ import java.io.UnsupportedEncodingException; * cache the size, and then write the size-prefixed buffers. * * We are trying to avoid too much generated code here, but this class still - * needs to have a somewhat sane API. We can't have the multiple passes be - * done by the calling code. In addition, we want to avoid the memory high - * water mark of duplicating all of the values into the traditional in-memory - * Message objects. We need to find another way. + * needs to have API. We can't have the multiple passes be done by the + * calling code. In addition, we want to avoid the memory high water mark + * of duplicating all of the values into the traditional in-memory Message + * objects. We need to find another way. * * So what we do here is to let the calling code write the data into a * byte[] (actually a collection of them wrapped in the EncodedBuffer class), diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 83abf1a33b2d..749e93972602 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -61,7 +61,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } public void onServedEditorChanged(EditorInfo info) { - if (isDummyOrEmptyEditor(info)) { + if (isFallbackOrEmptyEditor(info)) { mShowOnNextImeRender = false; } mFocusedEditor = info; @@ -112,15 +112,15 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { getImm().notifyImeHidden(); } - private boolean isDummyOrEmptyEditor(EditorInfo info) { - // TODO(b/123044812): Handle dummy input gracefully in IME Insets API + private boolean isFallbackOrEmptyEditor(EditorInfo info) { + // TODO(b/123044812): Handle fallback input gracefully in IME Insets API return info == null || (info.fieldId <= 0 && info.inputType <= 0); } private boolean isServedEditorRendered() { if (mFocusedEditor == null || mPreRenderedEditor == null - || isDummyOrEmptyEditor(mFocusedEditor) - || isDummyOrEmptyEditor(mPreRenderedEditor)) { + || isFallbackOrEmptyEditor(mFocusedEditor) + || isFallbackOrEmptyEditor(mPreRenderedEditor)) { // No view is focused or ready. return false; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 40dfcfc391a0..f573598baf1d 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -942,8 +942,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow. - * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface - * instead. + * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead. */ private static boolean sAcceptZeroSizeDragShadow; @@ -22859,7 +22858,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * displaying, else return the result of calling through to the * super class. * - * @return boolean If true than the Drawable is being displayed in the + * @return boolean If true then the Drawable is being displayed in the * view; else false and it is not allowed to animate. * * @see #unscheduleDrawable(android.graphics.drawable.Drawable) @@ -29334,7 +29333,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Dump all private flags in readable format, useful for documentation and - * sanity checking. + * consistency checking. */ private static void dumpFlags() { final HashMap<String, String> found = Maps.newHashMap(); diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 090e19f91e38..a211a1a3d197 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -54,7 +54,7 @@ public class BaseInputConnection implements InputConnection { /** @hide */ protected final InputMethodManager mIMM; final View mTargetView; - final boolean mDummyMode; + final boolean mFallbackMode; private Object[] mDefaultComposingSpans; @@ -64,14 +64,14 @@ public class BaseInputConnection implements InputConnection { BaseInputConnection(InputMethodManager mgr, boolean fullEditor) { mIMM = mgr; mTargetView = null; - mDummyMode = !fullEditor; + mFallbackMode = !fullEditor; } public BaseInputConnection(View targetView, boolean fullEditor) { mIMM = (InputMethodManager)targetView.getContext().getSystemService( Context.INPUT_METHOD_SERVICE); mTargetView = targetView; - mDummyMode = !fullEditor; + mFallbackMode = !fullEditor; } public static final void removeComposingSpans(Spannable text) { @@ -189,7 +189,7 @@ public class BaseInputConnection implements InputConnection { /** * Default implementation replaces any existing composing text with - * the given text. In addition, only if dummy mode, a key event is + * the given text. In addition, only if fallback mode, a key event is * sent for the new text and the current editable buffer cleared. */ public boolean commitText(CharSequence text, int newCursorPosition) { @@ -428,7 +428,7 @@ public class BaseInputConnection implements InputConnection { /** * The default implementation removes the composing state from the - * current editable text. In addition, only if dummy mode, a key event is + * current editable text. In addition, only if fallback mode, a key event is * sent for the new text and the current editable buffer cleared. */ public boolean finishComposingText() { @@ -437,7 +437,7 @@ public class BaseInputConnection implements InputConnection { if (content != null) { beginBatchEdit(); removeComposingSpans(content); - // Note: sendCurrentText does nothing unless mDummyMode is set + // Note: sendCurrentText does nothing unless mFallbackMode is set sendCurrentText(); endBatchEdit(); } @@ -447,10 +447,10 @@ public class BaseInputConnection implements InputConnection { /** * The default implementation uses TextUtils.getCapsMode to get the * cursor caps mode for the current selection position in the editable - * text, unless in dummy mode in which case 0 is always returned. + * text, unless in fallback mode in which case 0 is always returned. */ public int getCursorCapsMode(int reqModes) { - if (mDummyMode) return 0; + if (mFallbackMode) return 0; final Editable content = getEditable(); if (content == null) return 0; @@ -647,7 +647,7 @@ public class BaseInputConnection implements InputConnection { content.setSpan(COMPOSING, a, b, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING); - // Note: sendCurrentText does nothing unless mDummyMode is set + // Note: sendCurrentText does nothing unless mFallbackMode is set sendCurrentText(); endBatchEdit(); } @@ -698,7 +698,7 @@ public class BaseInputConnection implements InputConnection { } private void sendCurrentText() { - if (!mDummyMode) { + if (!mFallbackMode) { return; } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 271d5be3864e..94bf4b134003 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1497,7 +1497,7 @@ public class WebView extends AbsoluteLayout * * @param hosts the list of hosts * @param callback will be called with {@code true} if hosts are successfully added to the - * whitelist. It will be called with {@code false} if any hosts are malformed. The callback + * allowlist. It will be called with {@code false} if any hosts are malformed. The callback * will be run on the UI thread */ public static void setSafeBrowsingWhitelist(@NonNull List<String> hosts, diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 150fa88a36e3..7b6e1a370479 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -173,8 +173,9 @@ public class WebViewClient { * when accessing private data or the view system. * * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe - * Browsing checks. If this is undesired, whitelist the URL with {@link - * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}. + * Browsing checks. If this is undesired, you can use {@link WebView#setSafeBrowsingWhitelist} + * to skip Safe Browsing checks for that host or dismiss the warning in {@link + * #onSafeBrowsingHit} by calling {@link SafeBrowsingResponse#proceed}. * * @param view The {@link android.webkit.WebView} that is requesting the * resource. @@ -211,8 +212,9 @@ public class WebViewClient { * when accessing private data or the view system. * * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe - * Browsing checks. If this is undesired, whitelist the URL with {@link - * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}. + * Browsing checks. If this is undesired, you can use {@link WebView#setSafeBrowsingWhitelist} + * to skip Safe Browsing checks for that host or dismiss the warning in {@link + * #onSafeBrowsingHit} by calling {@link SafeBrowsingResponse#proceed}. * * @param view The {@link android.webkit.WebView} that is requesting the * resource. diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java index 1b899dbf6d03..33e64f4d37e9 100644 --- a/core/java/android/widget/CalendarViewLegacyDelegate.java +++ b/core/java/android/widget/CalendarViewLegacyDelegate.java @@ -38,8 +38,6 @@ import android.view.ViewGroup; import com.android.internal.R; -import libcore.icu.LocaleData; - import java.util.Locale; /** @@ -264,7 +262,7 @@ class CalendarViewLegacyDelegate extends CalendarView.AbstractCalendarViewDelega mShowWeekNumber = a.getBoolean(R.styleable.CalendarView_showWeekNumber, DEFAULT_SHOW_WEEK_NUMBER); mFirstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek, - LocaleData.get(Locale.getDefault()).firstDayOfWeek); + Calendar.getInstance().getFirstDayOfWeek()); final String minDate = a.getString(R.styleable.CalendarView_minDate); if (!CalendarView.parseDate(minDate, mMinDate)) { CalendarView.parseDate(DEFAULT_MIN_DATE, mMinDate); diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index 67fef13d23f2..7de2bd10482f 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -33,10 +33,6 @@ import com.android.internal.R; import com.android.internal.widget.ViewPager; import com.android.internal.widget.ViewPager.OnPageChangeListener; -import libcore.icu.LocaleData; - -import java.util.Locale; - class DayPickerView extends ViewGroup { private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material; private static final int DEFAULT_START_YEAR = 1900; @@ -86,7 +82,7 @@ class DayPickerView extends ViewGroup { attrs, a, defStyleAttr, defStyleRes); final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek, - LocaleData.get(Locale.getDefault()).firstDayOfWeek); + Calendar.getInstance().getFirstDayOfWeek()); final String minDate = a.getString(R.styleable.CalendarView_minDate); final String maxDate = a.getString(R.styleable.CalendarView_maxDate); diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index bfda7a71dea9..3a86adee610b 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -918,7 +918,7 @@ public final class Magnifier { bitmapRenderNode.setOutline(outline); bitmapRenderNode.setClipToOutline(true); - // Create a dummy draw, which will be replaced later with real drawing. + // Create a placeholder draw, which will be replaced later with real drawing. final RecordingCanvas canvas = bitmapRenderNode.beginRecording( mContentWidth, mContentHeight); try { diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index e4a34b943657..68ac2f684ef0 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -34,6 +34,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.icu.text.DecimalFormatSymbols; import android.os.Build; import android.os.Bundle; import android.text.InputFilter; @@ -61,8 +62,6 @@ import android.view.inputmethod.InputMethodManager; import com.android.internal.R; -import libcore.icu.LocaleData; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -209,7 +208,7 @@ public class NumberPicker extends LinearLayout { } private static char getZeroDigit(Locale locale) { - return LocaleData.get(locale).zeroDigit; + return DecimalFormatSymbols.getInstance(locale).getZeroDigit(); } private java.util.Formatter createFormatter(Locale locale) { diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 80de6fc65f90..8b74add8df0a 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -27,6 +27,7 @@ import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.Rect; import android.graphics.Typeface; +import android.icu.text.DateFormatSymbols; import android.icu.text.DisplayContext; import android.icu.text.SimpleDateFormat; import android.icu.util.Calendar; @@ -49,8 +50,6 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import com.android.internal.R; import com.android.internal.widget.ExploreByTouchHelper; -import libcore.icu.LocaleData; - import java.text.NumberFormat; import java.util.Locale; @@ -193,7 +192,8 @@ class SimpleMonthView extends View { private void updateDayOfWeekLabels() { // Use tiny (e.g. single-character) weekday names from ICU. The indices // for this list correspond to Calendar days, e.g. SUNDAY is index 1. - final String[] tinyWeekdayNames = LocaleData.get(mLocale).tinyWeekdayNames; + final String[] tinyWeekdayNames = DateFormatSymbols.getInstance(mLocale) + .getWeekdays(DateFormatSymbols.FORMAT, DateFormatSymbols.NARROW); for (int i = 0; i < DAYS_IN_WEEK; i++) { mDayOfWeekLabels[i] = tinyWeekdayNames[(mWeekStart + i - 1) % DAYS_IN_WEEK + 1]; } diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java index 88a67625d615..7804fd1f9f3c 100644 --- a/core/java/android/widget/TextClock.java +++ b/core/java/android/widget/TextClock.java @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.TypedArray; import android.database.ContentObserver; +import android.icu.text.DateTimePatternGenerator; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; @@ -43,8 +44,6 @@ import android.view.inspector.InspectableProperty; import com.android.internal.R; -import libcore.icu.LocaleData; - import java.util.Calendar; import java.util.TimeZone; @@ -259,14 +258,11 @@ public class TextClock extends TextView { } private void init() { - if (mFormat12 == null || mFormat24 == null) { - LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale); - if (mFormat12 == null) { - mFormat12 = ld.timeFormat_hm; - } - if (mFormat24 == null) { - mFormat24 = ld.timeFormat_Hm; - } + if (mFormat12 == null) { + mFormat12 = getBestDateTimePattern("hm"); + } + if (mFormat24 == null) { + mFormat24 = getBestDateTimePattern("Hm"); } createTime(mTimeZone); @@ -508,13 +504,11 @@ public class TextClock extends TextView { private void chooseFormat() { final boolean format24Requested = is24HourModeEnabled(); - LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale); - if (format24Requested) { - mFormat = abc(mFormat24, mFormat12, ld.timeFormat_Hm); + mFormat = abc(mFormat24, mFormat12, getBestDateTimePattern("Hm")); mDescFormat = abc(mDescFormat24, mDescFormat12, mFormat); } else { - mFormat = abc(mFormat12, mFormat24, ld.timeFormat_hm); + mFormat = abc(mFormat12, mFormat24, getBestDateTimePattern("hm")); mDescFormat = abc(mDescFormat12, mDescFormat24, mFormat); } @@ -527,6 +521,12 @@ public class TextClock extends TextView { } } + private String getBestDateTimePattern(String skeleton) { + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance( + getContext().getResources().getConfiguration().locale); + return dtpg.getBestPattern(skeleton); + } + /** * Returns a if not null, else return b if not null, else return c. */ diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index 51b18473f1ac..1c219eb95479 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -24,9 +24,11 @@ import android.annotation.Widget; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; +import android.icu.text.DateFormatSymbols; import android.icu.util.Calendar; import android.os.Parcel; import android.os.Parcelable; +import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.Log; import android.util.MathUtils; @@ -39,8 +41,6 @@ import android.view.inspector.InspectableProperty; import com.android.internal.R; -import libcore.icu.LocaleData; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Locale; @@ -421,11 +421,13 @@ public class TimePicker extends FrameLayout { static String[] getAmPmStrings(Context context) { final Locale locale = context.getResources().getConfiguration().locale; - final LocaleData d = LocaleData.get(locale); + DateFormatSymbols dfs = DateFormat.getIcuDateFormatSymbols(locale); + String[] amPm = dfs.getAmPmStrings(); + String[] narrowAmPm = dfs.getAmpmNarrowStrings(); final String[] result = new String[2]; - result[0] = d.amPm[0].length() > 4 ? d.narrowAm : d.amPm[0]; - result[1] = d.amPm[1].length() > 4 ? d.narrowPm : d.amPm[1]; + result[0] = amPm[0].length() > 4 ? narrowAmPm[0] : amPm[0]; + result[1] = amPm[1].length() > 4 ? narrowAmPm[1] : amPm[1]; return result; } diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java index 83c86d5ce36b..bd2fa5965bc9 100644 --- a/core/java/android/widget/TimePickerSpinnerDelegate.java +++ b/core/java/android/widget/TimePickerSpinnerDelegate.java @@ -35,8 +35,6 @@ import android.view.inputmethod.InputMethodManager; import com.android.internal.R; -import libcore.icu.LocaleData; - import java.util.Calendar; /** @@ -143,7 +141,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); // Get the localized am/pm strings and use them in the spinner. - mAmPmStrings = getAmPmStrings(context); + mAmPmStrings = TimePicker.getAmPmStrings(context); // am/pm final View amPmView = mDelegator.findViewById(R.id.amPm); @@ -574,12 +572,4 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { target.setContentDescription(mContext.getString(contDescResId)); } } - - public static String[] getAmPmStrings(Context context) { - String[] result = new String[2]; - LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); - result[0] = d.amPm[0].length() > 4 ? d.narrowAm : d.amPm[0]; - result[1] = d.amPm[1].length() > 4 ? d.narrowPm : d.amPm[1]; - return result; - } } diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java index 3343593f2bc3..0c43578a89cf 100644 --- a/core/java/com/android/internal/app/LocalePicker.java +++ b/core/java/com/android/internal/app/LocalePicker.java @@ -16,6 +16,8 @@ package com.android.internal.app; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.ListFragment; @@ -28,6 +30,7 @@ import android.os.Bundle; import android.os.LocaleList; import android.os.RemoteException; import android.provider.Settings; +import android.sysprop.LocalizationProperties; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -43,6 +46,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; public class LocalePicker extends ListFragment { private static final String TAG = "LocalePicker"; @@ -92,7 +98,38 @@ public class LocalePicker extends ListFragment { } public static String[] getSupportedLocales(Context context) { - return context.getResources().getStringArray(R.array.supported_locales); + String[] allLocales = context.getResources().getStringArray(R.array.supported_locales); + + Predicate<String> localeFilter = getLocaleFilter(); + if (localeFilter == null) { + return allLocales; + } + + List<String> result = new ArrayList<>(allLocales.length); + for (String locale : allLocales) { + if (localeFilter.test(locale)) { + result.add(locale); + } + } + + int localeCount = result.size(); + return (localeCount == allLocales.length) ? allLocales + : result.toArray(new String[localeCount]); + } + + @Nullable + private static Predicate<String> getLocaleFilter() { + try { + return LocalizationProperties.locale_filter() + .map(filter -> Pattern.compile(filter).asPredicate()) + .orElse(null); + } catch (SecurityException e) { + Log.e(TAG, "Failed to read locale filter.", e); + } catch (PatternSyntaxException e) { + Log.e(TAG, "Bad locale filter format (\"" + e.getPattern() + "\"), skipping."); + } + + return null; } public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) { @@ -265,6 +302,11 @@ public class LocalePicker extends ListFragment { */ @UnsupportedAppUsage public static void updateLocales(LocaleList locales) { + if (locales != null) { + locales = removeExcludedLocales(locales); + } + // Note: the empty list case is covered by Configuration.setLocales(). + try { final IActivityManager am = ActivityManager.getService(); final Configuration config = am.getConfiguration(); @@ -280,6 +322,26 @@ public class LocalePicker extends ListFragment { } } + @NonNull + private static LocaleList removeExcludedLocales(@NonNull LocaleList locales) { + Predicate<String> localeFilter = getLocaleFilter(); + if (localeFilter == null) { + return locales; + } + + int localeCount = locales.size(); + ArrayList<Locale> filteredLocales = new ArrayList<>(localeCount); + for (int i = 0; i < localeCount; ++i) { + Locale locale = locales.get(i); + if (localeFilter.test(locale.toString())) { + filteredLocales.add(locale); + } + } + + return (localeCount == filteredLocales.size()) ? locales + : new LocaleList(filteredLocales.toArray(new Locale[0])); + } + /** * Get the locale list. * diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java index 1f816c18f886..749ff84358d9 100644 --- a/core/java/com/android/internal/os/ChildZygoteInit.java +++ b/core/java/com/android/internal/os/ChildZygoteInit.java @@ -116,7 +116,7 @@ public class ChildZygoteInit { try { server.registerServerSocketAtAbstractName(socketName); - // Add the abstract socket to the FD whitelist so that the native zygote code + // Add the abstract socket to the FD allow list so that the native zygote code // can properly detach it after forking. Zygote.nativeAllowFileAcrossFork("ABSTRACT/" + socketName); diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java index a18943c264f5..8f36de1d9661 100644 --- a/core/java/com/android/internal/os/ClassLoaderFactory.java +++ b/core/java/com/android/internal/os/ClassLoaderFactory.java @@ -116,13 +116,17 @@ public class ClassLoaderFactory { final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent, classLoaderName, sharedLibraries); + // TODO(b/142191088) merge 6a5b8b1f6db172b5aaadcec0c3868e54e214b675 + String sonameList = "ALL"; + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace"); String errorMessage = createClassloaderNamespace(classLoader, targetSdkVersion, librarySearchPath, libraryPermittedPath, isNamespaceShared, - dexPath); + dexPath, + sonameList); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (errorMessage != null) { @@ -139,5 +143,6 @@ public class ClassLoaderFactory { String librarySearchPath, String libraryPermittedPath, boolean isNamespaceShared, - String dexPath); + String dexPath, + String sonameList); } diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS index 928310549e6e..afc94329dc4d 100644 --- a/core/java/com/android/internal/os/OWNERS +++ b/core/java/com/android/internal/os/OWNERS @@ -1 +1 @@ -per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com +per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 2a29dfb71e6c..faed79f29eeb 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -743,9 +743,9 @@ public final class Zygote { throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-app"); } else if (args.mStartChildZygote) { throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--start-child-zygote"); - } else if (args.mApiBlacklistExemptions != null) { + } else if (args.mApiDenylistExemptions != null) { throw new IllegalArgumentException( - USAP_ERROR_PREFIX + "--set-api-blacklist-exemptions"); + USAP_ERROR_PREFIX + "--set-api-denylist-exemptions"); } else if (args.mHiddenApiAccessLogSampleRate != -1) { throw new IllegalArgumentException( USAP_ERROR_PREFIX + "--hidden-api-log-sampling-rate="); diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java index 4442cf0c8208..1fb4f693a1b0 100644 --- a/core/java/com/android/internal/os/ZygoteArguments.java +++ b/core/java/com/android/internal/os/ZygoteArguments.java @@ -192,10 +192,10 @@ class ZygoteArguments { boolean mBootCompleted; /** - * Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, or - * when they change, via --set-api-blacklist-exemptions. + * Exemptions from API deny-listing. These are sent to the pre-forked zygote at boot time, or + * when they change, via --set-api-denylist-exemptions. */ - String[] mApiBlacklistExemptions; + String[] mApiDenylistExemptions; /** * Sampling rate for logging hidden API accesses to the event log. This is sent to the @@ -394,10 +394,10 @@ class ZygoteArguments { expectRuntimeArgs = false; } else if (arg.equals("--start-child-zygote")) { mStartChildZygote = true; - } else if (arg.equals("--set-api-blacklist-exemptions")) { + } else if (arg.equals("--set-api-denylist-exemptions")) { // consume all remaining args; this is a stand-alone command, never included // with the regular fork command. - mApiBlacklistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length); + mApiDenylistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length); curArg = args.length; expectRuntimeArgs = false; } else if (arg.startsWith("--hidden-api-log-sampling-rate=")) { diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 8f1f4cc1077c..ab064824626d 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -185,8 +185,8 @@ class ZygoteConnection { return null; } - if (parsedArgs.mApiBlacklistExemptions != null) { - return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions); + if (parsedArgs.mApiDenylistExemptions != null) { + return handleApiDenylistExemptions(zygoteServer, parsedArgs.mApiDenylistExemptions); } if (parsedArgs.mHiddenApiAccessLogSampleRate != -1 @@ -365,11 +365,11 @@ class ZygoteConnection { } /** - * Makes the necessary changes to implement a new API blacklist exemption policy, and then + * Makes the necessary changes to implement a new API deny list exemption policy, and then * responds to the system server, letting it know that the task has been completed. * * This necessitates a change to the internal state of the Zygote. As such, if the USAP - * pool is enabled all existing USAPs have an incorrect API blacklist exemption list. To + * pool is enabled all existing USAPs have an incorrect API deny list exemption list. To * properly handle this request the pool must be emptied and refilled. This process can return * a Runnable object that must be returned to ZygoteServer.runSelectLoop to be invoked. * @@ -378,9 +378,9 @@ class ZygoteConnection { * @return A Runnable object representing a new app in any USAPs spawned from here; the * zygote process will always receive a null value from this function. */ - private Runnable handleApiBlacklistExemptions(ZygoteServer zygoteServer, String[] exemptions) { + private Runnable handleApiDenylistExemptions(ZygoteServer zygoteServer, String[] exemptions) { return stateChangeWithUsapPoolReset(zygoteServer, - () -> ZygoteInit.setApiBlacklistExemptions(exemptions)); + () -> ZygoteInit.setApiDenylistExemptions(exemptions)); } private Runnable handleUsapPoolStatusChange(ZygoteServer zygoteServer, boolean newStatus) { diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 2e152123c94c..ee95087caf70 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -580,7 +580,7 @@ public class ZygoteInit { VMRuntime.registerAppInfo(profilePath, codePaths); } - public static void setApiBlacklistExemptions(String[] exemptions) { + public static void setApiDenylistExemptions(String[] exemptions) { VMRuntime.getRuntime().setHiddenApiExemptions(exemptions); } diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java index 8d281b7ce9a0..8c81984064d0 100644 --- a/core/java/com/android/internal/os/ZygoteServer.java +++ b/core/java/com/android/internal/os/ZygoteServer.java @@ -451,7 +451,7 @@ class ZygoteServer { * For reasons of correctness the USAP pool pipe and event FDs * must be processed before the session and server sockets. This * is to ensure that the USAP pool accounting information is - * accurate when handling other requests like API blacklist + * accurate when handling other requests like API deny list * exemptions. */ diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 7ff15f2e182d..c5d39823162f 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -6,4 +6,4 @@ per-file *Camera*,*camera* = shuzhenwang@google.com, yinchiayeh@google.com, zhij per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com # Zygote -per-file com_android_internal_os_Zygote.*,fd_utils.* = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com +per-file com_android_internal_os_Zygote.*,fd_utils.* = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp index 1efff7f8b0fb..c4c896e0a8b5 100644 --- a/core/jni/android_database_SQLiteConnection.cpp +++ b/core/jni/android_database_SQLiteConnection.cpp @@ -210,7 +210,8 @@ static void sqliteCustomFunctionCallback(sqlite3_context *context, // Get the callback function object. // Create a new local reference to it in case the callback tries to do something - // dumb like unregister the function (thereby destroying the global ref) while it is running. + // unexpected like unregister the function (thereby destroying the global ref) + // while it is running. jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); jobject functionObj = env->NewLocalRef(functionObjGlobal); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 541b937860c3..8411ecaef799 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -936,7 +936,7 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env, if (jHandle == NULL) { return (jint)AUDIO_JAVA_ERROR; } - // create dummy port and port config objects with just the correct handle + // create placeholder port and port config objects with just the correct handle // and configuration data. The actual AudioPortConfig objects will be // constructed by java code with correct class type (device, mix etc...) // and reference to AudioPort instance in this client diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index e56809f66dc7..7d6135bda9c6 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -93,9 +93,10 @@ static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) { - int dummy = 0; + int optval_ignored = 0; int fd = jniGetFDFromFileDescriptor(env, javaFd); - if (setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)) != 0) { + if (setsockopt( + fd, SOL_SOCKET, SO_DETACH_FILTER, &optval_ignored, sizeof(optval_ignored)) != 0) { jniThrowExceptionFmt(env, "java/net/SocketException", "setsockopt(SO_DETACH_FILTER): %s", strerror(errno)); } diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index cd3611546852..a96ea7b692ab 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -846,8 +846,10 @@ static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz) } cfg_state = CONFIG_UNKNOWN; if (cfg_state == CONFIG_UNKNOWN) { - const std::map<std::string, std::string> configs = - vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs(); + auto runtime_info = vintf::VintfObject::GetInstance()->getRuntimeInfo( + vintf::RuntimeInfo::FetchFlag::CONFIG_GZ); + CHECK(runtime_info != nullptr) << "Kernel configs cannot be fetched. b/151092221"; + const std::map<std::string, std::string>& configs = runtime_info->kernelConfigs(); std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK"); cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET; } @@ -911,7 +913,7 @@ int register_android_os_Debug(JNIEnv *env) { jclass clazz = env->FindClass("android/os/Debug$MemoryInfo"); - // Sanity check the number of other statistics expected in Java matches here. + // Check the number of other statistics expected in Java matches here. jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I"); jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field); jfieldID numDvkStats_field = env->GetStaticFieldID(clazz, "NUM_DVK_STATS", "I"); diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 7247ee068334..40a3eced91b1 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -328,7 +328,7 @@ static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, j if (parcel != NULL) { int32_t len = parcel->readInt32(); - // sanity check the stored length against the true data size + // Validate the stored length against the true data size if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { ret = env->NewByteArray(len); diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp index 9379ea6dcd10..b0271b9e92af 100644 --- a/core/jni/android_os_VintfRuntimeInfo.cpp +++ b/core/jni/android_os_VintfRuntimeInfo.cpp @@ -29,14 +29,12 @@ namespace android { using vintf::RuntimeInfo; using vintf::VintfObject; -#define MAP_STRING_METHOD(javaMethod, cppString, flags) \ - static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) \ - { \ - std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo( \ - false /* skipCache */, flags); \ - if (info == nullptr) return nullptr; \ - return env->NewStringUTF((cppString).c_str()); \ - } \ +#define MAP_STRING_METHOD(javaMethod, cppString, flags) \ + static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) { \ + std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(flags); \ + if (info == nullptr) return nullptr; \ + return env->NewStringUTF((cppString).c_str()); \ + } MAP_STRING_METHOD(getCpuInfo, info->cpuInfo(), RuntimeInfo::FetchFlag::CPU_INFO); MAP_STRING_METHOD(getOsName, info->osName(), RuntimeInfo::FetchFlag::CPU_VERSION); @@ -54,8 +52,8 @@ MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbV static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz) { - std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo( - false /* skipCache */, RuntimeInfo::FetchFlag::POLICYVERS); + std::shared_ptr<const RuntimeInfo> info = + VintfObject::GetRuntimeInfo(RuntimeInfo::FetchFlag::POLICYVERS); if (info == nullptr) return 0; return static_cast<jlong>(info->kernelSepolicyVersion()); } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 1da022c11420..16367ae759e7 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -957,7 +957,7 @@ static jlong android_os_Binder_clearCallingIdentity() static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) { - // XXX temporary sanity check to debug crashes. + // XXX temporary validation check to debug crashes. int uid = (int)(token>>32); if (uid > 0 && uid < 999) { // In Android currently there are no uids in this range. diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp index 24c3ff80badd..70a9be740810 100644 --- a/core/jni/android_view_InputQueue.cpp +++ b/core/jni/android_view_InputQueue.cpp @@ -176,8 +176,8 @@ void InputQueue::enqueueEvent(InputEvent* event) { Mutex::Autolock _l(mLock); mPendingEvents.push(event); if (mPendingEvents.size() == 1) { - char dummy = 0; - int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &dummy, sizeof(dummy))); + char payload = '\0'; + int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &payload, sizeof(payload))); if (res < 0 && errno != EAGAIN) { ALOGW("Failed writing to dispatch fd: %s", strerror(errno)); } diff --git a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp index f8d41e4bef54..59c413ff58a6 100644 --- a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp +++ b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp @@ -28,16 +28,19 @@ static jstring createClassloaderNamespace_native(JNIEnv* env, jstring librarySearchPath, jstring libraryPermittedPath, jboolean isShared, - jstring dexPath) { + jstring dexPath, + jstring sonameList) { return android::CreateClassLoaderNamespace(env, targetSdkVersion, classLoader, isShared == JNI_TRUE, dexPath, - librarySearchPath, libraryPermittedPath); + librarySearchPath, + libraryPermittedPath, + sonameList); } static const JNINativeMethod g_methods[] = { { "createClassloaderNamespace", - "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;", + "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", reinterpret_cast<void*>(createClassloaderNamespace_native) }, }; diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index fbb35e055e16..b3c76f860cd2 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -507,8 +507,16 @@ static void UnsetChldSignalHandler() { // Calls POSIX setgroups() using the int[] object as an argument. // A nullptr argument is tolerated. -static void SetGids(JNIEnv* env, jintArray managed_gids, fail_fn_t fail_fn) { +static void SetGids(JNIEnv* env, jintArray managed_gids, jboolean is_child_zygote, + fail_fn_t fail_fn) { if (managed_gids == nullptr) { + if (is_child_zygote) { + // For child zygotes like webview and app zygote, we want to clear out + // any supplemental groups the parent zygote had. + if (setgroups(0, NULL) == -1) { + fail_fn(CREATE_ERROR("Failed to remove supplementary groups for child zygote")); + } + } return; } @@ -1163,7 +1171,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, } } - SetGids(env, gids, fail_fn); + SetGids(env, gids, is_child_zygote, fail_fn); SetRLimits(env, rlimits, fail_fn); if (need_pre_initialize_native_bridge) { diff --git a/core/res/res/values-mcc310-mnc030/config.xml b/core/res/res/values-mcc310-mnc030/config.xml deleted file mode 100644 index 26b9192e0cc3..000000000000 --- a/core/res/res/values-mcc310-mnc030/config.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2019, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/core/res/res/values-mcc310-mnc070/config.xml b/core/res/res/values-mcc310-mnc070/config.xml deleted file mode 100644 index 26b9192e0cc3..000000000000 --- a/core/res/res/values-mcc310-mnc070/config.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2019, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/core/res/res/values-mcc310-mnc170/config.xml b/core/res/res/values-mcc310-mnc170/config.xml index 12e448cd6b21..f6cddc9bb2a3 100644 --- a/core/res/res/values-mcc310-mnc170/config.xml +++ b/core/res/res/values-mcc310-mnc170/config.xml @@ -20,9 +20,6 @@ <!-- These resources are around just to allow their values to be customized for different hardware and product builds. --> <resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - <!-- 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">true</bool> diff --git a/core/res/res/values-mcc310-mnc280/config.xml b/core/res/res/values-mcc310-mnc280/config.xml deleted file mode 100644 index 26b9192e0cc3..000000000000 --- a/core/res/res/values-mcc310-mnc280/config.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2019, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/core/res/res/values-mcc310-mnc380/config.xml b/core/res/res/values-mcc310-mnc380/config.xml index 12e448cd6b21..f6cddc9bb2a3 100644 --- a/core/res/res/values-mcc310-mnc380/config.xml +++ b/core/res/res/values-mcc310-mnc380/config.xml @@ -20,9 +20,6 @@ <!-- These resources are around just to allow their values to be customized for different hardware and product builds. --> <resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - <!-- 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">true</bool> diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml index 22b8fefcecf4..6943bd443cdc 100644 --- a/core/res/res/values-mcc310-mnc410/config.xml +++ b/core/res/res/values-mcc310-mnc410/config.xml @@ -49,9 +49,6 @@ <item>"#9"</item> </string-array> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - <!-- 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">true</bool> diff --git a/core/res/res/values-mcc310-mnc560/config.xml b/core/res/res/values-mcc310-mnc560/config.xml index 12e448cd6b21..f6cddc9bb2a3 100644 --- a/core/res/res/values-mcc310-mnc560/config.xml +++ b/core/res/res/values-mcc310-mnc560/config.xml @@ -20,9 +20,6 @@ <!-- These resources are around just to allow their values to be customized for different hardware and product builds. --> <resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - <!-- 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">true</bool> diff --git a/core/res/res/values-mcc310-mnc950/config.xml b/core/res/res/values-mcc310-mnc950/config.xml deleted file mode 100644 index 26b9192e0cc3..000000000000 --- a/core/res/res/values-mcc310-mnc950/config.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2019, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/core/res/res/values-mcc311-mnc180/config.xml b/core/res/res/values-mcc311-mnc180/config.xml index 12e448cd6b21..f6cddc9bb2a3 100644 --- a/core/res/res/values-mcc311-mnc180/config.xml +++ b/core/res/res/values-mcc311-mnc180/config.xml @@ -20,9 +20,6 @@ <!-- These resources are around just to allow their values to be customized for different hardware and product builds. --> <resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - <!-- 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">true</bool> diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml index 336e30e45b00..db2f8d01f93a 100755 --- a/core/res/res/values-mcc311-mnc480/config.xml +++ b/core/res/res/values-mcc311-mnc480/config.xml @@ -40,7 +40,4 @@ <bool name="config_use_sim_language_file">true</bool> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> - </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 3d73ade33d5b..c7c3ea798bb5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1230,7 +1230,7 @@ with the modem or some other restricted hardware, add "/dev/bus/usb/001/" to this list. If this is empty, no parts of the host USB bus will be excluded. --> - <string-array name="config_usbHostBlacklist" translatable="false"> + <string-array name="config_usbHostDenylist" translatable="false"> </string-array> <!-- List of paths to serial ports that are available to the serial manager. @@ -2954,6 +2954,9 @@ eutran : eutranSupportedRelease nfc : contactlessSupportedRelease crl : rspCrlSupportedVersion + nrepc : nrEpcSupportedRelease + nr5gc : nr5gcSupportedRelease + eutran5gc : eutran5gcSupportedRelease --> <string-array translatable="false" name="config_telephonyEuiccDeviceCapabilities"> <!-- Example: @@ -2965,6 +2968,9 @@ <item>"eutran,11"</item> <item>"nfc,1"</item> <item>"crl,1"</item> + <item>"nrepc,15"</item> + <item>"nr5gc,15"</item> + <item>"eutran5gc,15"</item> --> </string-array> @@ -4345,10 +4351,6 @@ only. The component must be part of a system app. --> <string name="config_defaultSupervisionProfileOwnerComponent" translatable="false"></string> - <!-- Whether to artificially interpret all signal strengths as - one bar higher than they actually are --> - <bool name="config_inflateSignalStrength">false</bool> - <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission grants, even if the UICC claims that the app should be privileged. See b/138150105 --> <string-array name="config_restrictedPreinstalledCarrierApps" translatable="false"/> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index ece65ff21487..7bd18c3a0e32 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1919,8 +1919,7 @@ <java-symbol type="bool" name="config_tether_upstream_automatic" /> <java-symbol type="array" name="config_tether_usb_regexs" /> <java-symbol type="array" name="config_tether_wifi_regexs" /> - <java-symbol type="array" name="config_tether_wifi_p2p_regexs" /> - <java-symbol type="array" name="config_usbHostBlacklist" /> + <java-symbol type="array" name="config_usbHostDenylist" /> <java-symbol type="array" name="config_serialPorts" /> <java-symbol type="array" name="radioAttributes" /> <java-symbol type="array" name="config_oemUsbModeOverride" /> @@ -3861,7 +3860,6 @@ <java-symbol type="color" name="decor_view_status_guard_light" /> <java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" /> - <java-symbol type="bool" name="config_inflateSignalStrength" /> <java-symbol type="array" name="config_restrictedPreinstalledCarrierApps" /> <java-symbol type="array" name="config_highRefreshRateBlacklist" /> diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml index d8ec72f33ddc..166edca3d046 100644 --- a/core/res/res/xml/power_profile.xml +++ b/core/res/res/xml/power_profile.xml @@ -20,7 +20,7 @@ <device name="Android"> <!-- Most values are the incremental current used by a feature, in mA (measured at nominal voltage). - The default values are deliberately incorrect dummy values. + The default values are deliberately incorrect values. OEM's must measure and provide actual values before shipping a device. Example real-world values are given in comments, but they diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp new file mode 100644 index 000000000000..7f20a0ba6642 --- /dev/null +++ b/core/sysprop/Android.bp @@ -0,0 +1,21 @@ +// 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. + +sysprop_library { + name: "com.android.sysprop.localization", + srcs: ["LocalizationProperties.sysprop"], + property_owner: "Platform", + api_packages: ["android.sysprop"], + vendor_available: false, +} diff --git a/core/sysprop/LocalizationProperties.sysprop b/core/sysprop/LocalizationProperties.sysprop new file mode 100644 index 000000000000..65f544fa6179 --- /dev/null +++ b/core/sysprop/LocalizationProperties.sysprop @@ -0,0 +1,24 @@ +# 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. + +module: "android.sysprop.LocalizationProperties" +owner: Platform + +prop { + api_name: "locale_filter" + type: String + prop_name: "ro.localization.locale_filter" + scope: Internal + access: Readonly +} diff --git a/core/sysprop/api/com.android.sysprop.localization-current.txt b/core/sysprop/api/com.android.sysprop.localization-current.txt new file mode 100644 index 000000000000..fe4f4578683c --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.localization-current.txt @@ -0,0 +1,9 @@ +props { + module: "android.sysprop.LocalizationProperties" + prop { + api_name: "locale_filter" + type: String + scope: Internal + prop_name: "ro.localization.locale_filter" + } +} diff --git a/core/sysprop/api/com.android.sysprop.localization-latest.txt b/core/sysprop/api/com.android.sysprop.localization-latest.txt new file mode 100644 index 000000000000..fe4f4578683c --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.localization-latest.txt @@ -0,0 +1,9 @@ +props { + module: "android.sysprop.LocalizationProperties" + prop { + api_name: "locale_filter" + type: String + scope: Internal + prop_name: "ro.localization.locale_filter" + } +} diff --git a/core/tests/coretests/apks/install/res/values/strings.xml b/core/tests/coretests/apks/install/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install/res/values/strings.xml +++ b/core/tests/coretests/apks/install/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml +++ b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml b/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml +++ b/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml +++ b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml +++ b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml +++ b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml +++ b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml b/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml +++ b/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml +++ b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml +++ b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml +++ b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/keyset/res/values/strings.xml b/core/tests/coretests/apks/keyset/res/values/strings.xml index ff99ffa77b2a..d811ec29ef19 100644 --- a/core/tests/coretests/apks/keyset/res/values/strings.xml +++ b/core/tests/coretests/apks/keyset/res/values/strings.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> <string name="keyset_perm_desc">keyset_perm_description</string> <string name="keyset_perm_label">keyset_perm_label</string> </resources> diff --git a/core/tests/coretests/apks/version/res/values/strings.xml b/core/tests/coretests/apks/version/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/version/res/values/strings.xml +++ b/core/tests/coretests/apks/version/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/apks/version_nosys/res/values/strings.xml b/core/tests/coretests/apks/version_nosys/res/values/strings.xml index 3b8b3b1af9b5..984152fb5fa7 100644 --- a/core/tests/coretests/apks/version_nosys/res/values/strings.xml +++ b/core/tests/coretests/apks/version_nosys/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Just need this dummy file to have something to build. --> +<!-- Just need this placeholder file to have something to build. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="dummy">dummy</string> + <string name="placeholder">placeholder</string> </resources> diff --git a/core/tests/coretests/src/android/graphics/PathTest.java b/core/tests/coretests/src/android/graphics/PathTest.java index c6d6d1ff90d5..b50792ca6b38 100644 --- a/core/tests/coretests/src/android/graphics/PathTest.java +++ b/core/tests/coretests/src/android/graphics/PathTest.java @@ -28,7 +28,9 @@ public class PathTest extends TestCase { final Path.FillType defaultFillType = path.getFillType(); final Path.FillType fillType = Path.FillType.INVERSE_EVEN_ODD; - assertFalse(fillType.equals(defaultFillType)); // Sanity check for the test itself. + + // This test is only meaningful if it changes from the default. + assertFalse(fillType.equals(defaultFillType)); path.setFillType(fillType); path.reset(); diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java index af3660a6dab9..ae6e79a040f7 100644 --- a/core/tests/coretests/src/android/os/VintfObjectTest.java +++ b/core/tests/coretests/src/android/os/VintfObjectTest.java @@ -20,7 +20,7 @@ import junit.framework.TestCase; public class VintfObjectTest extends TestCase { /** - * Sanity check for {@link VintfObject#report VintfObject.report()}. + * Quick check for {@link VintfObject#report VintfObject.report()}. */ public void testReport() { String[] xmls = VintfObject.report(); diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index fa1d56f2e68d..a3434e885012 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.icu.text.DateFormatSymbols; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -60,6 +61,15 @@ public class DateFormatTest { } @Test + public void testgetIcuDateFormatSymbols() { + DateFormatSymbols dfs = DateFormat.getIcuDateFormatSymbols(Locale.US); + assertEquals("AM", dfs.getAmPmStrings()[0]); + assertEquals("PM", dfs.getAmPmStrings()[1]); + assertEquals("a", dfs.getAmpmNarrowStrings()[0]); + assertEquals("p", dfs.getAmpmNarrowStrings()[1]); + } + + @Test public void testGetDateFormatOrder() { // lv and fa use differing orders depending on whether you're using numeric or // textual months. diff --git a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java new file mode 100644 index 000000000000..0f17d27048f3 --- /dev/null +++ b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text.format; + +import static android.icu.util.TimeZone.GMT_ZONE; +import static android.icu.util.ULocale.ENGLISH; +import static android.text.format.DateIntervalFormat.formatDateRange; +import static android.text.format.DateUtils.FORMAT_12HOUR; +import static android.text.format.DateUtils.FORMAT_24HOUR; +import static android.text.format.DateUtils.FORMAT_ABBREV_ALL; +import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; +import static android.text.format.DateUtils.FORMAT_ABBREV_TIME; +import static android.text.format.DateUtils.FORMAT_ABBREV_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_NO_MONTH_DAY; +import static android.text.format.DateUtils.FORMAT_NO_YEAR; +import static android.text.format.DateUtils.FORMAT_NUMERIC_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.FORMAT_UTC; + +import static org.junit.Assert.assertEquals; + +import android.icu.util.Calendar; +import android.icu.util.TimeZone; +import android.icu.util.ULocale; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.function.BiFunction; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DateIntervalFormatTest { + private static final long MINUTE = 60 * 1000; + private static final long HOUR = 60 * MINUTE; + private static final long DAY = 24 * HOUR; + private static final long MONTH = 31 * DAY; + private static final long YEAR = 12 * MONTH; + + // These are the old CTS tests for DateIntervalFormat.formatDateRange. + @Test + public void test_formatDateInterval() throws Exception { + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + + Calendar c = Calendar.getInstance(tz, ULocale.US); + c.set(Calendar.MONTH, Calendar.JANUARY); + c.set(Calendar.DAY_OF_MONTH, 19); + c.set(Calendar.HOUR_OF_DAY, 3); + c.set(Calendar.MINUTE, 30); + c.set(Calendar.SECOND, 15); + c.set(Calendar.MILLISECOND, 0); + long timeWithCurrentYear = c.getTimeInMillis(); + + c.set(Calendar.YEAR, 2009); + long fixedTime = c.getTimeInMillis(); + + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + long onTheHour = c.getTimeInMillis(); + + long noonDuration = (8 * 60 + 30) * 60 * 1000 - 15 * 1000; + long midnightDuration = (3 * 60 + 30) * 60 * 1000 + 15 * 1000; + + ULocale de_DE = new ULocale("de", "DE"); + ULocale en_US = new ULocale("en", "US"); + ULocale es_ES = new ULocale("es", "ES"); + ULocale es_US = new ULocale("es", "US"); + + assertEquals("Monday", + formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_WEEKDAY)); + assertEquals("January 19", + formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, + FORMAT_SHOW_DATE)); + assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME)); + assertEquals("January 19, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR)); + assertEquals("January 19", + formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_NO_YEAR)); + assertEquals("January", + formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, + FORMAT_NO_MONTH_DAY)); + assertEquals("3:30 AM", + formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_12HOUR | FORMAT_SHOW_TIME)); + assertEquals("03:30", + formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_24HOUR | FORMAT_SHOW_TIME)); + assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, + FORMAT_12HOUR /*| FORMAT_CAP_AMPM*/ | FORMAT_SHOW_TIME)); + assertEquals("12:00 PM", + formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, + FORMAT_12HOUR | FORMAT_SHOW_TIME)); + assertEquals("12:00 PM", + formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, + FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_CAP_NOON*/)); + assertEquals("12:00 PM", + formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, + FORMAT_12HOUR /*| FORMAT_NO_NOON*/ | FORMAT_SHOW_TIME)); + assertEquals("12:00 AM", formatDateRange(en_US, tz, fixedTime - midnightDuration, + fixedTime - midnightDuration, + FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_NO_MIDNIGHT*/)); + assertEquals("3:30 AM", + formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME | FORMAT_UTC)); + assertEquals("3 AM", formatDateRange(en_US, tz, onTheHour, onTheHour, + FORMAT_SHOW_TIME | FORMAT_ABBREV_TIME)); + assertEquals("Mon", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY)); + assertEquals("Jan 19", + formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH)); + assertEquals("Jan 19", + formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + + assertEquals("1/19/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * HOUR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("1/19/2009 – 1/22/2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("1/19/2009 – 4/22/2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("1/19/2009 – 2/9/2012", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + + assertEquals("19.1.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + HOUR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19.–22.01.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19.01. – 22.04.2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19.01.2009 – 09.02.2012", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + + assertEquals("19/1/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + HOUR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–22/1/2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–22/4/2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–9/2/2012", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + + assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–22/1/2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–22/4/2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + assertEquals("19/1/2009–9/2/2012", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE)); + + // These are some random other test cases I came up with. + + assertEquals("January 19 – 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, 0)); + assertEquals("Jan 19 – 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Mon, Jan 19 – Thu, Jan 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("Monday, January 19 – Thursday, January 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY)); + + assertEquals("January 19 – April 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, 0)); + assertEquals("Jan 19 – Apr 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Mon, Jan 19 – Wed, Apr 22, 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("January – April 2009", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY)); + + assertEquals("Jan 19, 2009 – Feb 9, 2012", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Jan 2009 – Feb 2012", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL)); + assertEquals("January 19, 2009 – February 9, 2012", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, 0)); + assertEquals("Monday, January 19, 2009 – Thursday, February 9, 2012", + formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY)); + + // The same tests but for de_DE. + + assertEquals("19.–22. Januar 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, 0)); + assertEquals("19.–22. Jan. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Mo., 19. – Do., 22. Jan. 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("Montag, 19. – Donnerstag, 22. Januar 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY)); + + assertEquals("19. Januar – 22. April 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, 0)); + assertEquals("19. Jan. – 22. Apr. 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Mo., 19. Jan. – Mi., 22. Apr. 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("Januar–April 2009", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY)); + + assertEquals("19. Jan. 2009 – 9. Feb. 2012", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("Jan. 2009 – Feb. 2012", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL)); + assertEquals("19. Januar 2009 – 9. Februar 2012", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, 0)); + assertEquals("Montag, 19. Januar 2009 – Donnerstag, 9. Februar 2012", + formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY)); + + // The same tests but for es_US. + + assertEquals("19–22 de enero de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, 0)); + assertEquals("19–22 de ene. de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("lun., 19 de ene. – jue., 22 de ene. de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY)); + + assertEquals("19 de enero–22 de abril de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, 0)); + assertEquals("19 de ene. – 22 de abr. 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("lun., 19 de ene. – mié., 22 de abr. de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("enero–abril de 2009", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY)); + + assertEquals("19 de ene. de 2009 – 9 de feb. de 2012", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("ene. de 2009 – feb. de 2012", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL)); + assertEquals("19 de enero de 2009–9 de febrero de 2012", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0)); + assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012", + formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY)); + + // The same tests but for es_ES. + + assertEquals("19–22 de enero de 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, 0)); + assertEquals("19–22 ene. 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("lun., 19 ene. – jue., 22 ene. 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY)); + + assertEquals("19 de enero–22 de abril de 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, 0)); + assertEquals("19 ene. – 22 abr. 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("lun., 19 ene. – mié., 22 abr. 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, + FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL)); + assertEquals("enero–abril de 2009", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY)); + + assertEquals("19 ene. 2009 – 9 feb. 2012", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); + assertEquals("ene. 2009 – feb. 2012", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, + FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL)); + assertEquals("19 de enero de 2009–9 de febrero de 2012", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, 0)); + assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012", + formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY)); + } + + // http://b/8862241 - we should be able to format dates past 2038. + // See also http://code.google.com/p/android/issues/detail?id=13050. + @Test + public void test8862241() throws Exception { + ULocale l = ULocale.US; + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + Calendar c = Calendar.getInstance(tz, l); + c.clear(); + c.set(2042, Calendar.JANUARY, 19, 3, 30); + long jan_19_2042 = c.getTimeInMillis(); + c.set(2046, Calendar.OCTOBER, 4, 3, 30); + long oct_4_2046 = c.getTimeInMillis(); + int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL; + assertEquals("Jan 19, 2042 – Oct 4, 2046", + formatDateRange(l, tz, jan_19_2042, oct_4_2046, flags)); + } + + // http://b/10089890 - we should take the given time zone into account. + @Test + public void test10089890() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + TimeZone pacific = TimeZone.getTimeZone("America/Los_Angeles"); + int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL | FORMAT_SHOW_TIME | FORMAT_24HOUR; + + // The Unix epoch is UTC, so 0 is 1970-01-01T00:00Z... + assertEquals("Jan 1, 1970, 00:00 – Jan 2, 1970, 00:00", + formatDateRange(l, utc, 0, DAY + 1, flags)); + // But MTV is hours behind, so 0 was still the afternoon of the previous day... + assertEquals("Dec 31, 1969, 16:00 – Jan 1, 1970, 16:00", + formatDateRange(l, pacific, 0, DAY, flags)); + } + + // http://b/10318326 - we can drop the minutes in a 12-hour time if they're zero, + // but not if we're using the 24-hour clock. That is: "4 PM" is reasonable, "16" is not. + @Test + public void test10318326() throws Exception { + long midnight = 0; + long teaTime = 16 * HOUR; + + int time12 = FORMAT_12HOUR | FORMAT_SHOW_TIME; + int time24 = FORMAT_24HOUR | FORMAT_SHOW_TIME; + int abbr12 = time12 | FORMAT_ABBREV_ALL; + int abbr24 = time24 | FORMAT_ABBREV_ALL; + + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + // Full length on-the-hour times. + assertEquals("00:00", formatDateRange(l, utc, midnight, midnight, time24)); + assertEquals("12:00 AM", formatDateRange(l, utc, midnight, midnight, time12)); + assertEquals("16:00", formatDateRange(l, utc, teaTime, teaTime, time24)); + assertEquals("4:00 PM", formatDateRange(l, utc, teaTime, teaTime, time12)); + + // Abbreviated on-the-hour times. + assertEquals("00:00", formatDateRange(l, utc, midnight, midnight, abbr24)); + assertEquals("12 AM", formatDateRange(l, utc, midnight, midnight, abbr12)); + assertEquals("16:00", formatDateRange(l, utc, teaTime, teaTime, abbr24)); + assertEquals("4 PM", formatDateRange(l, utc, teaTime, teaTime, abbr12)); + + // Abbreviated on-the-hour ranges. + assertEquals("00:00 – 16:00", formatDateRange(l, utc, midnight, teaTime, abbr24)); + assertEquals("12 AM – 4 PM", formatDateRange(l, utc, midnight, teaTime, abbr12)); + + // Abbreviated mixed ranges. + assertEquals("00:00 – 16:01", formatDateRange(l, utc, midnight, teaTime + MINUTE, abbr24)); + assertEquals("12:00 AM – 4:01 PM", + formatDateRange(l, utc, midnight, teaTime + MINUTE, abbr12)); + } + + // http://b/10560853 - when the time is not displayed, an end time 0 ms into the next day is + // considered to belong to the previous day. + @Test + public void test10560853_when_time_not_displayed() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + long midnight = 0; + long midnightNext = 1 * DAY; + + int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY; + + // An all-day event runs until 0 milliseconds into the next day, but is formatted as if it's + // just the first day. + assertEquals("Thursday, January 1, 1970", + formatDateRange(l, utc, midnight, midnightNext, flags)); + + // Run one millisecond over, though, and you're into the next day. + long nextMorning = 1 * DAY + 1; + assertEquals("Thursday, January 1 – Friday, January 2, 1970", + formatDateRange(l, utc, midnight, nextMorning, flags)); + + // But the same reasoning applies for that day. + long nextMidnight = 2 * DAY; + assertEquals("Thursday, January 1 – Friday, January 2, 1970", + formatDateRange(l, utc, midnight, nextMidnight, flags)); + } + + // http://b/10560853 - when the start and end times are otherwise on the same day, + // an end time 0 ms into the next day is considered to belong to the previous day. + @Test + public void test10560853_for_single_day_events() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE; + + assertEquals("January 1, 1970, 22:00 – 00:00", + formatDateRange(l, utc, 22 * HOUR, 24 * HOUR, flags)); + assertEquals("January 1, 1970, 22:00 – January 2, 1970, 00:30", + formatDateRange(l, utc, 22 * HOUR, 24 * HOUR + 30 * MINUTE, flags)); + } + + // The fix for http://b/10560853 didn't work except for the day around the epoch, which was + // all the unit test checked! + @Test + public void test_single_day_events_later_than_epoch() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE; + + Calendar c = Calendar.getInstance(utc, l); + c.clear(); + c.set(1980, Calendar.JANUARY, 1, 0, 0); + long jan_1_1980 = c.getTimeInMillis(); + assertEquals("January 1, 1980, 22:00 – 00:00", + formatDateRange(l, utc, jan_1_1980 + 22 * HOUR, jan_1_1980 + 24 * HOUR, flags)); + assertEquals("January 1, 1980, 22:00 – January 2, 1980, 00:30", + formatDateRange(l, utc, jan_1_1980 + 22 * HOUR, + jan_1_1980 + 24 * HOUR + 30 * MINUTE, flags)); + } + + // The fix for http://b/10560853 didn't work except for UTC, which was + // all the unit test checked! + @Test + public void test_single_day_events_not_in_UTC() throws Exception { + ULocale l = ULocale.US; + TimeZone pacific = TimeZone.getTimeZone("America/Los_Angeles"); + + int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE; + + Calendar c = Calendar.getInstance(pacific, l); + c.clear(); + c.set(1980, Calendar.JANUARY, 1, 0, 0); + long jan_1_1980 = c.getTimeInMillis(); + assertEquals("January 1, 1980, 22:00 – 00:00", + formatDateRange(l, pacific, jan_1_1980 + 22 * HOUR, jan_1_1980 + 24 * HOUR, flags)); + + c.set(1980, Calendar.JULY, 1, 0, 0); + long jul_1_1980 = c.getTimeInMillis(); + assertEquals("July 1, 1980, 22:00 – 00:00", + formatDateRange(l, pacific, jul_1_1980 + 22 * HOUR, jul_1_1980 + 24 * HOUR, flags)); + } + + // http://b/10209343 - even if the caller didn't explicitly ask us to include the year, + // we should do so for years other than the current year. + @Test + public void test10209343_when_not_this_year() { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_24HOUR; + + assertEquals("Thursday, January 1, 1970, 00:00", formatDateRange(l, utc, 0L, 0L, flags)); + + long t1833 = ((long) Integer.MIN_VALUE + Integer.MIN_VALUE) * 1000L; + assertEquals("Sunday, November 24, 1833, 17:31", + formatDateRange(l, utc, t1833, t1833, flags)); + + long t1901 = Integer.MIN_VALUE * 1000L; + assertEquals("Friday, December 13, 1901, 20:45", + formatDateRange(l, utc, t1901, t1901, flags)); + + long t2038 = Integer.MAX_VALUE * 1000L; + assertEquals("Tuesday, January 19, 2038, 03:14", + formatDateRange(l, utc, t2038, t2038, flags)); + + long t2106 = (2L + Integer.MAX_VALUE + Integer.MAX_VALUE) * 1000L; + assertEquals("Sunday, February 7, 2106, 06:28", + formatDateRange(l, utc, t2106, t2106, flags)); + } + + // http://b/10209343 - for the current year, we should honor the FORMAT_SHOW_YEAR flags. + @Test + public void test10209343_when_this_year() { + // Construct a date in the current year (whenever the test happens to be run). + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + Calendar c = Calendar.getInstance(utc, l); + c.set(Calendar.MONTH, Calendar.FEBRUARY); + c.set(Calendar.DAY_OF_MONTH, 10); + c.set(Calendar.HOUR_OF_DAY, 0); + long thisYear = c.getTimeInMillis(); + + // You don't get the year if it's this year... + assertEquals("February 10", formatDateRange(l, utc, thisYear, thisYear, FORMAT_SHOW_DATE)); + + // ...unless you explicitly ask for it. + assertEquals(String.format("February 10, %d", c.get(Calendar.YEAR)), + formatDateRange(l, utc, thisYear, thisYear, FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR)); + + // ...or it's not actually this year... + Calendar c2 = (Calendar) c.clone(); + c2.set(Calendar.YEAR, 1980); + long oldYear = c2.getTimeInMillis(); + assertEquals("February 10, 1980", + formatDateRange(l, utc, oldYear, oldYear, FORMAT_SHOW_DATE)); + + // (But you can disable that!) + assertEquals("February 10", + formatDateRange(l, utc, oldYear, oldYear, FORMAT_SHOW_DATE | FORMAT_NO_YEAR)); + + // ...or the start and end years aren't the same... + assertEquals(String.format("February 10, 1980 – February 10, %d", c.get(Calendar.YEAR)), + formatDateRange(l, utc, oldYear, thisYear, FORMAT_SHOW_DATE)); + + // (And you can't avoid that --- icu4c steps in and overrides you.) + assertEquals(String.format("February 10, 1980 – February 10, %d", c.get(Calendar.YEAR)), + formatDateRange(l, utc, oldYear, thisYear, FORMAT_SHOW_DATE | FORMAT_NO_YEAR)); + } + + // http://b/8467515 - yet another y2k38 bug report. + @Test + public void test8467515() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH + | FORMAT_ABBREV_WEEKDAY; + long t; + + Calendar calendar = Calendar.getInstance(utc, l); + calendar.clear(); + + calendar.set(2038, Calendar.JANUARY, 19, 12, 0, 0); + t = calendar.getTimeInMillis(); + assertEquals("Tue, Jan 19, 2038", formatDateRange(l, utc, t, t, flags)); + + calendar.set(1900, Calendar.JANUARY, 1, 0, 0, 0); + t = calendar.getTimeInMillis(); + assertEquals("Mon, Jan 1, 1900", formatDateRange(l, utc, t, t, flags)); + } + + // http://b/12004664 + @Test + public void test12004664() throws Exception { + TimeZone utc = TimeZone.getTimeZone("UTC"); + Calendar c = Calendar.getInstance(utc, ULocale.US); + c.clear(); + c.set(Calendar.YEAR, 1980); + c.set(Calendar.MONTH, Calendar.FEBRUARY); + c.set(Calendar.DAY_OF_MONTH, 10); + c.set(Calendar.HOUR_OF_DAY, 0); + long thisYear = c.getTimeInMillis(); + + int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR; + assertEquals("Sunday, February 10, 1980", + formatDateRange(new ULocale("en", "US"), utc, thisYear, thisYear, flags)); + + // If we supported non-Gregorian calendars, this is what that we'd expect for these + // ULocales. + // This is really the correct behavior, but since java.util.Calendar currently only supports + // the Gregorian calendar, we want to deliberately force icu4c to agree, otherwise we'd have + // a mix of calendars throughout an app's UI depending on whether Java or native code + // formatted + // the date. + // assertEquals("یکشنبه ۲۱ بهمن ۱۳۵۸ ه.ش.", formatDateRange(new ULocale("fa"), utc, + // thisYear, thisYear, flags)); + // assertEquals("AP ۱۳۵۸ سلواغه ۲۱, یکشنبه", formatDateRange(new ULocale("ps"), utc, + // thisYear, thisYear, flags)); + // assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 2523", formatDateRange(new ULocale("th"), utc, + // thisYear, thisYear, flags)); + + // For now, here are the localized Gregorian strings instead... + assertEquals("یکشنبه ۱۰ فوریهٔ ۱۹۸۰", + formatDateRange(new ULocale("fa"), utc, thisYear, thisYear, flags)); + assertEquals("يونۍ د ۱۹۸۰ د فبروري ۱۰", + formatDateRange(new ULocale("ps"), utc, thisYear, thisYear, flags)); + assertEquals("วันอาทิตย์ที่ 10 กุมภาพันธ์ ค.ศ. 1980", + formatDateRange(new ULocale("th"), utc, thisYear, thisYear, flags)); + } + + // http://b/13234532 + @Test + public void test13234532() throws Exception { + ULocale l = ULocale.US; + TimeZone utc = TimeZone.getTimeZone("UTC"); + + int flags = FORMAT_SHOW_TIME | FORMAT_ABBREV_ALL | FORMAT_12HOUR; + + assertEquals("10 – 11 AM", formatDateRange(l, utc, 10 * HOUR, 11 * HOUR, flags)); + assertEquals("11 AM – 1 PM", formatDateRange(l, utc, 11 * HOUR, 13 * HOUR, flags)); + assertEquals("2 – 3 PM", formatDateRange(l, utc, 14 * HOUR, 15 * HOUR, flags)); + } + + // http://b/20708022 + @Test + public void testEndOfDayOnLastDayOfMonth() throws Exception { + final ULocale locale = new ULocale("en"); + final TimeZone timeZone = TimeZone.getTimeZone("UTC"); + + assertEquals("11:00 PM – 12:00 AM", formatDateRange(locale, timeZone, + 1430434800000L, 1430438400000L, FORMAT_SHOW_TIME)); + } + + // http://b/68847519 + @Test + public void testEndAtMidnight_dateAndTime() { + BiFunction<Long, Long, String> fmt = (from, to) -> formatDateRange( + ENGLISH, GMT_ZONE, from, to, FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_24HOUR); + // If we're showing times and the end-point is midnight the following day, we want the + // behaviour of suppressing the date for the end... + assertEquals("February 27, 2007, 04:00 – 00:00", fmt.apply(1172548800000L, 1172620800000L)); + // ...unless the start-point is also midnight, in which case we need dates to disambiguate. + assertEquals("February 27, 2007, 00:00 – February 28, 2007, 00:00", + fmt.apply(1172534400000L, 1172620800000L)); + // We want to show the date if the end-point is a millisecond after midnight the following + // day, or if it is exactly midnight the day after that. + assertEquals("February 27, 2007, 04:00 – February 28, 2007, 00:00", + fmt.apply(1172548800000L, 1172620800001L)); + assertEquals("February 27, 2007, 04:00 – March 1, 2007, 00:00", + fmt.apply(1172548800000L, 1172707200000L)); + // We want to show the date if the start-point is anything less than a minute after + // midnight, + // since that gets displayed as midnight... + assertEquals("February 27, 2007, 00:00 – February 28, 2007, 00:00", + fmt.apply(1172534459999L, 1172620800000L)); + // ...but not if it is exactly one minute after midnight. + assertEquals("February 27, 2007, 00:01 – 00:00", fmt.apply(1172534460000L, 1172620800000L)); + } + + // http://b/68847519 + @Test + public void testEndAtMidnight_dateOnly() { + BiFunction<Long, Long, String> fmt = (from, to) -> formatDateRange( + ENGLISH, GMT_ZONE, from, to, FORMAT_SHOW_DATE); + // If we're only showing dates and the end-point is midnight of any day, we want the + // behaviour of showing an end date one earlier. So if the end-point is March 2, 2007 00:00, + // show March 1, 2007 instead (whether the start-point is midnight or not). + assertEquals("February 27 – March 1, 2007", fmt.apply(1172534400000L, 1172793600000L)); + assertEquals("February 27 – March 1, 2007", fmt.apply(1172548800000L, 1172793600000L)); + // We want to show the true date if the end-point is a millisecond after midnight. + assertEquals("February 27 – March 2, 2007", fmt.apply(1172534400000L, 1172793600001L)); + + // 2006-02-27 00:00:00.000 GMT - 2007-03-02 00:00:00.000 GMT + assertEquals("February 27, 2006 – March 1, 2007", + fmt.apply(1140998400000L, 1172793600000L)); + + // Spans a leap year's Feb 29th. + assertEquals("February 27 – March 1, 2004", fmt.apply(1077840000000L, 1078185600000L)); + } +} diff --git a/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java b/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java index d9ba8fb81d3c..4b3b5735b4f3 100644 --- a/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java +++ b/core/tests/coretests/src/android/text/format/RelativeDateTimeFormatterTest.java @@ -16,11 +16,11 @@ package android.text.format; -import static android.text.format.DateUtilsBridge.FORMAT_ABBREV_ALL; -import static android.text.format.DateUtilsBridge.FORMAT_ABBREV_RELATIVE; -import static android.text.format.DateUtilsBridge.FORMAT_NO_YEAR; -import static android.text.format.DateUtilsBridge.FORMAT_NUMERIC_DATE; -import static android.text.format.DateUtilsBridge.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.FORMAT_ABBREV_ALL; +import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE; +import static android.text.format.DateUtils.FORMAT_NO_YEAR; +import static android.text.format.DateUtils.FORMAT_NUMERIC_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; import static android.text.format.RelativeDateTimeFormatter.DAY_IN_MILLIS; import static android.text.format.RelativeDateTimeFormatter.HOUR_IN_MILLIS; import static android.text.format.RelativeDateTimeFormatter.MINUTE_IN_MILLIS; diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl index 8699cb491dff..caad45b46a21 100644 --- a/data/keyboards/Generic.kl +++ b/data/keyboards/Generic.kl @@ -317,7 +317,7 @@ key 366 DVR # key 367 "KEY_MHP" # key 368 "KEY_LANGUAGE" # key 369 "KEY_TITLE" -# key 370 "KEY_SUBTITLE" +key 370 CAPTIONS # key 371 "KEY_ANGLE" # key 372 "KEY_ZOOM" # key 373 "KEY_MODE" @@ -345,14 +345,14 @@ key 377 TV # key 395 "KEY_LIST" # key 396 "KEY_MEMO" key 397 CALENDAR -# key 398 "KEY_RED" -# key 399 "KEY_GREEN" -# key 400 "KEY_YELLOW" -# key 401 "KEY_BLUE" +key 398 PROG_RED +key 399 PROG_GREEN +key 400 PROG_YELLOW +key 401 PROG_BLUE key 402 CHANNEL_UP key 403 CHANNEL_DOWN # key 404 "KEY_FIRST" -# key 405 "KEY_LAST" +key 405 LAST_CHANNEL # key 406 "KEY_AB" # key 407 "KEY_NEXT" # key 408 "KEY_RESTART" @@ -410,8 +410,10 @@ key 580 APP_SWITCH key 582 VOICE_ASSIST # Keys defined by HID usages +key usage 0x0c0067 WINDOW key usage 0x0c006F BRIGHTNESS_UP key usage 0x0c0070 BRIGHTNESS_DOWN +key usage 0x0c0173 MEDIA_AUDIO_TRACK # Joystick and game controller axes. # Axes that are not mapped will be assigned generic axis numbers by the input subsystem. diff --git a/data/keyboards/OWNERS b/data/keyboards/OWNERS index 031a6c1c7a89..c4f6df824a39 100644 --- a/data/keyboards/OWNERS +++ b/data/keyboards/OWNERS @@ -2,3 +2,4 @@ set noparent michaelwr@google.com svv@google.com +lzye@google.com diff --git a/data/keyboards/Vendor_27f8_Product_0bbf.kl b/data/keyboards/Vendor_27f8_Product_0bbf.kl new file mode 100644 index 000000000000..a59f5663842c --- /dev/null +++ b/data/keyboards/Vendor_27f8_Product_0bbf.kl @@ -0,0 +1,54 @@ +# 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. + +# +# Razer Kishi Mobile Controller +# + + +# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html + +key 0x133 BUTTON_X +key 0x130 BUTTON_A +key 0x131 BUTTON_B +key 0x134 BUTTON_Y + +key 0x136 BUTTON_L1 +key 0x137 BUTTON_R1 +key 0x138 BUTTON_L2 +key 0x139 BUTTON_R2 + +axis 0x00 X +axis 0x01 Y + +axis 0x02 Z +axis 0x05 RZ + +axis 0x09 RTRIGGER +axis 0x0a LTRIGGER + +key 0x13d BUTTON_THUMBL +key 0x13e BUTTON_THUMBR + +# Hat +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt +# Left Triangle Button +key 0x13a BUTTON_SELECT +# Right Triangle Button +key 0x13b BUTTON_START +# Home Button +key 0x13c BUTTON_MODE diff --git a/data/keyboards/Vendor_2e95_Product_7725.kl b/data/keyboards/Vendor_2e95_Product_7725.kl new file mode 100644 index 000000000000..7672e22f8adc --- /dev/null +++ b/data/keyboards/Vendor_2e95_Product_7725.kl @@ -0,0 +1,64 @@ +# 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. + +# +# Scuf Vantage Controller +# + +# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html + +# Square +key 0x130 BUTTON_X +# Cross +key 0x131 BUTTON_A +# Circle +key 0x132 BUTTON_B +# Triangle +key 0x133 BUTTON_Y + +key 0x134 BUTTON_L1 +key 0x135 BUTTON_R1 +key 0x136 BUTTON_L2 +key 0x137 BUTTON_R2 + +# L2 Trigger axis +axis 0x03 LTRIGGER +# R2 Trigger axis +axis 0x04 RTRIGGER + +# Left Analog Stick +axis 0x00 X +axis 0x01 Y +# Right Analog Stick +axis 0x02 Z +axis 0x05 RZ + +# Left stick click +key 0x13a BUTTON_THUMBL +# Right stick click +key 0x13b BUTTON_THUMBR + +# Hat +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt +# Share +key 0x138 BUTTON_SELECT +# Options +key 0x139 BUTTON_START +# PS key +key 0x13c BUTTON_MODE +# Touchpad press +key 0x13d BUTTON_1 diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java index d8d96413a93d..43373ffbd3f4 100644 --- a/graphics/java/android/graphics/Region.java +++ b/graphics/java/android/graphics/Region.java @@ -409,10 +409,10 @@ public class Region implements Parcelable { mNativeRegion = ni; } - /* add dummy parameter so constructor can be called from jni without + /* Add an unused parameter so constructor can be called from jni without triggering 'not cloneable' exception */ @UnsupportedAppUsage - private Region(long ni, int dummy) { + private Region(long ni, int unused) { this(ni); } diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index eeaefc5b157c..a35143756d65 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -103,7 +103,7 @@ cc_library { }, }, sanitize: { - blacklist: "libandroidfw_blacklist.txt", + blocklist: "libandroidfw_blocklist.txt", }, } diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp new file mode 100644 index 000000000000..77ef8dfb9725 --- /dev/null +++ b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp @@ -0,0 +1,46 @@ +// 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. + +cc_fuzz { + name: "resourcefile_fuzzer", + srcs: [ + "resourcefile_fuzzer.cpp", + ], + host_supported: true, + corpus: ["corpus/*"], + static_libs: ["libgmock"], + target: { + android: { + shared_libs:[ + "libandroidfw", + "libbase", + "libcutils", + "libutils", + "libziparchive", + "libui", + ], + }, + host: { + static_libs: [ + "libandroidfw", + "libbase", + "libcutils", + "libutils", + "libziparchive", + "liblog", + "libz", + ], + }, + }, +} diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/corpus/resources.arsc b/libs/androidfw/fuzz/resourcefile_fuzzer/corpus/resources.arsc Binary files differnew file mode 100644 index 000000000000..3cf2ea733d28 --- /dev/null +++ b/libs/androidfw/fuzz/resourcefile_fuzzer/corpus/resources.arsc diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/resourcefile_fuzzer.cpp b/libs/androidfw/fuzz/resourcefile_fuzzer/resourcefile_fuzzer.cpp new file mode 100644 index 000000000000..96d44ab8e45c --- /dev/null +++ b/libs/androidfw/fuzz/resourcefile_fuzzer/resourcefile_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <string> +#include <memory> + +#include <androidfw/ApkAssets.h> +#include <androidfw/LoadedArsc.h> +#include <androidfw/StringPiece.h> + +#include <fuzzer/FuzzedDataProvider.h> + +using android::ApkAssets; +using android::LoadedArsc; +using android::StringPiece; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + + std::unique_ptr<const LoadedArsc> loaded_arsc = + LoadedArsc::Load(StringPiece(reinterpret_cast<const char*>(data), size)); + + return 0; +}
\ No newline at end of file diff --git a/libs/androidfw/libandroidfw_blacklist.txt b/libs/androidfw/libandroidfw_blocklist.txt index dd17e4d5b1e8..dd17e4d5b1e8 100644 --- a/libs/androidfw/libandroidfw_blacklist.txt +++ b/libs/androidfw/libandroidfw_blocklist.txt diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS index 936ba5cc8311..c232d1360419 100644 --- a/libs/hwui/OWNERS +++ b/libs/hwui/OWNERS @@ -1,6 +1,7 @@ +alecmouri@google.com +djsollen@google.com jreck@google.com njawad@google.com -djsollen@google.com -stani@google.com -scroggo@google.com reed@google.com +scroggo@google.com +stani@google.com diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index c21bdca3db77..7352061bd2cd 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -182,11 +182,8 @@ static SkImageInfo validateAlpha(const SkImageInfo& info) { void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes) { mInfo = validateAlpha(newInfo); - // Dirty hack is dirty - // TODO: Figure something out here, Skia's current design makes this - // really hard to work with. Skia really, really wants immutable objects, - // but with the nested-ref-count hackery going on that's just not - // feasible without going insane trying to figure it out + // TODO: Skia intends for SkPixelRef to be immutable, but this method + // modifies it. Find another way to support reusing the same pixel memory. this->android_only_reset(mInfo.width(), mInfo.height(), rowBytes); } diff --git a/libs/input/Android.bp b/libs/input/Android.bp index fd4371cac795..7942806bc86a 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -16,6 +16,9 @@ cc_library_shared { name: "libinputservice", srcs: [ "PointerController.cpp", + "PointerControllerContext.cpp", + "MouseCursorController.cpp", + "TouchSpotController.cpp", "SpriteController.cpp", "SpriteIcon.cpp", ], diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp new file mode 100644 index 000000000000..80b555be97dd --- /dev/null +++ b/libs/input/MouseCursorController.cpp @@ -0,0 +1,460 @@ +/* + * 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. + */ + +#define LOG_TAG "MouseCursorController" +//#define LOG_NDEBUG 0 + +// Log debug messages about pointer updates +#define DEBUG_MOUSE_CURSOR_UPDATES 0 + +#include "MouseCursorController.h" + +#include <log/log.h> + +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkColor.h> +#include <SkPaint.h> + +namespace { +// Time to spend fading out the pointer completely. +const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms +} // namespace + +namespace android { + +// --- MouseCursorController --- + +MouseCursorController::MouseCursorController(PointerControllerContext& context) + : mContext(context) { + std::scoped_lock lock(mLock); + + mLocked.animationFrameIndex = 0; + mLocked.lastFrameUpdatedTime = 0; + + mLocked.pointerFadeDirection = 0; + mLocked.pointerX = 0; + mLocked.pointerY = 0; + mLocked.pointerAlpha = 0.0f; // pointer is initially faded + mLocked.pointerSprite = mContext.getSpriteController()->createSprite(); + mLocked.updatePointerIcon = false; + mLocked.requestedPointerType = mContext.getPolicy()->getDefaultPointerIconId(); + + mLocked.resourcesLoaded = false; + + mLocked.buttonState = 0; +} + +MouseCursorController::~MouseCursorController() { + std::scoped_lock lock(mLock); + + mLocked.pointerSprite.clear(); +} + +bool MouseCursorController::getBounds(float* outMinX, float* outMinY, float* outMaxX, + float* outMaxY) const { + std::scoped_lock lock(mLock); + + return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY); +} + +bool MouseCursorController::getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, + float* outMaxY) const REQUIRES(mLock) { + if (!mLocked.viewport.isValid()) { + return false; + } + + *outMinX = mLocked.viewport.logicalLeft; + *outMinY = mLocked.viewport.logicalTop; + *outMaxX = mLocked.viewport.logicalRight - 1; + *outMaxY = mLocked.viewport.logicalBottom - 1; + return true; +} + +void MouseCursorController::move(float deltaX, float deltaY) { +#if DEBUG_MOUSE_CURSOR_UPDATES + ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); +#endif + if (deltaX == 0.0f && deltaY == 0.0f) { + return; + } + + std::scoped_lock lock(mLock); + + setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); +} + +void MouseCursorController::setButtonState(int32_t buttonState) { +#if DEBUG_MOUSE_CURSOR_UPDATES + ALOGD("Set button state 0x%08x", buttonState); +#endif + std::scoped_lock lock(mLock); + + if (mLocked.buttonState != buttonState) { + mLocked.buttonState = buttonState; + } +} + +int32_t MouseCursorController::getButtonState() const { + std::scoped_lock lock(mLock); + return mLocked.buttonState; +} + +void MouseCursorController::setPosition(float x, float y) { +#if DEBUG_MOUSE_CURSOR_UPDATES + ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); +#endif + std::scoped_lock lock(mLock); + setPositionLocked(x, y); +} + +void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { + float minX, minY, maxX, maxY; + if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { + if (x <= minX) { + mLocked.pointerX = minX; + } else if (x >= maxX) { + mLocked.pointerX = maxX; + } else { + mLocked.pointerX = x; + } + if (y <= minY) { + mLocked.pointerY = minY; + } else if (y >= maxY) { + mLocked.pointerY = maxY; + } else { + mLocked.pointerY = y; + } + updatePointerLocked(); + } +} + +void MouseCursorController::getPosition(float* outX, float* outY) const { + std::scoped_lock lock(mLock); + + *outX = mLocked.pointerX; + *outY = mLocked.pointerY; +} + +int32_t MouseCursorController::getDisplayId() const { + std::scoped_lock lock(mLock); + return mLocked.viewport.displayId; +} + +void MouseCursorController::fade(PointerControllerInterface::Transition transition) { + std::scoped_lock lock(mLock); + + // Remove the inactivity timeout, since we are fading now. + mContext.removeInactivityTimeout(); + + // Start fading. + if (transition == PointerControllerInterface::Transition::IMMEDIATE) { + mLocked.pointerFadeDirection = 0; + mLocked.pointerAlpha = 0.0f; + updatePointerLocked(); + } else { + mLocked.pointerFadeDirection = -1; + mContext.startAnimation(); + } +} + +void MouseCursorController::unfade(PointerControllerInterface::Transition transition) { + std::scoped_lock lock(mLock); + + // Always reset the inactivity timer. + mContext.resetInactivityTimeout(); + + // Start unfading. + if (transition == PointerControllerInterface::Transition::IMMEDIATE) { + mLocked.pointerFadeDirection = 0; + mLocked.pointerAlpha = 1.0f; + updatePointerLocked(); + } else { + mLocked.pointerFadeDirection = 1; + mContext.startAnimation(); + } +} + +void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) { + std::scoped_lock lock(mLock); + + loadResourcesLocked(getAdditionalMouseResources); + updatePointerLocked(); +} + +/** + * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation, + * so here we are getting the dimensions in the original, unrotated orientation (orientation 0). + */ +static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) { + width = viewport.deviceWidth; + height = viewport.deviceHeight; + + if (viewport.orientation == DISPLAY_ORIENTATION_90 || + viewport.orientation == DISPLAY_ORIENTATION_270) { + std::swap(width, height); + } +} + +void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport, + bool getAdditionalMouseResources) { + std::scoped_lock lock(mLock); + + if (viewport == mLocked.viewport) { + return; + } + + const DisplayViewport oldViewport = mLocked.viewport; + mLocked.viewport = viewport; + + int32_t oldDisplayWidth, oldDisplayHeight; + getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight); + int32_t newDisplayWidth, newDisplayHeight; + getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight); + + // Reset cursor position to center if size or display changed. + if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth || + oldDisplayHeight != newDisplayHeight) { + float minX, minY, maxX, maxY; + if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { + mLocked.pointerX = (minX + maxX) * 0.5f; + mLocked.pointerY = (minY + maxY) * 0.5f; + // Reload icon resources for density may be changed. + loadResourcesLocked(getAdditionalMouseResources); + } else { + mLocked.pointerX = 0; + mLocked.pointerY = 0; + } + } else if (oldViewport.orientation != viewport.orientation) { + // Apply offsets to convert from the pixel top-left corner position to the pixel center. + // This creates an invariant frame of reference that we can easily rotate when + // taking into account that the pointer may be located at fractional pixel offsets. + float x = mLocked.pointerX + 0.5f; + float y = mLocked.pointerY + 0.5f; + float temp; + + // Undo the previous rotation. + switch (oldViewport.orientation) { + case DISPLAY_ORIENTATION_90: + temp = x; + x = oldViewport.deviceHeight - y; + y = temp; + break; + case DISPLAY_ORIENTATION_180: + x = oldViewport.deviceWidth - x; + y = oldViewport.deviceHeight - y; + break; + case DISPLAY_ORIENTATION_270: + temp = x; + x = y; + y = oldViewport.deviceWidth - temp; + break; + } + + // Perform the new rotation. + switch (viewport.orientation) { + case DISPLAY_ORIENTATION_90: + temp = x; + x = y; + y = viewport.deviceHeight - temp; + break; + case DISPLAY_ORIENTATION_180: + x = viewport.deviceWidth - x; + y = viewport.deviceHeight - y; + break; + case DISPLAY_ORIENTATION_270: + temp = x; + x = viewport.deviceWidth - y; + y = temp; + break; + } + + // Apply offsets to convert from the pixel center to the pixel top-left corner position + // and save the results. + mLocked.pointerX = x - 0.5f; + mLocked.pointerY = y - 0.5f; + } + + updatePointerLocked(); +} + +void MouseCursorController::updatePointerIcon(int32_t iconId) { + std::scoped_lock lock(mLock); + + if (mLocked.requestedPointerType != iconId) { + mLocked.requestedPointerType = iconId; + mLocked.updatePointerIcon = true; + updatePointerLocked(); + } +} + +void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) { + std::scoped_lock lock(mLock); + + const int32_t iconId = mContext.getPolicy()->getCustomPointerIconId(); + mLocked.additionalMouseResources[iconId] = icon; + mLocked.requestedPointerType = iconId; + mLocked.updatePointerIcon = true; + updatePointerLocked(); +} + +bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) { + nsecs_t frameDelay = timestamp - mContext.getAnimationTime(); + + std::scoped_lock lock(mLock); + + // Animate pointer fade. + if (mLocked.pointerFadeDirection < 0) { + mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION; + if (mLocked.pointerAlpha <= 0.0f) { + mLocked.pointerAlpha = 0.0f; + mLocked.pointerFadeDirection = 0; + } else { + keepAnimating = true; + } + updatePointerLocked(); + } else if (mLocked.pointerFadeDirection > 0) { + mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION; + if (mLocked.pointerAlpha >= 1.0f) { + mLocked.pointerAlpha = 1.0f; + mLocked.pointerFadeDirection = 0; + } else { + keepAnimating = true; + } + updatePointerLocked(); + } + + return keepAnimating; +} + +bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) { + std::scoped_lock lock(mLock); + + std::map<int32_t, PointerAnimation>::const_iterator iter = + mLocked.animationResources.find(mLocked.requestedPointerType); + if (iter == mLocked.animationResources.end()) { + return false; + } + + if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) { + sp<SpriteController> spriteController = mContext.getSpriteController(); + spriteController->openTransaction(); + + int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame; + mLocked.animationFrameIndex += incr; + mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr; + while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) { + mLocked.animationFrameIndex -= iter->second.animationFrames.size(); + } + mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]); + + spriteController->closeTransaction(); + } + + // Keep animating. + return true; +} + +void MouseCursorController::updatePointerLocked() REQUIRES(mLock) { + if (!mLocked.viewport.isValid()) { + return; + } + sp<SpriteController> spriteController = mContext.getSpriteController(); + spriteController->openTransaction(); + + mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER); + mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY); + mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId); + + if (mLocked.pointerAlpha > 0) { + mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha); + mLocked.pointerSprite->setVisible(true); + } else { + mLocked.pointerSprite->setVisible(false); + } + + if (mLocked.updatePointerIcon) { + if (mLocked.requestedPointerType == mContext.getPolicy()->getDefaultPointerIconId()) { + mLocked.pointerSprite->setIcon(mLocked.pointerIcon); + } else { + std::map<int32_t, SpriteIcon>::const_iterator iter = + mLocked.additionalMouseResources.find(mLocked.requestedPointerType); + if (iter != mLocked.additionalMouseResources.end()) { + std::map<int32_t, PointerAnimation>::const_iterator anim_iter = + mLocked.animationResources.find(mLocked.requestedPointerType); + if (anim_iter != mLocked.animationResources.end()) { + mLocked.animationFrameIndex = 0; + mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC); + mContext.startAnimation(); + } + mLocked.pointerSprite->setIcon(iter->second); + } else { + ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType); + mLocked.pointerSprite->setIcon(mLocked.pointerIcon); + } + } + mLocked.updatePointerIcon = false; + } + + spriteController->closeTransaction(); +} + +void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) { + if (!mLocked.viewport.isValid()) { + return; + } + + if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true; + + sp<PointerControllerPolicyInterface> policy = mContext.getPolicy(); + policy->loadPointerResources(&mResources, mLocked.viewport.displayId); + policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId); + + mLocked.additionalMouseResources.clear(); + mLocked.animationResources.clear(); + if (getAdditionalMouseResources) { + policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, + &mLocked.animationResources, + mLocked.viewport.displayId); + } + + mLocked.updatePointerIcon = true; +} + +bool MouseCursorController::isViewportValid() { + std::scoped_lock lock(mLock); + return mLocked.viewport.isValid(); +} + +void MouseCursorController::getAdditionalMouseResources() { + std::scoped_lock lock(mLock); + + if (mLocked.additionalMouseResources.empty()) { + mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources, + &mLocked.animationResources, + mLocked.viewport.displayId); + } + mLocked.updatePointerIcon = true; + updatePointerLocked(); +} + +bool MouseCursorController::resourcesLoaded() { + std::scoped_lock lock(mLock); + return mLocked.resourcesLoaded; +} + +} // namespace android diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h new file mode 100644 index 000000000000..448165b5ac46 --- /dev/null +++ b/libs/input/MouseCursorController.h @@ -0,0 +1,111 @@ +/* + * 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 _UI_MOUSE_CURSOR_CONTROLLER_H +#define _UI_MOUSE_CURSOR_CONTROLLER_H + +#include <gui/DisplayEventReceiver.h> +#include <input/DisplayViewport.h> +#include <input/Input.h> +#include <ui/DisplayInfo.h> +#include <utils/BitSet.h> +#include <utils/Looper.h> +#include <utils/RefBase.h> + +#include <map> +#include <memory> +#include <vector> + +#include "PointerControllerContext.h" +#include "SpriteController.h" + +namespace android { + +/* + * Helper class for PointerController that specifically handles + * mouse cursor resources and actions. + */ +class MouseCursorController { +public: + MouseCursorController(PointerControllerContext& context); + ~MouseCursorController(); + + bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; + void move(float deltaX, float deltaY); + void setButtonState(int32_t buttonState); + int32_t getButtonState() const; + void setPosition(float x, float y); + void getPosition(float* outX, float* outY) const; + int32_t getDisplayId() const; + void fade(PointerControllerInterface::Transition transition); + void unfade(PointerControllerInterface::Transition transition); + void setDisplayViewport(const DisplayViewport& viewport, bool getAdditionalMouseResources); + + void updatePointerIcon(int32_t iconId); + void setCustomPointerIcon(const SpriteIcon& icon); + void reloadPointerResources(bool getAdditionalMouseResources); + + void getAdditionalMouseResources(); + bool isViewportValid(); + + bool doBitmapAnimation(nsecs_t timestamp); + bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating); + + bool resourcesLoaded(); + +private: + mutable std::mutex mLock; + + PointerResources mResources; + + PointerControllerContext& mContext; + + struct Locked { + DisplayViewport viewport; + + size_t animationFrameIndex; + nsecs_t lastFrameUpdatedTime; + + int32_t pointerFadeDirection; + float pointerX; + float pointerY; + float pointerAlpha; + sp<Sprite> pointerSprite; + SpriteIcon pointerIcon; + bool updatePointerIcon; + + bool resourcesLoaded; + + std::map<int32_t, SpriteIcon> additionalMouseResources; + std::map<int32_t, PointerAnimation> animationResources; + + int32_t requestedPointerType; + + int32_t buttonState; + + } mLocked GUARDED_BY(mLock); + + bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; + void setPositionLocked(float x, float y); + + void updatePointerLocked(); + + void loadResourcesLocked(bool getAdditionalMouseResources); +}; + +} // namespace android + +#endif // _UI_MOUSE_CURSOR_CONTROLLER_H diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 5e480a66c355..14c96cefd462 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -21,31 +21,26 @@ #define DEBUG_POINTER_UPDATES 0 #include "PointerController.h" +#include "MouseCursorController.h" +#include "PointerControllerContext.h" +#include "TouchSpotController.h" #include <log/log.h> -#include <memory> +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkColor.h> +#include <SkPaint.h> namespace android { // --- PointerController --- -// Time to wait before starting the fade when the pointer is inactive. -static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds -static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds - -// Time to spend fading out the spot completely. -static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms - -// Time to spend fading out the pointer completely. -static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms - -// The number of events to be read at once for DisplayEventReceiver. -static const int EVENT_BUFFER_SIZE = 100; - std::shared_ptr<PointerController> PointerController::create( const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, const sp<SpriteController>& spriteController) { + // using 'new' to access non-public constructor std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>( new PointerController(policy, looper, spriteController)); @@ -60,758 +55,175 @@ std::shared_ptr<PointerController> PointerController::create( * weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr. */ - controller->mHandler->pointerController = controller; - controller->mCallback->pointerController = controller; - if (controller->mDisplayEventReceiver.initCheck() == NO_ERROR) { - controller->mLooper->addFd(controller->mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, - Looper::EVENT_INPUT, controller->mCallback, nullptr); - } else { - ALOGE("Failed to initialize DisplayEventReceiver."); - } + controller->mContext.setHandlerController(controller); + controller->mContext.setCallbackController(controller); + controller->mContext.initializeDisplayEventReceiver(); return controller; } PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, const sp<SpriteController>& spriteController) - : mPolicy(policy), - mLooper(looper), - mSpriteController(spriteController), - mHandler(new MessageHandler()), - mCallback(new LooperCallback()) { - AutoMutex _l(mLock); - - mLocked.animationPending = false; - - mLocked.presentation = Presentation::POINTER; - mLocked.presentationChanged = false; - - mLocked.inactivityTimeout = InactivityTimeout::NORMAL; - - mLocked.pointerFadeDirection = 0; - mLocked.pointerX = 0; - mLocked.pointerY = 0; - mLocked.pointerAlpha = 0.0f; // pointer is initially faded - mLocked.pointerSprite = mSpriteController->createSprite(); - mLocked.pointerIconChanged = false; - mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId(); - - mLocked.animationFrameIndex = 0; - mLocked.lastFrameUpdatedTime = 0; - - mLocked.buttonState = 0; + : mContext(policy, looper, spriteController, *this), mCursorController(mContext) { + std::scoped_lock lock(mLock); + mLocked.presentation = Presentation::SPOT; } -PointerController::~PointerController() { - mLooper->removeMessages(mHandler); - - AutoMutex _l(mLock); - - mLocked.pointerSprite.clear(); - - for (auto& it : mLocked.spotsByDisplay) { - const std::vector<Spot*>& spots = it.second; - size_t numSpots = spots.size(); - for (size_t i = 0; i < numSpots; i++) { - delete spots[i]; - } - } - mLocked.spotsByDisplay.clear(); - mLocked.recycledSprites.clear(); -} - -bool PointerController::getBounds(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const { - AutoMutex _l(mLock); - - return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY); -} - -bool PointerController::getBoundsLocked(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const { - - if (!mLocked.viewport.isValid()) { - return false; - } - - *outMinX = mLocked.viewport.logicalLeft; - *outMinY = mLocked.viewport.logicalTop; - *outMaxX = mLocked.viewport.logicalRight - 1; - *outMaxY = mLocked.viewport.logicalBottom - 1; - return true; +bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX, + float* outMaxY) const { + return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY); } void PointerController::move(float deltaX, float deltaY) { -#if DEBUG_POINTER_UPDATES - ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); -#endif - if (deltaX == 0.0f && deltaY == 0.0f) { - return; - } - - AutoMutex _l(mLock); - - setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); + mCursorController.move(deltaX, deltaY); } void PointerController::setButtonState(int32_t buttonState) { -#if DEBUG_POINTER_UPDATES - ALOGD("Set button state 0x%08x", buttonState); -#endif - AutoMutex _l(mLock); - - if (mLocked.buttonState != buttonState) { - mLocked.buttonState = buttonState; - } + mCursorController.setButtonState(buttonState); } int32_t PointerController::getButtonState() const { - AutoMutex _l(mLock); - - return mLocked.buttonState; + return mCursorController.getButtonState(); } void PointerController::setPosition(float x, float y) { -#if DEBUG_POINTER_UPDATES - ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); -#endif - AutoMutex _l(mLock); - - setPositionLocked(x, y); -} - -void PointerController::setPositionLocked(float x, float y) { - float minX, minY, maxX, maxY; - if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { - if (x <= minX) { - mLocked.pointerX = minX; - } else if (x >= maxX) { - mLocked.pointerX = maxX; - } else { - mLocked.pointerX = x; - } - if (y <= minY) { - mLocked.pointerY = minY; - } else if (y >= maxY) { - mLocked.pointerY = maxY; - } else { - mLocked.pointerY = y; - } - updatePointerLocked(); - } + std::scoped_lock lock(mLock); + mCursorController.setPosition(x, y); } void PointerController::getPosition(float* outX, float* outY) const { - AutoMutex _l(mLock); - - *outX = mLocked.pointerX; - *outY = mLocked.pointerY; + mCursorController.getPosition(outX, outY); } int32_t PointerController::getDisplayId() const { - AutoMutex _l(mLock); - - return mLocked.viewport.displayId; + return mCursorController.getDisplayId(); } void PointerController::fade(Transition transition) { - AutoMutex _l(mLock); - - // Remove the inactivity timeout, since we are fading now. - removeInactivityTimeoutLocked(); - - // Start fading. - if (transition == Transition::IMMEDIATE) { - mLocked.pointerFadeDirection = 0; - mLocked.pointerAlpha = 0.0f; - updatePointerLocked(); - } else { - mLocked.pointerFadeDirection = -1; - startAnimationLocked(); - } + std::scoped_lock lock(mLock); + mCursorController.fade(transition); } void PointerController::unfade(Transition transition) { - AutoMutex _l(mLock); - - // Always reset the inactivity timer. - resetInactivityTimeoutLocked(); - - // Start unfading. - if (transition == Transition::IMMEDIATE) { - mLocked.pointerFadeDirection = 0; - mLocked.pointerAlpha = 1.0f; - updatePointerLocked(); - } else { - mLocked.pointerFadeDirection = 1; - startAnimationLocked(); - } + std::scoped_lock lock(mLock); + mCursorController.unfade(transition); } void PointerController::setPresentation(Presentation presentation) { - AutoMutex _l(mLock); + std::scoped_lock lock(mLock); if (mLocked.presentation == presentation) { return; } mLocked.presentation = presentation; - mLocked.presentationChanged = true; - if (!mLocked.viewport.isValid()) { + if (!mCursorController.isViewportValid()) { return; } if (presentation == Presentation::POINTER) { - if (mLocked.additionalMouseResources.empty()) { - mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, - &mLocked.animationResources, - mLocked.viewport.displayId); - } - fadeOutAndReleaseAllSpotsLocked(); - updatePointerLocked(); + mCursorController.getAdditionalMouseResources(); + clearSpotsLocked(); } } -void PointerController::setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) { -#if DEBUG_POINTER_UPDATES - ALOGD("setSpots: idBits=%08x", spotIdBits.value); - for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - const PointerCoords& c = spotCoords[spotIdToIndex[id]]; - ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id, - c.getAxisValue(AMOTION_EVENT_AXIS_X), - c.getAxisValue(AMOTION_EVENT_AXIS_Y), - c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - displayId); +void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits, int32_t displayId) { + std::scoped_lock lock(mLock); + auto it = mLocked.spotControllers.find(displayId); + if (it == mLocked.spotControllers.end()) { + mLocked.spotControllers.try_emplace(displayId, displayId, mContext); } -#endif - - AutoMutex _l(mLock); - if (!mLocked.viewport.isValid()) { - return; - } - - std::vector<Spot*> newSpots; - std::map<int32_t, std::vector<Spot*>>::const_iterator iter = - mLocked.spotsByDisplay.find(displayId); - if (iter != mLocked.spotsByDisplay.end()) { - newSpots = iter->second; - } - - mSpriteController->openTransaction(); - - // Add or move spots for fingers that are down. - for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.clearFirstMarkedBit(); - const PointerCoords& c = spotCoords[spotIdToIndex[id]]; - const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0 - ? mResources.spotTouch : mResources.spotHover; - float x = c.getAxisValue(AMOTION_EVENT_AXIS_X); - float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y); - - Spot* spot = getSpot(id, newSpots); - if (!spot) { - spot = createAndAddSpotLocked(id, newSpots); - } - - spot->updateSprite(&icon, x, y, displayId); - } - - // Remove spots for fingers that went up. - for (size_t i = 0; i < newSpots.size(); i++) { - Spot* spot = newSpots[i]; - if (spot->id != Spot::INVALID_ID - && !spotIdBits.hasBit(spot->id)) { - fadeOutAndReleaseSpotLocked(spot); - } - } - - mSpriteController->closeTransaction(); - mLocked.spotsByDisplay[displayId] = newSpots; + mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits); } void PointerController::clearSpots() { -#if DEBUG_POINTER_UPDATES - ALOGD("clearSpots"); -#endif + std::scoped_lock lock(mLock); + clearSpotsLocked(); +} - AutoMutex _l(mLock); - if (!mLocked.viewport.isValid()) { - return; +void PointerController::clearSpotsLocked() REQUIRES(mLock) { + for (auto& [displayID, spotController] : mLocked.spotControllers) { + spotController.clearSpots(); } - - fadeOutAndReleaseAllSpotsLocked(); } void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) { - AutoMutex _l(mLock); - - if (mLocked.inactivityTimeout != inactivityTimeout) { - mLocked.inactivityTimeout = inactivityTimeout; - resetInactivityTimeoutLocked(); - } + mContext.setInactivityTimeout(inactivityTimeout); } void PointerController::reloadPointerResources() { - AutoMutex _l(mLock); + std::scoped_lock lock(mLock); - loadResourcesLocked(); - updatePointerLocked(); -} - -/** - * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation, - * so here we are getting the dimensions in the original, unrotated orientation (orientation 0). - */ -static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) { - width = viewport.deviceWidth; - height = viewport.deviceHeight; + for (auto& [displayID, spotController] : mLocked.spotControllers) { + spotController.reloadSpotResources(); + } - if (viewport.orientation == DISPLAY_ORIENTATION_90 - || viewport.orientation == DISPLAY_ORIENTATION_270) { - std::swap(width, height); + if (mCursorController.resourcesLoaded()) { + bool getAdditionalMouseResources = false; + if (mLocked.presentation == PointerController::Presentation::POINTER) { + getAdditionalMouseResources = true; + } + mCursorController.reloadPointerResources(getAdditionalMouseResources); } } void PointerController::setDisplayViewport(const DisplayViewport& viewport) { - AutoMutex _l(mLock); - if (viewport == mLocked.viewport) { - return; - } - - const DisplayViewport oldViewport = mLocked.viewport; - mLocked.viewport = viewport; - - int32_t oldDisplayWidth, oldDisplayHeight; - getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight); - int32_t newDisplayWidth, newDisplayHeight; - getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight); - - // Reset cursor position to center if size or display changed. - if (oldViewport.displayId != viewport.displayId - || oldDisplayWidth != newDisplayWidth - || oldDisplayHeight != newDisplayHeight) { - - float minX, minY, maxX, maxY; - if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { - mLocked.pointerX = (minX + maxX) * 0.5f; - mLocked.pointerY = (minY + maxY) * 0.5f; - // Reload icon resources for density may be changed. - loadResourcesLocked(); - } else { - mLocked.pointerX = 0; - mLocked.pointerY = 0; - } + std::scoped_lock lock(mLock); - fadeOutAndReleaseAllSpotsLocked(); - } else if (oldViewport.orientation != viewport.orientation) { - // Apply offsets to convert from the pixel top-left corner position to the pixel center. - // This creates an invariant frame of reference that we can easily rotate when - // taking into account that the pointer may be located at fractional pixel offsets. - float x = mLocked.pointerX + 0.5f; - float y = mLocked.pointerY + 0.5f; - float temp; - - // Undo the previous rotation. - switch (oldViewport.orientation) { - case DISPLAY_ORIENTATION_90: - temp = x; - x = oldViewport.deviceHeight - y; - y = temp; - break; - case DISPLAY_ORIENTATION_180: - x = oldViewport.deviceWidth - x; - y = oldViewport.deviceHeight - y; - break; - case DISPLAY_ORIENTATION_270: - temp = x; - x = y; - y = oldViewport.deviceWidth - temp; - break; - } - - // Perform the new rotation. - switch (viewport.orientation) { - case DISPLAY_ORIENTATION_90: - temp = x; - x = y; - y = viewport.deviceHeight - temp; - break; - case DISPLAY_ORIENTATION_180: - x = viewport.deviceWidth - x; - y = viewport.deviceHeight - y; - break; - case DISPLAY_ORIENTATION_270: - temp = x; - x = viewport.deviceWidth - y; - y = temp; - break; - } - - // Apply offsets to convert from the pixel center to the pixel top-left corner position - // and save the results. - mLocked.pointerX = x - 0.5f; - mLocked.pointerY = y - 0.5f; + bool getAdditionalMouseResources = false; + if (mLocked.presentation == PointerController::Presentation::POINTER) { + getAdditionalMouseResources = true; } - - updatePointerLocked(); + mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources); } void PointerController::updatePointerIcon(int32_t iconId) { - AutoMutex _l(mLock); - if (mLocked.requestedPointerType != iconId) { - mLocked.requestedPointerType = iconId; - mLocked.presentationChanged = true; - updatePointerLocked(); - } + std::scoped_lock lock(mLock); + mCursorController.updatePointerIcon(iconId); } void PointerController::setCustomPointerIcon(const SpriteIcon& icon) { - AutoMutex _l(mLock); - - const int32_t iconId = mPolicy->getCustomPointerIconId(); - mLocked.additionalMouseResources[iconId] = icon; - mLocked.requestedPointerType = iconId; - mLocked.presentationChanged = true; - - updatePointerLocked(); -} - -void PointerController::MessageHandler::handleMessage(const Message& message) { - std::shared_ptr<PointerController> controller = pointerController.lock(); - - if (controller == nullptr) { - ALOGE("PointerController instance was released before processing message: what=%d", - message.what); - return; - } - switch (message.what) { - case MSG_INACTIVITY_TIMEOUT: - controller->doInactivityTimeout(); - break; - } -} - -int PointerController::LooperCallback::handleEvent(int /* fd */, int events, void* /* data */) { - std::shared_ptr<PointerController> controller = pointerController.lock(); - if (controller == nullptr) { - ALOGW("PointerController instance was released with pending callbacks. events=0x%x", - events); - return 0; // Remove the callback, the PointerController is gone anyways - } - if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { - ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events); - return 0; // remove the callback - } - - if (!(events & Looper::EVENT_INPUT)) { - ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events); - return 1; // keep the callback - } - - bool gotVsync = false; - ssize_t n; - nsecs_t timestamp; - DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; - while ((n = controller->mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { - for (size_t i = 0; i < static_cast<size_t>(n); ++i) { - if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { - timestamp = buf[i].header.timestamp; - gotVsync = true; - } - } - } - if (gotVsync) { - controller->doAnimate(timestamp); - } - return 1; // keep the callback + std::scoped_lock lock(mLock); + mCursorController.setCustomPointerIcon(icon); } void PointerController::doAnimate(nsecs_t timestamp) { - AutoMutex _l(mLock); - - mLocked.animationPending = false; + std::scoped_lock lock(mLock); - bool keepFading = doFadingAnimationLocked(timestamp); - bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp); - if (keepFading || keepBitmapFlipping) { - startAnimationLocked(); - } -} + mContext.setAnimationPending(false); -bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) { - bool keepAnimating = false; - nsecs_t frameDelay = timestamp - mLocked.animationTime; + bool keepFading = false; + keepFading = mCursorController.doFadingAnimation(timestamp, keepFading); - // Animate pointer fade. - if (mLocked.pointerFadeDirection < 0) { - mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION; - if (mLocked.pointerAlpha <= 0.0f) { - mLocked.pointerAlpha = 0.0f; - mLocked.pointerFadeDirection = 0; - } else { - keepAnimating = true; - } - updatePointerLocked(); - } else if (mLocked.pointerFadeDirection > 0) { - mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION; - if (mLocked.pointerAlpha >= 1.0f) { - mLocked.pointerAlpha = 1.0f; - mLocked.pointerFadeDirection = 0; - } else { - keepAnimating = true; - } - updatePointerLocked(); + for (auto& [displayID, spotController] : mLocked.spotControllers) { + keepFading = spotController.doFadingAnimation(timestamp, keepFading); } - // Animate spots that are fading out and being removed. - for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) { - std::vector<Spot*>& spots = it->second; - size_t numSpots = spots.size(); - for (size_t i = 0; i < numSpots;) { - Spot* spot = spots[i]; - if (spot->id == Spot::INVALID_ID) { - spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; - if (spot->alpha <= 0) { - spots.erase(spots.begin() + i); - releaseSpotLocked(spot); - numSpots--; - continue; - } else { - spot->sprite->setAlpha(spot->alpha); - keepAnimating = true; - } - } - ++i; - } - - if (spots.size() == 0) { - it = mLocked.spotsByDisplay.erase(it); - } else { - ++it; - } - } - - return keepAnimating; -} - -bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) { - std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find( - mLocked.requestedPointerType); - if (iter == mLocked.animationResources.end()) { - return false; - } - - if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) { - mSpriteController->openTransaction(); - - int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame; - mLocked.animationFrameIndex += incr; - mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr; - while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) { - mLocked.animationFrameIndex -= iter->second.animationFrames.size(); - } - mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]); - - mSpriteController->closeTransaction(); + bool keepBitmapFlipping = mCursorController.doBitmapAnimation(timestamp); + if (keepFading || keepBitmapFlipping) { + mContext.startAnimation(); } - - // Keep animating. - return true; } void PointerController::doInactivityTimeout() { fade(Transition::GRADUAL); } -void PointerController::startAnimationLocked() { - if (!mLocked.animationPending) { - mLocked.animationPending = true; - mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC); - mDisplayEventReceiver.requestNextVsync(); - } -} - -void PointerController::resetInactivityTimeoutLocked() { - mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT); - - nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT - ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT - : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL; - mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT); -} - -void PointerController::removeInactivityTimeoutLocked() { - mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT); -} - -void PointerController::updatePointerLocked() REQUIRES(mLock) { - if (!mLocked.viewport.isValid()) { - return; - } - - mSpriteController->openTransaction(); - - mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER); - mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY); - mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId); - - if (mLocked.pointerAlpha > 0) { - mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha); - mLocked.pointerSprite->setVisible(true); - } else { - mLocked.pointerSprite->setVisible(false); - } - - if (mLocked.pointerIconChanged || mLocked.presentationChanged) { - if (mLocked.presentation == Presentation::POINTER) { - if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) { - mLocked.pointerSprite->setIcon(mLocked.pointerIcon); - } else { - std::map<int32_t, SpriteIcon>::const_iterator iter = - mLocked.additionalMouseResources.find(mLocked.requestedPointerType); - if (iter != mLocked.additionalMouseResources.end()) { - std::map<int32_t, PointerAnimation>::const_iterator anim_iter = - mLocked.animationResources.find(mLocked.requestedPointerType); - if (anim_iter != mLocked.animationResources.end()) { - mLocked.animationFrameIndex = 0; - mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC); - startAnimationLocked(); - } - mLocked.pointerSprite->setIcon(iter->second); - } else { - ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType); - mLocked.pointerSprite->setIcon(mLocked.pointerIcon); - } - } - } else { - mLocked.pointerSprite->setIcon(mResources.spotAnchor); - } - mLocked.pointerIconChanged = false; - mLocked.presentationChanged = false; - } - - mSpriteController->closeTransaction(); -} - -PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) { - for (size_t i = 0; i < spots.size(); i++) { - Spot* spot = spots[i]; - if (spot->id == id) { - return spot; - } +void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) { + std::unordered_set<int32_t> displayIdSet; + for (DisplayViewport viewport : viewports) { + displayIdSet.insert(viewport.displayId); } - return nullptr; -} - -PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id, - std::vector<Spot*>& spots) { - // Remove spots until we have fewer than MAX_SPOTS remaining. - while (spots.size() >= MAX_SPOTS) { - Spot* spot = removeFirstFadingSpotLocked(spots); - if (!spot) { - spot = spots[0]; - spots.erase(spots.begin()); - } - releaseSpotLocked(spot); - } - - // Obtain a sprite from the recycled pool. - sp<Sprite> sprite; - if (! mLocked.recycledSprites.empty()) { - sprite = mLocked.recycledSprites.back(); - mLocked.recycledSprites.pop_back(); - } else { - sprite = mSpriteController->createSprite(); - } - - // Return the new spot. - Spot* spot = new Spot(id, sprite); - spots.push_back(spot); - return spot; -} - -PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) { - for (size_t i = 0; i < spots.size(); i++) { - Spot* spot = spots[i]; - if (spot->id == Spot::INVALID_ID) { - spots.erase(spots.begin() + i); - return spot; - } - } - return nullptr; -} - -void PointerController::releaseSpotLocked(Spot* spot) { - spot->sprite->clearIcon(); - - if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { - mLocked.recycledSprites.push_back(spot->sprite); - } - - delete spot; -} - -void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) { - if (spot->id != Spot::INVALID_ID) { - spot->id = Spot::INVALID_ID; - startAnimationLocked(); - } -} - -void PointerController::fadeOutAndReleaseAllSpotsLocked() { - for (auto& it : mLocked.spotsByDisplay) { - const std::vector<Spot*>& spots = it.second; - size_t numSpots = spots.size(); - for (size_t i = 0; i < numSpots; i++) { - Spot* spot = spots[i]; - fadeOutAndReleaseSpotLocked(spot); - } - } -} - -void PointerController::loadResourcesLocked() REQUIRES(mLock) { - if (!mLocked.viewport.isValid()) { - return; - } - - mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId); - mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId); - - mLocked.additionalMouseResources.clear(); - mLocked.animationResources.clear(); - if (mLocked.presentation == Presentation::POINTER) { - mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, - &mLocked.animationResources, mLocked.viewport.displayId); - } - - mLocked.pointerIconChanged = true; -} - - -// --- PointerController::Spot --- - -void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y, - int32_t displayId) { - sprite->setLayer(Sprite::BASE_LAYER_SPOT + id); - sprite->setAlpha(alpha); - sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale)); - sprite->setPosition(x, y); - sprite->setDisplayId(displayId); - this->x = x; - this->y = y; - - if (icon != lastIcon) { - lastIcon = icon; - if (icon) { - sprite->setIcon(*icon); - sprite->setVisible(true); + std::scoped_lock lock(mLock); + for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) { + int32_t displayID = it->first; + if (!displayIdSet.count(displayID)) { + it = mLocked.spotControllers.erase(it); } else { - sprite->setVisible(false); + ++it; } } } diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 14c0679654c6..1f561da333b1 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -30,48 +30,14 @@ #include <memory> #include <vector> +#include "MouseCursorController.h" +#include "PointerControllerContext.h" #include "SpriteController.h" +#include "TouchSpotController.h" namespace android { /* - * Pointer resources. - */ -struct PointerResources { - SpriteIcon spotHover; - SpriteIcon spotTouch; - SpriteIcon spotAnchor; -}; - -struct PointerAnimation { - std::vector<SpriteIcon> animationFrames; - nsecs_t durationPerFrame; -}; - -/* - * Pointer controller policy interface. - * - * The pointer controller policy is used by the pointer controller to interact with - * the Window Manager and other system components. - * - * The actual implementation is partially supported by callbacks into the DVM - * via JNI. This interface is also mocked in the unit tests. - */ -class PointerControllerPolicyInterface : public virtual RefBase { -protected: - PointerControllerPolicyInterface() { } - virtual ~PointerControllerPolicyInterface() { } - -public: - virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0; - virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0; - virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, - std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0; - virtual int32_t getDefaultPointerIconId() = 0; - virtual int32_t getCustomPointerIconId() = 0; -}; - -/* * Tracks pointer movements and draws the pointer sprite to a surface. * * Handles pointer acceleration and animation. @@ -81,15 +47,10 @@ public: static std::shared_ptr<PointerController> create( const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, const sp<SpriteController>& spriteController); - enum class InactivityTimeout { - NORMAL = 0, - SHORT = 1, - }; - virtual ~PointerController(); + virtual ~PointerController() = default; - virtual bool getBounds(float* outMinX, float* outMinY, - float* outMaxX, float* outMaxY) const; + virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; virtual void move(float deltaX, float deltaY); virtual void setButtonState(int32_t buttonState); virtual int32_t getButtonState() const; @@ -101,129 +62,37 @@ public: virtual void setDisplayViewport(const DisplayViewport& viewport); virtual void setPresentation(Presentation presentation); - virtual void setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId); + virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits, int32_t displayId); virtual void clearSpots(); void updatePointerIcon(int32_t iconId); void setCustomPointerIcon(const SpriteIcon& icon); void setInactivityTimeout(InactivityTimeout inactivityTimeout); + void doInactivityTimeout(); + void doAnimate(nsecs_t timestamp); void reloadPointerResources(); + void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports); private: - static constexpr size_t MAX_RECYCLED_SPRITES = 12; - static constexpr size_t MAX_SPOTS = 12; - - enum { - MSG_INACTIVITY_TIMEOUT, - }; - - struct Spot { - static const uint32_t INVALID_ID = 0xffffffff; - - uint32_t id; - sp<Sprite> sprite; - float alpha; - float scale; - float x, y; - - inline Spot(uint32_t id, const sp<Sprite>& sprite) - : id(id), - sprite(sprite), - alpha(1.0f), - scale(1.0f), - x(0.0f), - y(0.0f), - lastIcon(nullptr) {} - - void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId); + friend PointerControllerContext::LooperCallback; + friend PointerControllerContext::MessageHandler; - private: - const SpriteIcon* lastIcon; - }; + mutable std::mutex mLock; - class MessageHandler : public virtual android::MessageHandler { - public: - void handleMessage(const Message& message) override; - std::weak_ptr<PointerController> pointerController; - }; + PointerControllerContext mContext; - class LooperCallback : public virtual android::LooperCallback { - public: - int handleEvent(int fd, int events, void* data) override; - std::weak_ptr<PointerController> pointerController; - }; - - mutable Mutex mLock; - - sp<PointerControllerPolicyInterface> mPolicy; - sp<Looper> mLooper; - sp<SpriteController> mSpriteController; - sp<MessageHandler> mHandler; - sp<LooperCallback> mCallback; - - DisplayEventReceiver mDisplayEventReceiver; - - PointerResources mResources; + MouseCursorController mCursorController; struct Locked { - bool animationPending; - nsecs_t animationTime; - - size_t animationFrameIndex; - nsecs_t lastFrameUpdatedTime; - - DisplayViewport viewport; - - InactivityTimeout inactivityTimeout; - Presentation presentation; - bool presentationChanged; - - int32_t pointerFadeDirection; - float pointerX; - float pointerY; - float pointerAlpha; - sp<Sprite> pointerSprite; - SpriteIcon pointerIcon; - bool pointerIconChanged; - - std::map<int32_t, SpriteIcon> additionalMouseResources; - std::map<int32_t, PointerAnimation> animationResources; - int32_t requestedPointerType; - - int32_t buttonState; - - std::map<int32_t /* displayId */, std::vector<Spot*>> spotsByDisplay; - std::vector<sp<Sprite>> recycledSprites; + std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers; } mLocked GUARDED_BY(mLock); PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, const sp<SpriteController>& spriteController); - - bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; - void setPositionLocked(float x, float y); - - void doAnimate(nsecs_t timestamp); - bool doFadingAnimationLocked(nsecs_t timestamp); - bool doBitmapAnimationLocked(nsecs_t timestamp); - void doInactivityTimeout(); - - void startAnimationLocked(); - - void resetInactivityTimeoutLocked(); - void removeInactivityTimeoutLocked(); - void updatePointerLocked(); - - Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots); - Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots); - Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots); - void releaseSpotLocked(Spot* spot); - void fadeOutAndReleaseSpotLocked(Spot* spot); - void fadeOutAndReleaseAllSpotsLocked(); - - void loadResourcesLocked(); + void clearSpotsLocked(); }; } // namespace android diff --git a/libs/input/PointerControllerContext.cpp b/libs/input/PointerControllerContext.cpp new file mode 100644 index 000000000000..2d7e22b01112 --- /dev/null +++ b/libs/input/PointerControllerContext.cpp @@ -0,0 +1,179 @@ +/* + * 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. + */ + +#include "PointerControllerContext.h" +#include "PointerController.h" + +namespace { +// Time to wait before starting the fade when the pointer is inactive. +const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds +const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds + +// The number of events to be read at once for DisplayEventReceiver. +const int EVENT_BUFFER_SIZE = 100; +} // namespace + +namespace android { + +// --- PointerControllerContext --- + +PointerControllerContext::PointerControllerContext( + const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, + const sp<SpriteController>& spriteController, PointerController& controller) + : mPolicy(policy), + mLooper(looper), + mSpriteController(spriteController), + mHandler(new MessageHandler()), + mCallback(new LooperCallback()), + mController(controller) { + std::scoped_lock lock(mLock); + mLocked.inactivityTimeout = InactivityTimeout::NORMAL; + mLocked.animationPending = false; +} + +PointerControllerContext::~PointerControllerContext() { + mLooper->removeMessages(mHandler); +} + +void PointerControllerContext::setInactivityTimeout(InactivityTimeout inactivityTimeout) { + std::scoped_lock lock(mLock); + + if (mLocked.inactivityTimeout != inactivityTimeout) { + mLocked.inactivityTimeout = inactivityTimeout; + resetInactivityTimeoutLocked(); + } +} + +void PointerControllerContext::startAnimation() { + std::scoped_lock lock(mLock); + if (!mLocked.animationPending) { + mLocked.animationPending = true; + mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC); + mDisplayEventReceiver.requestNextVsync(); + } +} + +void PointerControllerContext::resetInactivityTimeout() { + std::scoped_lock lock(mLock); + resetInactivityTimeoutLocked(); +} + +void PointerControllerContext::resetInactivityTimeoutLocked() REQUIRES(mLock) { + mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT); + + nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT + ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT + : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL; + mLooper->sendMessageDelayed(timeout, mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT); +} + +void PointerControllerContext::removeInactivityTimeout() { + std::scoped_lock lock(mLock); + mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT); +} + +void PointerControllerContext::setAnimationPending(bool animationPending) { + std::scoped_lock lock(mLock); + mLocked.animationPending = animationPending; +} + +nsecs_t PointerControllerContext::getAnimationTime() { + std::scoped_lock lock(mLock); + return mLocked.animationTime; +} + +void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) { + mHandler->pointerController = controller; +} + +void PointerControllerContext::setCallbackController( + std::shared_ptr<PointerController> controller) { + mCallback->pointerController = controller; +} + +sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() { + return mPolicy; +} + +sp<SpriteController> PointerControllerContext::getSpriteController() { + return mSpriteController; +} + +void PointerControllerContext::initializeDisplayEventReceiver() { + if (mDisplayEventReceiver.initCheck() == NO_ERROR) { + mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, Looper::EVENT_INPUT, + mCallback, nullptr); + } else { + ALOGE("Failed to initialize DisplayEventReceiver."); + } +} + +void PointerControllerContext::handleDisplayEvents() { + bool gotVsync = false; + ssize_t n; + nsecs_t timestamp; + DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; + while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { + for (size_t i = 0; i < static_cast<size_t>(n); ++i) { + if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { + timestamp = buf[i].header.timestamp; + gotVsync = true; + } + } + } + if (gotVsync) { + mController.doAnimate(timestamp); + } +} + +void PointerControllerContext::MessageHandler::handleMessage(const Message& message) { + std::shared_ptr<PointerController> controller = pointerController.lock(); + + if (controller == nullptr) { + ALOGE("PointerController instance was released before processing message: what=%d", + message.what); + return; + } + switch (message.what) { + case MSG_INACTIVITY_TIMEOUT: + controller->doInactivityTimeout(); + break; + } +} + +int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int events, + void* /* data */) { + std::shared_ptr<PointerController> controller = pointerController.lock(); + if (controller == nullptr) { + ALOGW("PointerController instance was released with pending callbacks. events=0x%x", + events); + return 0; // Remove the callback, the PointerController is gone anyways + } + if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { + ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events); + return 0; // remove the callback + } + + if (!(events & Looper::EVENT_INPUT)) { + ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events); + return 1; // keep the callback + } + + controller->mContext.handleDisplayEvents(); + return 1; // keep the callback +} + +} // namespace android diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h new file mode 100644 index 000000000000..92e1bda25f56 --- /dev/null +++ b/libs/input/PointerControllerContext.h @@ -0,0 +1,154 @@ +/* + * 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 _UI_POINTER_CONTROLLER_CONTEXT_H +#define _UI_POINTER_CONTROLLER_CONTEXT_H + +#include <PointerControllerInterface.h> +#include <gui/DisplayEventReceiver.h> +#include <input/DisplayViewport.h> +#include <input/Input.h> +#include <ui/DisplayInfo.h> +#include <utils/BitSet.h> +#include <utils/Looper.h> +#include <utils/RefBase.h> + +#include <map> +#include <memory> +#include <vector> + +#include "SpriteController.h" + +namespace android { + +class PointerController; + +/* + * Pointer resources. + */ +struct PointerResources { + SpriteIcon spotHover; + SpriteIcon spotTouch; + SpriteIcon spotAnchor; +}; + +struct PointerAnimation { + std::vector<SpriteIcon> animationFrames; + nsecs_t durationPerFrame; +}; + +enum class InactivityTimeout { + NORMAL = 0, + SHORT = 1, +}; + +/* + * Pointer controller policy interface. + * + * The pointer controller policy is used by the pointer controller to interact with + * the Window Manager and other system components. + * + * The actual implementation is partially supported by callbacks into the DVM + * via JNI. This interface is also mocked in the unit tests. + */ +class PointerControllerPolicyInterface : public virtual RefBase { +protected: + PointerControllerPolicyInterface() {} + virtual ~PointerControllerPolicyInterface() {} + +public: + virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0; + virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0; + virtual void loadAdditionalMouseResources( + std::map<int32_t, SpriteIcon>* outResources, + std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0; + virtual int32_t getDefaultPointerIconId() = 0; + virtual int32_t getCustomPointerIconId() = 0; +}; + +/* + * Contains logic and resources shared among PointerController, + * MouseCursorController, and TouchSpotController. + */ + +class PointerControllerContext { +public: + PointerControllerContext(const sp<PointerControllerPolicyInterface>& policy, + const sp<Looper>& looper, const sp<SpriteController>& spriteController, + PointerController& controller); + ~PointerControllerContext(); + + void removeInactivityTimeout(); + void resetInactivityTimeout(); + void startAnimation(); + void setInactivityTimeout(InactivityTimeout inactivityTimeout); + + void setAnimationPending(bool animationPending); + nsecs_t getAnimationTime(); + + void clearSpotsByDisplay(int32_t displayId); + + void setHandlerController(std::shared_ptr<PointerController> controller); + void setCallbackController(std::shared_ptr<PointerController> controller); + + sp<PointerControllerPolicyInterface> getPolicy(); + sp<SpriteController> getSpriteController(); + + void initializeDisplayEventReceiver(); + void handleDisplayEvents(); + + class MessageHandler : public virtual android::MessageHandler { + public: + enum { + MSG_INACTIVITY_TIMEOUT, + }; + + void handleMessage(const Message& message) override; + std::weak_ptr<PointerController> pointerController; + }; + + class LooperCallback : public virtual android::LooperCallback { + public: + int handleEvent(int fd, int events, void* data) override; + std::weak_ptr<PointerController> pointerController; + }; + +private: + sp<PointerControllerPolicyInterface> mPolicy; + sp<Looper> mLooper; + sp<SpriteController> mSpriteController; + sp<MessageHandler> mHandler; + sp<LooperCallback> mCallback; + + DisplayEventReceiver mDisplayEventReceiver; + + PointerController& mController; + + mutable std::mutex mLock; + + struct Locked { + bool animationPending; + nsecs_t animationTime; + + InactivityTimeout inactivityTimeout; + } mLocked GUARDED_BY(mLock); + + void resetInactivityTimeoutLocked(); +}; + +} // namespace android + +#endif // _UI_POINTER_CONTROLLER_CONTEXT_H diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp new file mode 100644 index 000000000000..c7430ceead41 --- /dev/null +++ b/libs/input/TouchSpotController.cpp @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#define LOG_TAG "TouchSpotController" + +// Log debug messages about pointer updates +#define DEBUG_SPOT_UPDATES 0 + +#include "TouchSpotController.h" + +#include <log/log.h> + +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkColor.h> +#include <SkPaint.h> + +namespace { +// Time to spend fading out the spot completely. +const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms +} // namespace + +namespace android { + +// --- Spot --- + +void TouchSpotController::Spot::updateSprite(const SpriteIcon* icon, float x, float y, + int32_t displayId) { + sprite->setLayer(Sprite::BASE_LAYER_SPOT + id); + sprite->setAlpha(alpha); + sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale)); + sprite->setPosition(x, y); + sprite->setDisplayId(displayId); + this->x = x; + this->y = y; + + if (icon != mLastIcon) { + mLastIcon = icon; + if (icon) { + sprite->setIcon(*icon); + sprite->setVisible(true); + } else { + sprite->setVisible(false); + } + } +} + +// --- TouchSpotController --- + +TouchSpotController::TouchSpotController(int32_t displayId, PointerControllerContext& context) + : mDisplayId(displayId), mContext(context) { + mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId); +} + +TouchSpotController::~TouchSpotController() { + std::scoped_lock lock(mLock); + + size_t numSpots = mLocked.displaySpots.size(); + for (size_t i = 0; i < numSpots; i++) { + delete mLocked.displaySpots[i]; + } + mLocked.displaySpots.clear(); +} + +void TouchSpotController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits) { +#if DEBUG_SPOT_UPDATES + ALOGD("setSpots: idBits=%08x", spotIdBits.value); + for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + const PointerCoords& c = spotCoords[spotIdToIndex[id]]; + ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id, + c.getAxisValue(AMOTION_EVENT_AXIS_X), c.getAxisValue(AMOTION_EVENT_AXIS_Y), + c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), displayId); + } +#endif + + std::scoped_lock lock(mLock); + sp<SpriteController> spriteController = mContext.getSpriteController(); + spriteController->openTransaction(); + + // Add or move spots for fingers that are down. + for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) { + uint32_t id = idBits.clearFirstMarkedBit(); + const PointerCoords& c = spotCoords[spotIdToIndex[id]]; + const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0 + ? mResources.spotTouch + : mResources.spotHover; + float x = c.getAxisValue(AMOTION_EVENT_AXIS_X); + float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y); + + Spot* spot = getSpot(id, mLocked.displaySpots); + if (!spot) { + spot = createAndAddSpotLocked(id, mLocked.displaySpots); + } + + spot->updateSprite(&icon, x, y, mDisplayId); + } + + for (Spot* spot : mLocked.displaySpots) { + if (spot->id != Spot::INVALID_ID && !spotIdBits.hasBit(spot->id)) { + fadeOutAndReleaseSpotLocked(spot); + } + } + + spriteController->closeTransaction(); +} + +void TouchSpotController::clearSpots() { +#if DEBUG_SPOT_UPDATES + ALOGD("clearSpots"); +#endif + + std::scoped_lock lock(mLock); + fadeOutAndReleaseAllSpotsLocked(); +} + +TouchSpotController::Spot* TouchSpotController::getSpot(uint32_t id, + const std::vector<Spot*>& spots) { + for (size_t i = 0; i < spots.size(); i++) { + Spot* spot = spots[i]; + if (spot->id == id) { + return spot; + } + } + return nullptr; +} + +TouchSpotController::Spot* TouchSpotController::createAndAddSpotLocked(uint32_t id, + std::vector<Spot*>& spots) { + // Remove spots until we have fewer than MAX_SPOTS remaining. + while (spots.size() >= MAX_SPOTS) { + Spot* spot = removeFirstFadingSpotLocked(spots); + if (!spot) { + spot = spots[0]; + spots.erase(spots.begin()); + } + releaseSpotLocked(spot); + } + + // Obtain a sprite from the recycled pool. + sp<Sprite> sprite; + if (!mLocked.recycledSprites.empty()) { + sprite = mLocked.recycledSprites.back(); + mLocked.recycledSprites.pop_back(); + } else { + sprite = mContext.getSpriteController()->createSprite(); + } + + // Return the new spot. + Spot* spot = new Spot(id, sprite); + spots.push_back(spot); + return spot; +} + +TouchSpotController::Spot* TouchSpotController::removeFirstFadingSpotLocked( + std::vector<Spot*>& spots) REQUIRES(mLock) { + for (size_t i = 0; i < spots.size(); i++) { + Spot* spot = spots[i]; + if (spot->id == Spot::INVALID_ID) { + spots.erase(spots.begin() + i); + return spot; + } + } + return NULL; +} + +void TouchSpotController::releaseSpotLocked(Spot* spot) REQUIRES(mLock) { + spot->sprite->clearIcon(); + + if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { + mLocked.recycledSprites.push_back(spot->sprite); + } + + delete spot; +} + +void TouchSpotController::fadeOutAndReleaseSpotLocked(Spot* spot) REQUIRES(mLock) { + if (spot->id != Spot::INVALID_ID) { + spot->id = Spot::INVALID_ID; + mContext.startAnimation(); + } +} + +void TouchSpotController::fadeOutAndReleaseAllSpotsLocked() REQUIRES(mLock) { + size_t numSpots = mLocked.displaySpots.size(); + for (size_t i = 0; i < numSpots; i++) { + Spot* spot = mLocked.displaySpots[i]; + fadeOutAndReleaseSpotLocked(spot); + } +} + +void TouchSpotController::reloadSpotResources() { + mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId); +} + +bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) { + std::scoped_lock lock(mLock); + nsecs_t animationTime = mContext.getAnimationTime(); + nsecs_t frameDelay = timestamp - animationTime; + size_t numSpots = mLocked.displaySpots.size(); + for (size_t i = 0; i < numSpots;) { + Spot* spot = mLocked.displaySpots[i]; + if (spot->id == Spot::INVALID_ID) { + spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; + if (spot->alpha <= 0) { + mLocked.displaySpots.erase(mLocked.displaySpots.begin() + i); + releaseSpotLocked(spot); + numSpots--; + continue; + } else { + spot->sprite->setAlpha(spot->alpha); + keepAnimating = true; + } + } + ++i; + } + return keepAnimating; +} + +} // namespace android diff --git a/libs/input/TouchSpotController.h b/libs/input/TouchSpotController.h new file mode 100644 index 000000000000..f3b355010bee --- /dev/null +++ b/libs/input/TouchSpotController.h @@ -0,0 +1,91 @@ +/* + * 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 _UI_TOUCH_SPOT_CONTROLLER_H +#define _UI_TOUCH_SPOT_CONTROLLER_H + +#include "PointerControllerContext.h" + +namespace android { + +/* + * Helper class for PointerController that specifically handles + * touch spot resources and actions for a single display. + */ +class TouchSpotController { +public: + TouchSpotController(int32_t displayId, PointerControllerContext& context); + ~TouchSpotController(); + void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits); + void clearSpots(); + + void reloadSpotResources(); + bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating); + +private: + struct Spot { + static const uint32_t INVALID_ID = 0xffffffff; + + uint32_t id; + sp<Sprite> sprite; + float alpha; + float scale; + float x, y; + + inline Spot(uint32_t id, const sp<Sprite>& sprite) + : id(id), + sprite(sprite), + alpha(1.0f), + scale(1.0f), + x(0.0f), + y(0.0f), + mLastIcon(nullptr) {} + + void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId); + + private: + const SpriteIcon* mLastIcon; + }; + + int32_t mDisplayId; + + mutable std::mutex mLock; + + PointerResources mResources; + + PointerControllerContext& mContext; + + static constexpr size_t MAX_RECYCLED_SPRITES = 12; + static constexpr size_t MAX_SPOTS = 12; + + struct Locked { + std::vector<Spot*> displaySpots; + std::vector<sp<Sprite>> recycledSprites; + + } mLocked GUARDED_BY(mLock); + + Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots); + Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots); + Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots); + void releaseSpotLocked(Spot* spot); + void fadeOutAndReleaseSpotLocked(Spot* spot); + void fadeOutAndReleaseAllSpotsLocked(); +}; + +} // namespace android + +#endif // _UI_TOUCH_SPOT_CONTROLLER_H diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp index 6e129a064385..b67088a389b6 100644 --- a/libs/input/tests/PointerController_test.cpp +++ b/libs/input/tests/PointerController_test.cpp @@ -178,9 +178,6 @@ void PointerControllerTest::ensureDisplayViewportIsSet() { viewport.deviceWidth = 400; viewport.deviceHeight = 300; mPointerController->setDisplayViewport(viewport); - - // The first call to setDisplayViewport should trigger the loading of the necessary resources. - EXPECT_TRUE(mPolicy->allResourcesAreLoaded()); } void PointerControllerTest::loopThread() { @@ -208,6 +205,7 @@ TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) { TEST_F(PointerControllerTest, updatePointerIcon) { ensureDisplayViewportIsSet(); + mPointerController->setPresentation(PointerController::Presentation::POINTER); mPointerController->unfade(PointerController::Transition::IMMEDIATE); int32_t type = CURSOR_TYPE_ADDITIONAL; @@ -247,8 +245,6 @@ TEST_F(PointerControllerTest, setCustomPointerIcon) { TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) { mPointerController->setPresentation(PointerController::Presentation::POINTER); - mPointerController->setSpots(nullptr, nullptr, BitSet32(), -1); - mPointerController->clearSpots(); mPointerController->setPosition(1.0f, 1.0f); mPointerController->move(1.0f, 1.0f); mPointerController->unfade(PointerController::Transition::IMMEDIATE); diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 52e266129875..40d213fe418b 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -590,7 +590,7 @@ android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz) ALOGV("getSyncSettings: %d %d %f %f", scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate); - // sanity check params + // check params if (scp.sync.mSource >= AVSYNC_SOURCE_MAX || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX || scp.sync.mTolerance < 0.f diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp index f75200868a0d..d1ce30a3e827 100644 --- a/media/jni/android_media_MediaSync.cpp +++ b/media/jni/android_media_MediaSync.cpp @@ -451,7 +451,7 @@ static jobject android_media_MediaSync_getSyncParams(JNIEnv *env, jobject thiz) ALOGV("getSyncParams: %d %d %f %f", scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate); - // sanity check params + // check params if (scs.sync.mSource >= AVSYNC_SOURCE_MAX || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX || scs.sync.mTolerance < 0.f diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp index f4d65d0a397f..f419904afa69 100644 --- a/media/jni/audioeffect/Visualizer.cpp +++ b/media/jni/audioeffect/Visualizer.cpp @@ -34,21 +34,9 @@ namespace android { // --------------------------------------------------------------------------- -Visualizer::Visualizer (const String16& opPackageName, - int32_t priority, - effect_callback_t cbf, - void* user, - audio_session_t sessionId) - : AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId), - mCaptureRate(CAPTURE_RATE_DEF), - mCaptureSize(CAPTURE_SIZE_DEF), - mSampleRate(44100000), - mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED), - mMeasurementMode(MEASUREMENT_MODE_NONE), - mCaptureCallBack(NULL), - mCaptureCbkUser(NULL) +Visualizer::Visualizer (const String16& opPackageName) + : AudioEffect(opPackageName) { - initCaptureSize(); } Visualizer::~Visualizer() @@ -58,6 +46,22 @@ Visualizer::~Visualizer() setCaptureCallBack(NULL, NULL, 0, 0); } +status_t Visualizer::set(int32_t priority, + effect_callback_t cbf, + void* user, + audio_session_t sessionId, + audio_io_handle_t io, + const AudioDeviceTypeAddr& device) +{ + status_t status = AudioEffect::set( + SL_IID_VISUALIZATION, nullptr, priority, cbf, user, sessionId, io, device); + if (status == NO_ERROR || status == ALREADY_EXISTS) { + initCaptureSize(); + } + return status; +} + + void Visualizer::release() { ALOGV("Visualizer::release()"); diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h index d4672a95c6d8..b943b96053f9 100644 --- a/media/jni/audioeffect/Visualizer.h +++ b/media/jni/audioeffect/Visualizer.h @@ -65,14 +65,21 @@ public: /* Constructor. * See AudioEffect constructor for details on parameters. */ - Visualizer(const String16& opPackageName, - int32_t priority = 0, - effect_callback_t cbf = NULL, - void* user = NULL, - audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX); + explicit Visualizer(const String16& opPackageName); ~Visualizer(); + /** + * Initialize an uninitialized Visualizer. + * See AudioEffect 'set' function for details on parameters. + */ + status_t set(int32_t priority = 0, + effect_callback_t cbf = NULL, + void* user = NULL, + audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX, + audio_io_handle_t io = AUDIO_IO_HANDLE_NONE, + const AudioDeviceTypeAddr& device = {}); + // Declared 'final' because we call this in ~Visualizer(). status_t setEnabled(bool enabled) final; @@ -163,15 +170,15 @@ private: uint32_t initCaptureSize(); Mutex mCaptureLock; - uint32_t mCaptureRate; - uint32_t mCaptureSize; - uint32_t mSampleRate; - uint32_t mScalingMode; - uint32_t mMeasurementMode; - capture_cbk_t mCaptureCallBack; - void *mCaptureCbkUser; + uint32_t mCaptureRate = CAPTURE_RATE_DEF; + uint32_t mCaptureSize = CAPTURE_SIZE_DEF; + uint32_t mSampleRate = 44100000; + uint32_t mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED; + uint32_t mMeasurementMode = MEASUREMENT_MODE_NONE; + capture_cbk_t mCaptureCallBack = nullptr; + void *mCaptureCbkUser = nullptr; sp<CaptureThread> mCaptureThread; - uint32_t mCaptureFlags; + uint32_t mCaptureFlags = 0; }; diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index 007dd10aba1f..501e47febf7f 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -337,20 +337,20 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t } // create the native AudioEffect object - lpAudioEffect = new AudioEffect(typeStr, - String16(opPackageNameStr.c_str()), - uuidStr, - priority, - effectCallback, - &lpJniStorage->mCallbackData, - (audio_session_t) sessionId, - AUDIO_IO_HANDLE_NONE, - device); + lpAudioEffect = new AudioEffect(String16(opPackageNameStr.c_str())); if (lpAudioEffect == 0) { ALOGE("Error creating AudioEffect"); goto setup_failure; } + lpAudioEffect->set(typeStr, + uuidStr, + priority, + effectCallback, + &lpJniStorage->mCallbackData, + (audio_session_t) sessionId, + AUDIO_IO_HANDLE_NONE, + device); lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck()); if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) { ALOGE("AudioEffect initCheck failed %d", lStatus); diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index f9a77f474c50..4c5970a30a05 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -382,15 +382,15 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th } // create the native Visualizer object - lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()), - 0, - android_media_visualizer_effect_callback, - lpJniStorage, - (audio_session_t) sessionId); + lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str())); if (lpVisualizer == 0) { ALOGE("Error creating Visualizer"); goto setup_failure; } + lpVisualizer->set(0, + android_media_visualizer_effect_callback, + lpJniStorage, + (audio_session_t) sessionId); lStatus = translateError(lpVisualizer->initCheck()); if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) { diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java b/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java index ce81a18eeaa8..ab9ae8ab2ac8 100644 --- a/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java +++ b/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java @@ -43,7 +43,7 @@ public class FilterFunction { public Frame execute(KeyValueMap inputMap) { int filterOutCount = mFilter.getNumberOfOutputs(); - // Sanity checks + // Validation checks if (filterOutCount > 1) { throw new RuntimeException("Calling execute on filter " + mFilter + " with multiple " + "outputs! Use executeMulti() instead!"); diff --git a/media/mca/filterfw/jni/jni_native_program.cpp b/media/mca/filterfw/jni/jni_native_program.cpp index 14246078225e..cd4f7187c250 100644 --- a/media/mca/filterfw/jni/jni_native_program.cpp +++ b/media/mca/filterfw/jni/jni_native_program.cpp @@ -134,7 +134,7 @@ jboolean Java_android_filterfw_core_NativeProgram_callNativeProcess(JNIEnv* env, jobject output) { NativeProgram* program = ConvertFromJava<NativeProgram>(env, thiz); - // Sanity checks + // Validation checks if (!program || !inputs) { return JNI_FALSE; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java index 0ae640dd7910..e74bda8a6b35 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java @@ -16,16 +16,6 @@ package com.android.mediaframeworktest.helpers; -import com.android.ex.camera2.blocking.BlockingCameraManager; -import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException; -import com.android.ex.camera2.blocking.BlockingSessionCallback; -import com.android.ex.camera2.blocking.BlockingStateCallback; -import com.android.ex.camera2.exceptions.TimeoutRuntimeException; - -import junit.framework.Assert; - -import org.mockito.Mockito; - import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; @@ -64,6 +54,16 @@ import android.view.WindowManager; import androidx.test.InstrumentationRegistry; +import com.android.ex.camera2.blocking.BlockingCameraManager; +import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException; +import com.android.ex.camera2.blocking.BlockingSessionCallback; +import com.android.ex.camera2.blocking.BlockingStateCallback; +import com.android.ex.camera2.exceptions.TimeoutRuntimeException; + +import junit.framework.Assert; + +import org.mockito.Mockito; + import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Array; @@ -77,8 +77,8 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -225,7 +225,7 @@ public class CameraTestUtils extends Assert { } /** - * Dummy listener that release the image immediately once it is available. + * Mock listener that release the image immediately once it is available. * * <p> * It can be used for the case where we don't care the image data at all. diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java index 96b0424595e3..a77b2898c5e0 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java @@ -22,7 +22,7 @@ import java.util.Objects; /** * Helper set of methods to perform precondition checks before starting method execution. * - * <p>Typically used to sanity check arguments or the current object state.</p> + * <p>Typically used to check arguments or the current object state.</p> */ /** * (non-Javadoc) diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java index b3f443b30a70..9a64b58a080d 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java @@ -16,7 +16,7 @@ package com.android.mediaframeworktest.helpers; -import junit.framework.Assert; +import static com.android.mediaframeworktest.helpers.AssertHelpers.assertArrayContainsAnyOf; import android.graphics.ImageFormat; import android.graphics.Rect; @@ -31,6 +31,8 @@ import android.util.Range; import android.util.Rational; import android.util.Size; +import junit.framework.Assert; + import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; @@ -40,8 +42,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import static com.android.mediaframeworktest.helpers.AssertHelpers.assertArrayContainsAnyOf; - /** * Helpers to get common static info out of the camera. * @@ -435,7 +435,7 @@ public class StaticMetadata { } /** - * Get max AE regions and do sanity check. + * Get max AE regions and do validation check. * * @return AE max regions supported by the camera device */ @@ -448,7 +448,7 @@ public class StaticMetadata { } /** - * Get max AWB regions and do sanity check. + * Get max AWB regions and do validation check. * * @return AWB max regions supported by the camera device */ @@ -461,7 +461,7 @@ public class StaticMetadata { } /** - * Get max AF regions and do sanity check. + * Get max AF regions and do validation check. * * @return AF max regions supported by the camera device */ @@ -545,7 +545,7 @@ public class StaticMetadata { } /** - * Get available thumbnail sizes and do the sanity check. + * Get available thumbnail sizes and do the validation check. * * @return The array of available thumbnail sizes */ @@ -573,7 +573,7 @@ public class StaticMetadata { } /** - * Get available focal lengths and do the sanity check. + * Get available focal lengths and do the validation check. * * @return The array of available focal lengths */ @@ -594,7 +594,7 @@ public class StaticMetadata { } /** - * Get available apertures and do the sanity check. + * Get available apertures and do the validation check. * * @return The non-null array of available apertures */ @@ -909,7 +909,7 @@ public class StaticMetadata { } /** - * Get hyperfocalDistance and do the sanity check. + * Get hyperfocalDistance and do the validation check. * <p> * Note that, this tag is optional, will return -1 if this tag is not * available. @@ -1068,7 +1068,7 @@ public class StaticMetadata { } /** - * get android.control.availableModes and do the sanity check. + * get android.control.availableModes and do the validation check. * * @return available control modes. */ @@ -1124,7 +1124,7 @@ public class StaticMetadata { } /** - * Get aeAvailableModes and do the sanity check. + * Get aeAvailableModes and do the validation check. * * <p>Depending on the check level this class has, for WAR or COLLECT levels, * If the aeMode list is invalid, return an empty mode array. The the caller doesn't @@ -1196,7 +1196,7 @@ public class StaticMetadata { } /** - * Get available AWB modes and do the sanity check. + * Get available AWB modes and do the validation check. * * @return array that contains available AWB modes, empty array if awbAvailableModes is * unavailable. @@ -1222,7 +1222,7 @@ public class StaticMetadata { } /** - * Get available AF modes and do the sanity check. + * Get available AF modes and do the validation check. * * @return array that contains available AF modes, empty array if afAvailableModes is * unavailable. @@ -1580,7 +1580,7 @@ public class StaticMetadata { } /** - * Get value of key android.control.aeCompensationStep and do the sanity check. + * Get value of key android.control.aeCompensationStep and do the validation check. * * @return default value if the value is null. */ @@ -1605,7 +1605,7 @@ public class StaticMetadata { } /** - * Get value of key android.control.aeCompensationRange and do the sanity check. + * Get value of key android.control.aeCompensationRange and do the validation check. * * @return default value if the value is null or malformed. */ @@ -1635,7 +1635,7 @@ public class StaticMetadata { } /** - * Get availableVideoStabilizationModes and do the sanity check. + * Get availableVideoStabilizationModes and do the validation check. * * @return available video stabilization modes, empty array if it is unavailable. */ @@ -1666,7 +1666,7 @@ public class StaticMetadata { } /** - * Get availableOpticalStabilization and do the sanity check. + * Get availableOpticalStabilization and do the validation check. * * @return available optical stabilization modes, empty array if it is unavailable. */ @@ -1780,7 +1780,7 @@ public class StaticMetadata { } /** - * Get max pipeline depth and do the sanity check. + * Get max pipeline depth and do the validation check. * * @return max pipeline depth, default value if it is not available. */ @@ -1846,7 +1846,7 @@ public class StaticMetadata { /** - * Get available capabilities and do the sanity check. + * Get available capabilities and do the validation check. * * @return reported available capabilities list, empty list if the value is unavailable. */ @@ -2070,7 +2070,7 @@ public class StaticMetadata { } /** - * Get max number of output raw streams and do the basic sanity check. + * Get max number of output raw streams and do the basic validation check. * * @return reported max number of raw output stream */ @@ -2083,7 +2083,7 @@ public class StaticMetadata { } /** - * Get max number of output processed streams and do the basic sanity check. + * Get max number of output processed streams and do the basic validation check. * * @return reported max number of processed output stream */ @@ -2096,7 +2096,7 @@ public class StaticMetadata { } /** - * Get max number of output stalling processed streams and do the basic sanity check. + * Get max number of output stalling processed streams and do the basic validation check. * * @return reported max number of stalling processed output stream */ @@ -2109,7 +2109,7 @@ public class StaticMetadata { } /** - * Get lens facing and do the sanity check + * Get lens facing and do the validation check * @return lens facing, return default value (BACK) if value is unavailable. */ public int getLensFacingChecked() { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java index 31b79677f9ff..47caf0a0bc9b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java @@ -309,7 +309,7 @@ public class Camera2CaptureRequestTest extends Camera2SurfaceViewTestCase { private void changeExposure(CaptureRequest.Builder requestBuilder, long expTime, int sensitivity) { // Check if the max analog sensitivity is available and no larger than max sensitivity. - // The max analog sensitivity is not actually used here. This is only an extra sanity check. + // The max analog sensitivity is not actually used here. This is only an extra check. mStaticInfo.getMaxAnalogSensitivityChecked(); expTime = mStaticInfo.getExposureClampToRange(expTime); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java index 6a4db5791d5c..dc8da4868df3 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java @@ -985,7 +985,7 @@ public class Camera2RecordingTest extends Camera2SurfaceViewTestCase { } /** - * Validate video snapshot capture image object sanity and test. + * Validate video snapshot capture image object soundness and test. * * <p> Check for size, format and jpeg decoding</p> * diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java index f7373f7b68db..cbdcc36eea3a 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java @@ -570,7 +570,7 @@ public class Camera2StillCaptureTest extends Camera2SurfaceViewTestCase { } /** - * Validate JPEG capture image object sanity and test. + * Validate JPEG capture image object soundness and test. * <p> * In addition to image object sanity, this function also does the decoding * test, which is slower. diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index c050d0322fa2..a4863e2e22dc 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -43412,6 +43412,7 @@ package android.system { package android.telecom { public final class Call { + method public void addConferenceParticipants(@NonNull java.util.List<android.net.Uri>); method public void answer(int); method public void conference(android.telecom.Call); method public void deflect(android.net.Uri); @@ -43520,6 +43521,7 @@ package android.telecom { method public static boolean hasProperty(int, int); method public boolean hasProperty(int); method public static String propertiesToString(int); + field public static final int CAPABILITY_ADD_PARTICIPANT = 33554432; // 0x2000000 field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 @@ -43549,6 +43551,7 @@ package android.telecom { field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000 field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800 field public static final int PROPERTY_RTT = 1024; // 0x400 @@ -43626,6 +43629,7 @@ package android.telecom { public abstract class Conference extends android.telecom.Conferenceable { ctor public Conference(android.telecom.PhoneAccountHandle); method public final boolean addConnection(android.telecom.Connection); + method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle); method public final void destroy(); method public final android.telecom.CallAudioState getCallAudioState(); method public final java.util.List<android.telecom.Connection> getConferenceableConnections(); @@ -43641,6 +43645,9 @@ package android.telecom { method public final android.telecom.StatusHints getStatusHints(); method public android.telecom.Connection.VideoProvider getVideoProvider(); method public int getVideoState(); + method public final boolean isRingbackRequested(); + method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>); + method public void onAnswer(int); method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onConnectionAdded(android.telecom.Connection); method public void onDisconnect(); @@ -43649,6 +43656,7 @@ package android.telecom { method public void onMerge(android.telecom.Connection); method public void onMerge(); method public void onPlayDtmfTone(char); + method public void onReject(); method public void onSeparate(android.telecom.Connection); method public void onStopDtmfTone(); method public void onSwap(); @@ -43669,6 +43677,8 @@ package android.telecom { method public final void setDisconnected(android.telecom.DisconnectCause); method public final void setExtras(@Nullable android.os.Bundle); method public final void setOnHold(); + method public final void setRingbackRequested(boolean); + method public final void setRinging(); method public final void setStatusHints(android.telecom.StatusHints); method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider); method public final void setVideoState(android.telecom.Connection, int); @@ -43705,6 +43715,7 @@ package android.telecom { method public final boolean isRingbackRequested(); method public final void notifyConferenceMergeFailed(); method public void onAbort(); + method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>); method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); @@ -43784,6 +43795,7 @@ package android.telecom { field public static final int AUDIO_CODEC_GSM_HR = 10; // 0xa field public static final int AUDIO_CODEC_NONE = 0; // 0x0 field public static final int AUDIO_CODEC_QCELP13K = 3; // 0x3 + field public static final int CAPABILITY_ADD_PARTICIPANT = 67108864; // 0x4000000 field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000 @@ -43827,6 +43839,7 @@ package android.telecom { field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4 + field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 4096; // 0x1000 field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int PROPERTY_IS_RTT = 256; // 0x100 field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400 @@ -43922,9 +43935,13 @@ package android.telecom { method public void onConference(android.telecom.Connection, android.telecom.Connection); method public void onConnectionServiceFocusGained(); method public void onConnectionServiceFocusLost(); + method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); + method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); @@ -44235,6 +44252,7 @@ package android.telecom { method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int); method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle); + method public void addNewIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.os.Bundle); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification(); method public android.content.Intent createManageBlockedNumbersIntent(); method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall(); @@ -44262,6 +44280,7 @@ package android.telecom { method public void registerPhoneAccount(android.telecom.PhoneAccount); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger(); + method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull java.util.List<android.net.Uri>, @NonNull android.os.Bundle); method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle); field public static final String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER"; field public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; @@ -44799,6 +44818,8 @@ package android.telephony { field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool"; field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool"; + field public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool"; + field public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool"; field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool"; field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool"; diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index 28319242ef2a..df45c9ec1dee 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -9,3 +9,17 @@ package android.annotation { } +package android.os { + + public class Binder implements android.os.IBinder { + method public final void markVintfStability(); + } + + public interface Parcelable { + method public default int getStability(); + field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0 + field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1 + } + +} + diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 0b299092c433..c6314d3924bc 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -8830,10 +8830,10 @@ package android.telephony { public class SubscriptionManager { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription(); method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String); - method @NonNull public int[] getActiveAndHiddenSubscriptionIdList(); - method @NonNull public int[] getActiveSubscriptionIdList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String); method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int); method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int); diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 68da999ae786..e937a51c5b21 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -48,7 +48,7 @@ android_library { "androidx.lifecycle_lifecycle-extensions", "SystemUI-tags", "SystemUI-proto", - "dagger2-2.19", + "dagger2", "//external/kotlinc:kotlin-annotations", ], @@ -59,7 +59,7 @@ android_library { manifest: "AndroidManifest.xml", - plugins: ["dagger2-compiler-2.19"], + plugins: ["dagger2-compiler"], } @@ -100,7 +100,7 @@ android_app { kotlincflags: ["-Xjvm-default=enable"], - plugins: ["dagger2-compiler-2.19"], + plugins: ["dagger2-compiler"], required: ["privapp_whitelist_com.android.systemui"], } diff --git a/packages/DynamicSystemInstallationService/tests/res/values/strings.xml b/packages/DynamicSystemInstallationService/tests/res/values/strings.xml index fdb620bfe094..019c0c914771 100644 --- a/packages/DynamicSystemInstallationService/tests/res/values/strings.xml +++ b/packages/DynamicSystemInstallationService/tests/res/values/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <!-- testFromJsonString --> - <string name="blacklist_json_string" translatable="false"> + <string name="blocklist_json_string" translatable="false"> { \"entries\":[ { diff --git a/packages/DynamicSystemInstallationService/tests/src/com/android/dynsystem/KeyRevocationListTest.java b/packages/DynamicSystemInstallationService/tests/src/com/android/dynsystem/KeyRevocationListTest.java index 82ce542cf5de..c1233ebab2ec 100644 --- a/packages/DynamicSystemInstallationService/tests/src/com/android/dynsystem/KeyRevocationListTest.java +++ b/packages/DynamicSystemInstallationService/tests/src/com/android/dynsystem/KeyRevocationListTest.java @@ -47,32 +47,32 @@ public class KeyRevocationListTest { private static Context sContext; - private static String sBlacklistJsonString; + private static String sBlocklistJsonString; @BeforeClass public static void setUpClass() throws Exception { sContext = InstrumentationRegistry.getInstrumentation().getContext(); - sBlacklistJsonString = - sContext.getString(com.android.dynsystem.tests.R.string.blacklist_json_string); + sBlocklistJsonString = + sContext.getString(com.android.dynsystem.tests.R.string.blocklist_json_string); } @Test @SmallTest public void testFromJsonString() throws JSONException { - KeyRevocationList blacklist; - blacklist = KeyRevocationList.fromJsonString(sBlacklistJsonString); - Assert.assertNotNull(blacklist); - Assert.assertFalse(blacklist.mEntries.isEmpty()); - blacklist = KeyRevocationList.fromJsonString("{}"); - Assert.assertNotNull(blacklist); - Assert.assertTrue(blacklist.mEntries.isEmpty()); + KeyRevocationList blocklist; + blocklist = KeyRevocationList.fromJsonString(sBlocklistJsonString); + Assert.assertNotNull(blocklist); + Assert.assertFalse(blocklist.mEntries.isEmpty()); + blocklist = KeyRevocationList.fromJsonString("{}"); + Assert.assertNotNull(blocklist); + Assert.assertTrue(blocklist.mEntries.isEmpty()); } @Test @SmallTest public void testFromUrl() throws IOException, JSONException { URLConnection mockConnection = mock(URLConnection.class); - doReturn(new ByteArrayInputStream(sBlacklistJsonString.getBytes())) + doReturn(new ByteArrayInputStream(sBlocklistJsonString.getBytes())) .when(mockConnection).getInputStream(); URL mockUrl = new URL( "http", // protocol @@ -97,36 +97,36 @@ public class KeyRevocationListTest { } }); - KeyRevocationList blacklist = KeyRevocationList.fromUrl(mockUrl); - Assert.assertNotNull(blacklist); - Assert.assertFalse(blacklist.mEntries.isEmpty()); + KeyRevocationList blocklist = KeyRevocationList.fromUrl(mockUrl); + Assert.assertNotNull(blocklist); + Assert.assertFalse(blocklist.mEntries.isEmpty()); - blacklist = null; + blocklist = null; try { - blacklist = KeyRevocationList.fromUrl(mockBadUrl); + blocklist = KeyRevocationList.fromUrl(mockBadUrl); // Up should throw, down should be unreachable Assert.fail("Expected IOException not thrown"); } catch (IOException e) { // This is expected, do nothing } - Assert.assertNull(blacklist); + Assert.assertNull(blocklist); } @Test @SmallTest public void testIsRevoked() { - KeyRevocationList blacklist = new KeyRevocationList(); - blacklist.addEntry("key1", "REVOKED", "reason for key1"); + KeyRevocationList blocklist = new KeyRevocationList(); + blocklist.addEntry("key1", "REVOKED", "reason for key1"); KeyRevocationList.RevocationStatus revocationStatus = - blacklist.getRevocationStatusForKey("key1"); + blocklist.getRevocationStatusForKey("key1"); Assert.assertNotNull(revocationStatus); Assert.assertEquals(revocationStatus.mReason, "reason for key1"); - revocationStatus = blacklist.getRevocationStatusForKey("key2"); + revocationStatus = blocklist.getRevocationStatusForKey("key2"); Assert.assertNull(revocationStatus); - Assert.assertTrue(blacklist.isRevoked("key1")); - Assert.assertFalse(blacklist.isRevoked("key2")); + Assert.assertTrue(blocklist.isRevoked("key1")); + Assert.assertFalse(blocklist.isRevoked("key2")); } } diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeView.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeView.java index 276d55ee9a5e..9fe7ab655e46 100644 --- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeView.java +++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeView.java @@ -26,7 +26,7 @@ import android.os.Message; import android.view.View; /** - * Dummy view to emulate stuff an OEM may want to do. + * Fake view to emulate stuff an OEM may want to do. */ public class FakeView extends View { static final long TICK_DELAY = 30*1000; // 30 seconds diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java index 0b6996365372..121f5492a5ab 100644 --- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java +++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java @@ -38,7 +38,10 @@ public class LicenseHtmlLoaderCompat extends AsyncLoaderCompat<File> { "/odm/etc/NOTICE.xml.gz", "/oem/etc/NOTICE.xml.gz", "/product/etc/NOTICE.xml.gz", - "/product_services/etc/NOTICE.xml.gz"}; + "/system_ext/etc/NOTICE.xml.gz", + "/vendor_dlkm/etc/NOTICE.xml.gz", + "/odm_dlkm/etc/NOTICE.xml.gz", + }; static final String NOTICE_HTML_FILE_NAME = "NOTICE.html"; private final Context mContext; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java index 246f2ceac87c..e1174fa05ea5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java @@ -17,7 +17,8 @@ package com.android.settingslib.net; import android.content.Context; -import android.telephony.SubscriptionManager; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; /** * Utilities for dealing with signal strength. @@ -28,7 +29,13 @@ public class SignalStrengthUtil { * bar for the subscription with the given id */ public static boolean shouldInflateSignalStrength(Context context, int subscriptionId) { - return SubscriptionManager.getResourcesForSubId(context, subscriptionId) - .getBoolean(com.android.internal.R.bool.config_inflateSignalStrength); + final CarrierConfigManager carrierConfigMgr = + context.getSystemService(CarrierConfigManager.class); + PersistableBundle bundle = null; + if (carrierConfigMgr != null) { + bundle = carrierConfigMgr.getConfigForSubId(subscriptionId); + } + return (bundle != null && bundle.getBoolean( + CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index d338bc090757..d107bc33aa86 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -247,7 +247,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro } /** - * Sanity warning: this wipes out mScoreCache, so use with extreme caution + * Validity warning: this wipes out mScoreCache, so use with extreme caution * @param workThread substitute Handler thread, for testing purposes only */ @VisibleForTesting diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 3b48c1d12f40..cf4f75cc45f7 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -190,6 +190,9 @@ <uses-permission android:name="android.permission.MANAGE_APPOPS" /> + <!-- Permission required for IncrementalLogCollectionTest --> + <uses-permission android:name="android.permission.LOADER_USAGE_STATS" /> + <!-- Permission required for storage tests - FuseDaemonHostTest --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> @@ -198,6 +201,9 @@ <!-- Permission needed to test tcp keepalive offload. --> <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" /> + <!-- Permission needed for CTS test - UnsupportedErrorDialogTests --> + <uses-permission android:name="android.permission.RESET_APP_ERRORS" /> + <!-- Permission needed to run keyguard manager tests in CTS --> <uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" /> diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index dbfaca0b6b80..a645dfc7c5ad 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -62,7 +62,7 @@ android_library { "iconloader_base", "SystemUI-tags", "SystemUI-proto", - "dagger2-2.19", + "dagger2", "jsr330" ], manifest: "AndroidManifest.xml", @@ -73,7 +73,7 @@ android_library { kotlincflags: ["-Xjvm-default=enable"], - plugins: ["dagger2-compiler-2.19"], + plugins: ["dagger2-compiler"], } android_library { @@ -118,7 +118,7 @@ android_library { "mockito-target-inline-minus-junit4", "testables", "truth-prebuilt", - "dagger2-2.19", + "dagger2", "jsr330" ], libs: [ @@ -131,7 +131,7 @@ android_library { "--extra-packages", "com.android.systemui", ], - plugins: ["dagger2-compiler-2.19"], + plugins: ["dagger2-compiler"], } android_app { diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md index c440fba10135..bb68647ceb00 100644 --- a/packages/SystemUI/docs/dagger.md +++ b/packages/SystemUI/docs/dagger.md @@ -206,11 +206,31 @@ public CustomView(@Named(VIEW_CONTEXT) Context themedViewContext, AttributeSet a ## Updating Dagger2 +We depend on the Dagger source found in external/dagger2. We should automatically pick up on updates +when that repository is updated. + +*Deprecated:* + Binaries can be downloaded from https://repo1.maven.org/maven2/com/google/dagger/ and then loaded into [/prebuilts/tools/common/m2/repository/com/google/dagger/](http://cs/android/prebuilts/tools/common/m2/repository/com/google/dagger/) +The following commands should work, substituting in the version that you are looking for: + +```` +cd prebuilts/tools/common/m2/repository/com/google/dagger/ + +wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger/2.28.1/ + +wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.28.1/ + +wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-spi/2.28.1/ + +wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.28.1/ +```` +Then update `prebuilts/tools/common/m2/Android.bp` to point at your new jars. + ## TODO List - Eliminate usages of Dependency#get diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index 8bfd5f327729..d12ba291a43d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -137,7 +137,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { // Sending empty PIN here to query the number of remaining PIN attempts new CheckSimPin("", mSubId) { void onSimCheckResponse(final PinResult result) { - Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result " + Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result " + result.toString()); if (result.getAttemptsRemaining() >= 0) { mRemainingAttempts = result.getAttemptsRemaining(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java index 75cf691819c9..10460da92137 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -191,7 +191,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { void onSimLockChangedResponse(final PinResult result) { if (result == null) Log.e(LOG_TAG, "onSimCheckResponse, pin result is NULL"); else { - Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result " + Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result " + result.toString()); if (result.getAttemptsRemaining() >= 0) { mRemainingAttempts = result.getAttemptsRemaining(); diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java index 626d0cfed997..c1de21bed05e 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java @@ -167,7 +167,7 @@ class ImageGLWallpaper { private void setupTexture(Bitmap bitmap) { final int[] tids = new int[1]; - if (bitmap == null) { + if (bitmap == null || bitmap.isRecycled()) { Log.w(TAG, "setupTexture: invalid bitmap"); return; } @@ -179,16 +179,20 @@ class ImageGLWallpaper { return; } - // Bind a named texture to a target. - glBindTexture(GL_TEXTURE_2D, tids[0]); - // Load the bitmap data and copy it over into the texture object that is currently bound. - GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); - // Use bilinear texture filtering when minification. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // Use bilinear texture filtering when magnification. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - mTextureId = tids[0]; + try { + // Bind a named texture to a target. + glBindTexture(GL_TEXTURE_2D, tids[0]); + // Load the bitmap data and copy it over into the texture object + // that is currently bound. + GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); + // Use bilinear texture filtering when minification. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // Use bilinear texture filtering when magnification. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + mTextureId = tids[0]; + } catch (IllegalArgumentException e) { + Log.w(TAG, "Failed uploading texture: " + e.getLocalizedMessage()); + } } void useTexture() { diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java index 24a4b9e3052b..231779df6f52 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java @@ -86,7 +86,13 @@ class ImageProcessHelper { protected Float doInBackground(Bitmap... bitmaps) { Bitmap bitmap = bitmaps[0]; if (bitmap != null) { - return new Threshold().compute(bitmap); + try { + return new Threshold().compute(bitmap); + } catch (RuntimeException e) { + Log.e(TAG, "Failed at computing threshold, color space=" + + bitmap.getColorSpace(), e); + return DEFAULT_THRESHOLD; + } } Log.e(TAG, "ThresholdComputeTask: Can't get bitmap"); return DEFAULT_THRESHOLD; @@ -116,7 +122,8 @@ class ImageProcessHelper { int width = bitmap.getWidth(); int height = bitmap.getHeight(); - Bitmap grayscale = Bitmap.createBitmap(width, height, bitmap.getConfig()); + Bitmap grayscale = Bitmap.createBitmap(width, height, + bitmap.getConfig(), false, bitmap.getColorSpace()); Canvas canvas = new Canvas(grayscale); ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX); Paint paint = new Paint(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index c67512c11922..ffe51ca44c4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -269,7 +269,7 @@ public class InstantAppNotifier extends SystemUI 0, new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", pkg, null)), - 0, + PendingIntent.FLAG_IMMUTABLE, null, user); Notification.Action action = @@ -282,7 +282,7 @@ public class InstantAppNotifier extends SystemUI mContext, 0, new Intent(Intent.ACTION_VIEW).setData(Uri.parse(helpUrl)), - 0, + PendingIntent.FLAG_IMMUTABLE, null, user) : null; @@ -303,7 +303,7 @@ public class InstantAppNotifier extends SystemUI mContext, 0 /* requestCode */, browserIntent, - 0 /* flags */, + PendingIntent.FLAG_IMMUTABLE /* flags */, null, user); ComponentName aiaComponent = null; @@ -325,8 +325,8 @@ public class InstantAppNotifier extends SystemUI .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.longVersionCode) .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent); - PendingIntent webPendingIntent = - PendingIntent.getActivityAsUser(mContext, 0, goToWebIntent, 0, null, user); + PendingIntent webPendingIntent = PendingIntent.getActivityAsUser(mContext, 0, + goToWebIntent, PendingIntent.FLAG_IMMUTABLE, null, user); Notification.Action webAction = new Notification.Action.Builder( null, mContext.getString(R.string.go_to_web), webPendingIntent) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index a7e7f085ffd7..1a5f9b75cd13 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -265,7 +265,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, /** * Set that we are exiting the headsUp pinned mode, but some notifications might still be - * animating out. This is used to keep the touchable regions in a sane state. + * animating out. This is used to keep the touchable regions in a reasonable state. */ public void setHeadsUpGoingAway(boolean headsUpGoingAway) { if (headsUpGoingAway != mHeadsUpGoingAway) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt index f7b8a2e29129..a791e7307ba8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt @@ -73,7 +73,9 @@ class KeyguardLiftController constructor( val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible && !statusBarStateController.isDozing - val shouldListen = onKeyguard || bouncerVisible + val userId = KeyguardUpdateMonitor.getCurrentUser() + val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId) + val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled if (shouldListen != isListening) { isListening = shouldListen @@ -84,4 +86,4 @@ class KeyguardLiftController constructor( } } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index 371de7439f8f..173cddcfe471 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.TypedArray; import android.graphics.Rect; +import android.icu.text.DateTimePatternGenerator; import android.os.Bundle; import android.os.Handler; import android.os.Parcelable; @@ -54,8 +55,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController.Configurati import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; -import libcore.icu.LocaleData; - import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; @@ -384,20 +383,21 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C private final CharSequence getSmallTime() { Context context = getContext(); boolean is24 = DateFormat.is24HourFormat(context, mCurrentUserId); - LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance( + context.getResources().getConfiguration().locale); final char MAGIC1 = '\uEF00'; final char MAGIC2 = '\uEF01'; SimpleDateFormat sdf; String format = mShowSeconds - ? is24 ? d.timeFormat_Hms : d.timeFormat_hms - : is24 ? d.timeFormat_Hm : d.timeFormat_hm; + ? is24 ? dtpg.getBestPattern("Hms") : dtpg.getBestPattern("hms") + : is24 ? dtpg.getBestPattern("Hm") : dtpg.getBestPattern("hm"); if (!format.equals(mClockFormatString)) { mContentDescriptionFormat = new SimpleDateFormat(format); /* * Search for an unquoted "a" in the format string, so we can - * add dummy characters around it to let us find it again after + * add marker characters around it to let us find it again after * formatting and change its size. */ if (mAmPmStyle != AM_PM_STYLE_NORMAL) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java index 54502e41ca64..12d0617d90ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java @@ -198,7 +198,7 @@ public class DeadZone { can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA); if (DEBUG && size > mSizeMin) - // crazy aggressive redrawing here, for debugging only + // Very aggressive redrawing here, for debugging only mNavigationBarView.postInvalidateDelayed(100); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 3b08ef5fc1e1..e4feaaef5c44 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -1157,7 +1157,6 @@ public class NetworkControllerImpl extends BroadcastReceiver boolean show4gForLte = false; boolean hideLtePlus = false; boolean hspaDataDistinguishable; - boolean inflateSignalStrengths = false; boolean alwaysShowDataRatIcon = false; static Config readConfig(Context context) { @@ -1169,8 +1168,6 @@ public class NetworkControllerImpl extends BroadcastReceiver res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); config.hspaDataDistinguishable = res.getBoolean(R.bool.config_hspa_data_distinguishable); - config.inflateSignalStrengths = res.getBoolean( - com.android.internal.R.bool.config_inflateSignalStrength); CarrierConfigManager configMgr = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java index b5f98ad47c09..89297fd83bb0 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java @@ -54,7 +54,7 @@ public class UsbAccessoryUriActivity extends AlertActivity String uriString = intent.getStringExtra("uri"); mUri = (uriString == null ? null : Uri.parse(uriString)); - // sanity check before displaying dialog + // Exception check before displaying dialog if (mUri == null) { Log.e(TAG, "could not parse Uri " + uriString); finish(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 9271caf0b721..4553e9e0dfe6 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -478,7 +478,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) { int subscription = simInited - ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE; + ? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE; if (data != null) intent.putExtras(data); intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subscription); diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 4d95f3f474b5..2adfce2c42ae 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -363,7 +363,7 @@ public class PowerUITest extends SysuiTestCase { mPowerUI.mSevereWarningShownThisChargeCycle = false; BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper(); - // sanity check to make sure we can show for a valid config + // readiness check to make sure we can show for a valid config state.mBatteryLevel = 10; state.mTimeRemainingMillis = Duration.ofHours(2).toMillis(); boolean shouldShow = mPowerUI.shouldShowHybridWarning(state.get()); @@ -428,7 +428,7 @@ public class PowerUITest extends SysuiTestCase { mPowerUI.mSevereWarningShownThisChargeCycle = false; BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper(); - // sanity check to make sure we can show for a valid config + // readiness check to make sure we can show for a valid config state.mBatteryLevel = 1; state.mTimeRemainingMillis = Duration.ofMinutes(1).toMillis(); boolean shouldShow = mPowerUI.shouldShowHybridWarning(state.get()); @@ -551,7 +551,7 @@ public class PowerUITest extends SysuiTestCase { state.mIsHybrid = false; BatteryStateSnapshot lastState = state.get(); - // sanity check to make sure we can show for a valid config + // readiness check to make sure we can show for a valid config state.mBatteryLevel = 10; state.mBucket = -1; boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState); diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index f89ee24f9594..bc2be14551a3 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -32,6 +32,7 @@ java_defaults { "android.hardware.tetheroffload.config-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", "net-utils-framework-common", + "net-utils-device-common", ], libs: [ "framework-tethering.impl", diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml index 2b2fe4534c3e..e6444f3ead5c 100644 --- a/packages/Tethering/AndroidManifest.xml +++ b/packages/Tethering/AndroidManifest.xml @@ -24,7 +24,7 @@ <!-- Permissions must be defined here, and not in the base manifest, as the tethering running in the system server process does not need any permission, and having privileged permissions added would cause crashes on startup unless they are also - added to the privileged permissions whitelist for that package. --> + added to the privileged permissions allowlist for that package. --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt index 2c4059dda9b5..591861f5b837 100644 --- a/packages/Tethering/jarjar-rules.txt +++ b/packages/Tethering/jarjar-rules.txt @@ -1,17 +1,8 @@ # These must be kept in sync with the framework-tethering-shared-srcs filegroup. -# If there are files in that filegroup that do not appear here, the classes in the +# Classes from the framework-tethering-shared-srcs filegroup. +# If there are files in that filegroup that are not covered below, the classes in the # module will be overwritten by the ones in the framework. -# Don't jar-jar the entire package because tethering still use some internal classes -# (like TrafficStatsConstants in com.android.internal.util) -# TODO: simply these when tethering is built as system_current. -rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1 -rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1 -rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1 -rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1 -rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1 -rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1 -rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1 - +rule com.android.internal.util.** com.android.networkstack.tethering.util.@1 rule android.util.LocalLog* com.android.networkstack.tethering.util.LocalLog@1 rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1 diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags index 051fbd19fc6c..86b903353cf5 100644 --- a/packages/Tethering/proguard.flags +++ b/packages/Tethering/proguard.flags @@ -1,5 +1,5 @@ # Keep class's integer static field for MessageUtils to parsing their name. --keep class com.android.networkstack.tethering.Tethering$TetherMasterSM { +-keep class com.android.networkstack.tethering.Tethering$TetherMainSM { static final int CMD_*; static final int EVENT_*; } diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml index 4807e52804a1..89a9046a1b88 100644 --- a/packages/Tethering/res/values/config.xml +++ b/packages/Tethering/res/values/config.xml @@ -71,6 +71,9 @@ <!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. --> <bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool> + <!-- Use legacy wifi p2p dedicated address instead of randomize address. --> + <bool translatable="false" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip">false</bool> + <!-- Dhcp range (min, max) to use for tethering purposes --> <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml index 6a33d55cb0de..0ee7a992ee20 100644 --- a/packages/Tethering/res/values/overlayable.xml +++ b/packages/Tethering/res/values/overlayable.xml @@ -30,6 +30,7 @@ --> <item type="bool" name="config_tether_enable_bpf_offload"/> <item type="bool" name="config_tether_enable_legacy_dhcp_server"/> + <item type="bool" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip"/> <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"/> diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index 4710a30b2998..aaaec17bf922 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -16,7 +16,7 @@ package android.net.dhcp; -import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; +import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; import android.net.LinkAddress; import android.util.ArraySet; diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index a61fcfb81950..673cbf09d259 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -19,13 +19,14 @@ package android.net.ip; import static android.net.RouteInfo.RTN_UNICAST; import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; import static android.net.util.NetworkConstants.asByte; import static android.net.util.PrefixUtils.asIpPrefix; import static android.net.util.TetheringMessageBase.BASE_IPSERVER; import static android.system.OsConstants.RT_SCOPE_UNIVERSE; +import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; + import android.net.INetd; import android.net.INetworkStackStatusCallback; import android.net.IpPrefix; @@ -196,15 +197,19 @@ public class IpServer extends StateMachine { public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2; // notification that this interface is down public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3; - // notification from the master SM that it had trouble enabling IP Forwarding + // notification from the {@link Tethering.TetherMainSM} that it had trouble enabling IP + // Forwarding public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4; - // notification from the master SM that it had trouble disabling IP Forwarding + // notification from the {@link Tethering.TetherMainSM} SM that it had trouble disabling IP + // Forwarding public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5; - // notification from the master SM that it had trouble starting tethering + // notification from the {@link Tethering.TetherMainSM} SM that it had trouble starting + // tethering public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6; - // notification from the master SM that it had trouble stopping tethering + // notification from the {@link Tethering.TetherMainSM} that it had trouble stopping tethering public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7; - // notification from the master SM that it had trouble setting the DNS forwarders + // notification from the {@link Tethering.TetherMainSM} that it had trouble setting the DNS + // forwarders public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8; // the upstream connection has changed public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9; @@ -422,9 +427,13 @@ public class IpServer extends StateMachine { getHandler().post(() -> { // We are on the handler thread: mDhcpServerStartIndex can be read safely. if (mStartIndex != mDhcpServerStartIndex) { - // This start request is obsolete. When the |server| binder token goes out of - // scope, the garbage collector will finalize it, which causes the network stack - // process garbage collector to collect the server itself. + // This start request is obsolete. Explicitly stop the DHCP server to shut + // down its thread. When the |server| binder token goes out of scope, the + // garbage collector will finalize it, which causes the network stack process + // garbage collector to collect the server itself. + try { + server.stop(null); + } catch (RemoteException e) { } return; } @@ -1315,7 +1324,7 @@ public class IpServer extends StateMachine { /** * This state is terminal for the per interface state machine. At this - * point, the master state machine should have removed this interface + * point, the tethering main state machine should have removed this interface * specific state machine from its list of possible recipients of * tethering requests. The state machine itself will hang around until * the garbage collector finds it. diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java index 1b763ce920da..29c0a817b6f4 100644 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java @@ -19,7 +19,7 @@ package android.net.util; * This class defines Message.what base addresses for various state machine. */ public class TetheringMessageBase { - public static final int BASE_MASTER = 0; + public static final int BASE_MAIN_SM = 0; public static final int BASE_IPSERVER = 100; } diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java index 9dace709d734..bb7322f2a0d2 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java @@ -296,16 +296,16 @@ public class EntitlementManager { * Reference TetheringManager.TETHERING_{@code *} for each tether type. * * @param config an object that encapsulates the various tethering configuration elements. - * Note: this method is only called from TetherMaster on the handler thread. + * Note: this method is only called from @{link Tethering.TetherMainSM} on the handler thread. * If there are new callers from different threads, the logic should move to - * masterHandler to avoid race conditions. + * @{link Tethering.TetherMainSM} handler to avoid race conditions. */ public void reevaluateSimCardProvisioning(final TetheringConfiguration config) { if (DBG) mLog.i("reevaluateSimCardProvisioning"); if (!mHandler.getLooper().isCurrentThread()) { // Except for test, this log should not appear in normal flow. - mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread"); + mLog.log("reevaluateSimCardProvisioning() don't run in TetherMainSM thread"); } mEntitlementCacheValue.clear(); mCurrentEntitlementResults.clear(); diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java index aa58a4b6a320..fd9e36080c80 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java @@ -15,6 +15,8 @@ */ package com.android.networkstack.tethering; +import static android.net.TetheringManager.TETHERING_WIFI_P2P; + import static java.util.Arrays.asList; import android.content.Context; @@ -58,6 +60,7 @@ public class PrivateAddressCoordinator { private static final int BYTE_MASK = 0xff; // reserved for bluetooth tethering. private static final int BLUETOOTH_RESERVED = 44; + private static final int WIFI_P2P_RESERVED = 49; private static final byte DEFAULT_ID = (byte) 42; // Upstream monitor would be stopped when tethering is down. When tethering restart, downstream @@ -71,15 +74,18 @@ public class PrivateAddressCoordinator { // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 // Tethering use 192.168.0.0/16 that has 256 contiguous class C network numbers. private static final String DEFAULT_TETHERING_PREFIX = "192.168.0.0/16"; + private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24"; private final IpPrefix mTetheringPrefix; private final ConnectivityManager mConnectivityMgr; + private final TetheringConfiguration mConfig; - public PrivateAddressCoordinator(Context context) { + public PrivateAddressCoordinator(Context context, TetheringConfiguration config) { mDownstreams = new ArraySet<>(); mUpstreamPrefixMap = new ArrayMap<>(); mTetheringPrefix = new IpPrefix(DEFAULT_TETHERING_PREFIX); mConnectivityMgr = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE); + mConfig = config; } /** @@ -141,12 +147,21 @@ public class PrivateAddressCoordinator { mUpstreamPrefixMap.removeAll(toBeRemoved); } + private boolean isReservedSubnet(final int subnet) { + return subnet == BLUETOOTH_RESERVED || subnet == WIFI_P2P_RESERVED; + } + /** * Pick a random available address and mark its prefix as in use for the provided IpServer, * returns null if there is no available address. */ @Nullable public LinkAddress requestDownstreamAddress(final IpServer ipServer) { + if (mConfig.shouldEnableWifiP2pDedicatedIp() + && ipServer.interfaceType() == TETHERING_WIFI_P2P) { + return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS); + } + // Address would be 192.168.[subAddress]/24. final byte[] bytes = mTetheringPrefix.getRawAddress(); final int subAddress = getRandomSubAddr(); @@ -154,7 +169,7 @@ public class PrivateAddressCoordinator { bytes[3] = getSanitizedAddressSuffix(subAddress, (byte) 0, (byte) 1, (byte) 0xff); for (int i = 0; i < MAX_UBYTE; i++) { final int newSubNet = (subNet + i) & BYTE_MASK; - if (newSubNet == BLUETOOTH_RESERVED) continue; + if (isReservedSubnet(newSubNet)) continue; bytes[2] = (byte) newSubNet; final InetAddress addr; diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java index 3627085cb6aa..255cf750c083 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -50,7 +50,7 @@ import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; -import static android.net.util.TetheringMessageBase.BASE_MASTER; +import static android.net.util.TetheringMessageBase.BASE_MAIN_SM; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; @@ -159,7 +159,7 @@ public class Tethering { private static final boolean VDBG = false; private static final Class[] sMessageClasses = { - Tethering.class, TetherMasterSM.class, IpServer.class + Tethering.class, TetherMainSM.class, IpServer.class }; private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(sMessageClasses); @@ -216,7 +216,7 @@ public class Tethering { private final ArrayMap<String, TetherState> mTetherStates; private final BroadcastReceiver mStateReceiver; private final Looper mLooper; - private final StateMachine mTetherMasterSM; + private final StateMachine mTetherMainSM; private final OffloadController mOffloadController; private final UpstreamNetworkMonitor mUpstreamNetworkMonitor; // TODO: Figure out how to merge this and other downstream-tracking objects @@ -273,10 +273,10 @@ public class Tethering { mTetherStates = new ArrayMap<>(); mConnectedClientsTracker = new ConnectedClientsTracker(); - mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps); - mTetherMasterSM.start(); + mTetherMainSM = new TetherMainSM("TetherMain", mLooper, deps); + mTetherMainSM.start(); - mHandler = mTetherMasterSM.getHandler(); + mHandler = mTetherMainSM.getHandler(); mOffloadController = mDeps.getOffloadController(mHandler, mLog, new OffloadController.Dependencies() { @@ -285,8 +285,8 @@ public class Tethering { return mConfig; } }); - mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog, - TetherMasterSM.EVENT_UPSTREAM_CALLBACK); + mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog, + TetherMainSM.EVENT_UPSTREAM_CALLBACK); mForwardedDownstreams = new LinkedHashSet<>(); IntentFilter filter = new IntentFilter(); @@ -294,8 +294,8 @@ public class Tethering { // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream // permission is changed according to entitlement check result. mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog, - () -> mTetherMasterSM.sendMessage( - TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); + () -> mTetherMainSM.sendMessage( + TetherMainSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { mLog.log("OBSERVED UiEnitlementFailed"); stopTethering(downstream); @@ -320,10 +320,13 @@ public class Tethering { mExecutor = new TetheringThreadExecutor(mHandler); mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); mNetdCallback = new NetdCallback(); - mPrivateAddressCoordinator = new PrivateAddressCoordinator(mContext); // Load tethering configuration. updateConfiguration(); + // It is OK for the configuration to be passed to the PrivateAddressCoordinator at + // construction time because the only part of the configuration it uses is + // shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that. + mPrivateAddressCoordinator = new PrivateAddressCoordinator(mContext, mConfig); // Must be initialized after tethering configuration is loaded because BpfCoordinator // constructor needs to use the configuration. @@ -945,7 +948,7 @@ public class Tethering { } if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString()); - mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); + mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED); } private void handleUsbAction(Intent intent) { @@ -1170,7 +1173,7 @@ public class Tethering { private void disableWifiP2pIpServingLockedIfNeeded(String ifname) { if (TextUtils.isEmpty(ifname)) return; - disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0); + disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0); } private void enableWifiIpServingLocked(String ifname, int wifiIpMode) { @@ -1381,23 +1384,23 @@ public class Tethering { return false; } - class TetherMasterSM extends StateMachine { + class TetherMainSM extends StateMachine { // an interface SM has requested Tethering/Local Hotspot - static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1; + static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MAIN_SM + 1; // an interface SM has unrequested Tethering/Local Hotspot - static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2; + static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MAIN_SM + 2; // upstream connection change - do the right thing - static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3; + static final int CMD_UPSTREAM_CHANGED = BASE_MAIN_SM + 3; // we don't have a valid upstream conn, check again after a delay - static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4; - // Events from NetworkCallbacks that we process on the master state + static final int CMD_RETRY_UPSTREAM = BASE_MAIN_SM + 4; + // Events from NetworkCallbacks that we process on the main state // machine thread on behalf of the UpstreamNetworkMonitor. - static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5; + static final int EVENT_UPSTREAM_CALLBACK = BASE_MAIN_SM + 5; // we treated the error and want now to clear it - static final int CMD_CLEAR_ERROR = BASE_MASTER + 6; - static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7; + static final int CMD_CLEAR_ERROR = BASE_MAIN_SM + 6; + static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MAIN_SM + 7; // Events from EntitlementManager to choose upstream again. - static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8; + static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MAIN_SM + 8; private final State mInitialState; private final State mTetherModeAliveState; @@ -1425,7 +1428,7 @@ public class Tethering { private static final int UPSTREAM_SETTLE_TIME_MS = 10000; - TetherMasterSM(String name, Looper looper, TetheringDependencies deps) { + TetherMainSM(String name, Looper looper, TetheringDependencies deps) { super(name, looper); mInitialState = new InitialState(); @@ -1479,7 +1482,7 @@ public class Tethering { } } - protected boolean turnOnMasterTetherSettings() { + protected boolean turnOnMainTetherSettings() { final TetheringConfiguration cfg = mConfig; try { mNetd.ipfwdEnableForwarding(TAG); @@ -1506,11 +1509,11 @@ public class Tethering { return false; } } - mLog.log("SET master tether settings: ON"); + mLog.log("SET main tether settings: ON"); return true; } - protected boolean turnOffMasterTetherSettings() { + protected boolean turnOffMainTetherSettings() { try { mNetd.tetherStop(); } catch (RemoteException | ServiceSpecificException e) { @@ -1526,7 +1529,7 @@ public class Tethering { return false; } transitionTo(mInitialState); - mLog.log("SET master tether settings: OFF"); + mLog.log("SET main tether settings: OFF"); return true; } @@ -1730,7 +1733,7 @@ public class Tethering { // TODO: Re-evaluate possible upstreams. Currently upstream // reevaluation is triggered via received CONNECTIVITY_ACTION // broadcasts that result in being passed a - // TetherMasterSM.CMD_UPSTREAM_CHANGED. + // TetherMainSM.CMD_UPSTREAM_CHANGED. handleNewUpstreamNetworkState(null); break; default: @@ -1745,9 +1748,9 @@ public class Tethering { @Override public void enter() { - // If turning on master tether settings fails, we have already + // If turning on main tether settings fails, we have already // transitioned to an error state; exit early. - if (!turnOnMasterTetherSettings()) { + if (!turnOnMainTetherSettings()) { return; } @@ -1819,7 +1822,7 @@ public class Tethering { if (mNotifyList.isEmpty()) { // This transitions us out of TetherModeAliveState, // either to InitialState or an error state. - turnOffMasterTetherSettings(); + turnOffMainTetherSettings(); break; } @@ -2329,7 +2332,7 @@ public class Tethering { }; } - // TODO: Move into TetherMasterSM. + // TODO: Move into TetherMainSM. private void notifyInterfaceStateChange(IpServer who, int state, int error) { final String iface = who.interfaceName(); synchronized (mPublicSync) { @@ -2344,27 +2347,27 @@ public class Tethering { mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error)); - // If TetherMasterSM is in ErrorState, TetherMasterSM stays there. - // Thus we give a chance for TetherMasterSM to recover to InitialState + // If TetherMainSM is in ErrorState, TetherMainSM stays there. + // Thus we give a chance for TetherMainSM to recover to InitialState // by sending CMD_CLEAR_ERROR if (error == TETHER_ERROR_INTERNAL_ERROR) { - mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who); + mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who); } int which; switch (state) { case IpServer.STATE_UNAVAILABLE: case IpServer.STATE_AVAILABLE: - which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE; + which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE; break; case IpServer.STATE_TETHERED: case IpServer.STATE_LOCAL_ONLY: - which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE; + which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE; break; default: Log.wtf(TAG, "Unknown interface state: " + state); return; } - mTetherMasterSM.sendMessage(which, state, 0, who); + mTetherMainSM.sendMessage(which, state, 0, who); sendTetherStateChangedBroadcast(); } @@ -2384,8 +2387,8 @@ public class Tethering { mLog.log(String.format( "OBSERVED LinkProperties update iface=%s state=%s lp=%s", iface, IpServer.getStateString(state), newLp)); - final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; - mTetherMasterSM.sendMessage(which, state, 0, newLp); + final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; + mTetherMainSM.sendMessage(which, state, 0, newLp); } private void maybeTrackNewInterfaceLocked(final String iface) { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index e1771a561370..5783805861a3 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -84,6 +84,9 @@ public class TetheringConfiguration { public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER = "tether_enable_legacy_dhcp_server"; + public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP = + "use_legacy_wifi_p2p_dedicated_ip"; + /** * Default value that used to periodic polls tether offload stats from tethering offload HAL * to make the data warnings work. @@ -113,6 +116,7 @@ public class TetheringConfiguration { private final int mOffloadPollInterval; // TODO: Add to TetheringConfigurationParcel if required. private final boolean mEnableBpfOffload; + private final boolean mEnableWifiP2pDedicatedIp; public TetheringConfiguration(Context ctx, SharedLog log, int id) { final SharedLog configLog = log.forSubComponent("config"); @@ -156,6 +160,10 @@ public class TetheringConfiguration { R.integer.config_tether_offload_poll_interval, DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); + mEnableWifiP2pDedicatedIp = getResourceBoolean(res, + R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip, + false /* defaultValue */); + configLog.log(toString()); } @@ -199,6 +207,11 @@ public class TetheringConfiguration { return !TextUtils.isEmpty(provisioningAppNoUi); } + /** Check whether dedicated wifi p2p address is enabled. */ + public boolean shouldEnableWifiP2pDedicatedIp() { + return mEnableWifiP2pDedicatedIp; + } + /** Does the dumping.*/ public void dump(PrintWriter pw) { pw.print("activeDataSubId: "); @@ -233,6 +246,9 @@ public class TetheringConfiguration { pw.print("enableLegacyDhcpServer: "); pw.println(enableLegacyDhcpServer); + + pw.print("enableWifiP2pDedicatedIp: "); + pw.println(mEnableWifiP2pDedicatedIp); } /** Returns the string representation of this object.*/ diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java index 320427c393ac..b17065cb7804 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java @@ -63,7 +63,7 @@ import java.util.Set; * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network. * * The methods and data members of this class are only to be accessed and - * modified from the tethering master state machine thread. Any other + * modified from the tethering main state machine thread. Any other * access semantics would necessitate the addition of locking. * * TODO: Move upstream selection logic here. diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index 05cf58ab84ff..3b72b5b47191 100644 --- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -36,7 +36,8 @@ import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH; import static android.net.netlink.StructNdMsg.NUD_FAILED; import static android.net.netlink.StructNdMsg.NUD_REACHABLE; import static android.net.netlink.StructNdMsg.NUD_STALE; -import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; + +import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -49,6 +50,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; @@ -72,6 +74,7 @@ import android.net.MacAddress; import android.net.RouteInfo; import android.net.TetherOffloadRuleParcel; import android.net.TetherStatsParcel; +import android.net.dhcp.DhcpServerCallbacks; import android.net.dhcp.DhcpServingParamsParcel; import android.net.dhcp.IDhcpEventCallbacks; import android.net.dhcp.IDhcpServer; @@ -162,17 +165,6 @@ public class IpServerTest { private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception { - doAnswer(inv -> { - final IDhcpServerCallbacks cb = inv.getArgument(2); - new Thread(() -> { - try { - cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); - } catch (RemoteException e) { - fail(e.getMessage()); - } - }).run(); - return null; - }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS); @@ -224,6 +216,20 @@ public class IpServerTest { when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress); } + private void setUpDhcpServer() throws Exception { + doAnswer(inv -> { + final IDhcpServerCallbacks cb = inv.getArgument(2); + new Thread(() -> { + try { + cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); + } catch (RemoteException e) { + fail(e.getMessage()); + } + }).run(); + return null; + }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog); @@ -257,6 +263,8 @@ public class IpServerTest { return mTetherConfig; } })); + + setUpDhcpServer(); } @Test @@ -964,6 +972,31 @@ public class IpServerTest { reset(mRaDaemon); } + @Test + public void testStopObsoleteDhcpServer() throws Exception { + final ArgumentCaptor<DhcpServerCallbacks> cbCaptor = + ArgumentCaptor.forClass(DhcpServerCallbacks.class); + doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), + cbCaptor.capture()); + initStateMachine(TETHERING_WIFI); + dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); + verify(mDhcpServer, never()).startWithCallbacks(any(), any()); + + // No stop dhcp server because dhcp server is not created yet. + dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); + verify(mDhcpServer, never()).stop(any()); + + // Stop obsolete dhcp server. + try { + final DhcpServerCallbacks cb = cbCaptor.getValue(); + cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); + mLooper.dispatchAll(); + } catch (RemoteException e) { + fail(e.getMessage()); + } + verify(mDhcpServer).stop(any()); + } + private void assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix) { // Last address byte is random diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java index 2c0df6fc6327..8e93c2e447b3 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java @@ -15,6 +15,11 @@ */ package com.android.networkstack.tethering; +import static android.net.TetheringManager.TETHERING_ETHERNET; +import static android.net.TetheringManager.TETHERING_USB; +import static android.net.TetheringManager.TETHERING_WIFI; +import static android.net.TetheringManager.TETHERING_WIFI_P2P; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.mockito.Mockito.never; @@ -54,22 +59,34 @@ public final class PrivateAddressCoordinatorTest { @Mock private IpServer mHotspotIpServer; @Mock private IpServer mUsbIpServer; @Mock private IpServer mEthernetIpServer; + @Mock private IpServer mWifiP2pIpServer; @Mock private Context mContext; @Mock private ConnectivityManager mConnectivityMgr; + @Mock private TetheringConfiguration mConfig; private PrivateAddressCoordinator mPrivateAddressCoordinator; private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24"); + private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24"); private final Network mWifiNetwork = new Network(1); private final Network mMobileNetwork = new Network(2); private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork}; + private void setUpIpServers() throws Exception { + when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB); + when(mEthernetIpServer.interfaceType()).thenReturn(TETHERING_ETHERNET); + when(mHotspotIpServer.interfaceType()).thenReturn(TETHERING_WIFI); + when(mWifiP2pIpServer.interfaceType()).thenReturn(TETHERING_WIFI_P2P); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr); when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks); - mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext)); + when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false); + setUpIpServers(); + mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig)); } @Test @@ -256,4 +273,38 @@ public final class PrivateAddressCoordinatorTest { final IpPrefix ethPrefix = PrefixUtils.asIpPrefix(ethAddr); assertEquals(predefinedPrefix, ethPrefix); } + + private int getSubAddress(final byte... ipv4Address) { + assertEquals(4, ipv4Address.length); + + int subnet = Byte.toUnsignedInt(ipv4Address[2]); + return (subnet << 8) + ipv4Address[3]; + } + + private void assertReseveredWifiP2pPrefix() throws Exception { + LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( + mHotspotIpServer); + final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address); + final IpPrefix legacyWifiP2pPrefix = PrefixUtils.asIpPrefix(mLegacyWifiP2pAddress); + assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix); + mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); + } + + @Test + public void testEnableLegacyWifiP2PAddress() throws Exception { + when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn( + getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress())); + // No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix + // is resevered. + assertReseveredWifiP2pPrefix(); + + when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(true); + assertReseveredWifiP2pPrefix(); + + // If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address. + LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( + mWifiP2pIpServer); + assertEquals(mLegacyWifiP2pAddress, address); + mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer); + } } 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 a9ac4e2851f3..dc0940cc0222 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 @@ -128,6 +128,8 @@ public class TetheringConfigurationTest { .thenReturn(new String[0]); when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); + when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip)) + .thenReturn(false); initializeBpfOffloadConfiguration(true, null /* unset */); mHasTelephonyManager = true; @@ -413,4 +415,17 @@ public class TetheringConfigurationTest { R.string.config_mobile_hotspot_provision_response)).thenReturn( PROVISIONING_APP_RESPONSE); } + + @Test + public void testEnableLegacyWifiP2PAddress() throws Exception { + final TetheringConfiguration defaultCfg = new TetheringConfiguration( + mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertFalse(defaultCfg.shouldEnableWifiP2pDedicatedIp()); + + when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip)) + .thenReturn(true); + final TetheringConfiguration testCfg = new TetheringConfiguration( + mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp()); + } } diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt index 4b6bbac051e0..75c819bb0ced 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt @@ -18,33 +18,40 @@ package com.android.networkstack.tethering import android.app.Notification import android.app.NotificationManager +import android.app.PendingIntent +import android.app.PendingIntent.FLAG_IMMUTABLE import android.content.Context +import android.content.Intent import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.content.res.Resources import android.net.ConnectivityManager.TETHERING_WIFI +import android.net.NetworkCapabilities +import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING import android.os.Handler import android.os.HandlerThread import android.os.Looper -import android.net.NetworkCapabilities -import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING import android.os.UserHandle +import android.provider.Settings import android.telephony.TelephonyManager import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import androidx.test.runner.AndroidJUnit4 import com.android.internal.util.test.BroadcastInterceptingContext +import com.android.networkstack.tethering.TetheringNotificationUpdater.ACTION_DISABLE_TETHERING import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID import com.android.networkstack.tethering.TetheringNotificationUpdater.ROAMING_NOTIFICATION_ID import com.android.networkstack.tethering.TetheringNotificationUpdater.VERIZON_CARRIER_ID +import com.android.networkstack.tethering.TetheringNotificationUpdater.getSettingsPackageName import com.android.testutils.waitForIdle import org.junit.After import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull import org.junit.Assert.fail import org.junit.Before import org.junit.Test @@ -87,12 +94,17 @@ class TetheringNotificationUpdaterTest { // every test but should always be initialized before use (or the test should crash). private lateinit var context: TestContext private lateinit var notificationUpdater: TetheringNotificationUpdater + + // Initializing the following members depends on initializing some of the mocks and + // is more logically done in setup(). private lateinit var fakeTetheringThread: HandlerThread private val ROAMING_CAPABILITIES = NetworkCapabilities() private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING) private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general private val TIMEOUT_MS = 500L + private val ACTIVITY_PENDING_INTENT = 0 + private val BROADCAST_PENDING_INTENT = 1 private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) { override fun createContextAsUser(user: UserHandle, flags: Int) = @@ -146,10 +158,43 @@ class TetheringNotificationUpdaterTest { fakeTetheringThread.quitSafely() } + private fun verifyActivityPendingIntent(intent: Intent, flags: Int) { + // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add + // the flag in creating arguments). If the described PendingIntent does not already exist, + // getActivity() will return null instead of PendingIntent object. + val pi = PendingIntent.getActivity( + context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), + 0 /* requestCode */, + intent, + flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE, + null /* options */) + assertNotNull("Activity PendingIntent with FLAG_IMMUTABLE does not exist.", pi) + } + + private fun verifyBroadcastPendingIntent(intent: Intent, flags: Int) { + // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add + // the flag in creating arguments). If the described PendingIntent does not already exist, + // getBroadcast() will return null instead of PendingIntent object. + val pi = PendingIntent.getBroadcast( + context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), + 0 /* requestCode */, + intent, + flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE) + assertNotNull("Broadcast PendingIntent with FLAG_IMMUTABLE does not exist.", pi) + } + private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE) private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT) - private fun verifyNotification(iconId: Int, title: String, text: String, id: Int) { + private fun verifyNotification( + iconId: Int, + title: String, + text: String, + id: Int, + intentSenderType: Int, + intent: Intent, + flags: Int + ) { verify(notificationManager, never()).cancel(any(), eq(id)) val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java) @@ -161,6 +206,11 @@ class TetheringNotificationUpdaterTest { assertEquals(title, notification.title()) assertEquals(text, notification.text()) + when (intentSenderType) { + ACTIVITY_PENDING_INTENT -> verifyActivityPendingIntent(intent, flags) + BROADCAST_PENDING_INTENT -> verifyBroadcastPendingIntent(intent, flags) + } + reset(notificationManager) } @@ -176,6 +226,10 @@ class TetheringNotificationUpdaterTest { @Test fun testRestrictedNotification() { + val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS) + .setPackage(getSettingsPackageName(context.packageManager)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // Set test sub id. notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) @@ -183,7 +237,7 @@ class TetheringNotificationUpdaterTest { // User restrictions on. Show restricted notification. notificationUpdater.notifyTetheringDisabledByRestriction() verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE, - RESTRICTED_NOTIFICATION_ID) + RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) // User restrictions off. Clear notification. notificationUpdater.tetheringRestrictionLifted() @@ -196,7 +250,7 @@ class TetheringNotificationUpdaterTest { // User restrictions on again. Show restricted notification. notificationUpdater.notifyTetheringDisabledByRestriction() verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE, - RESTRICTED_NOTIFICATION_ID) + RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) } val MAX_BACKOFF_MS = 200L @@ -234,6 +288,8 @@ class TetheringNotificationUpdaterTest { @Test fun testNoUpstreamNotification() { + val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName) + // Set test sub id. notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) @@ -246,7 +302,8 @@ class TetheringNotificationUpdaterTest { notificationUpdater.onUpstreamCapabilitiesChanged(null) notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID) + NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, + FLAG_IMMUTABLE) // Same capabilities changed. Nothing happened. notificationUpdater.onUpstreamCapabilitiesChanged(null) @@ -260,7 +317,8 @@ class TetheringNotificationUpdaterTest { notificationUpdater.onUpstreamCapabilitiesChanged(null) notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID) + NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, + FLAG_IMMUTABLE) // No downstream. notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) @@ -305,6 +363,11 @@ class TetheringNotificationUpdaterTest { @Test fun testRoamingNotification() { + val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName) + val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS) + .setPackage(getSettingsPackageName(context.packageManager)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // Set test sub id. notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID)) @@ -316,7 +379,7 @@ class TetheringNotificationUpdaterTest { // Upstream capabilities changed to roaming state. Show roaming notification. notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE, - ROAMING_NOTIFICATION_ID) + ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) // Same capabilities change. Nothing happened. notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) @@ -329,14 +392,15 @@ class TetheringNotificationUpdaterTest { // Upstream capabilities changed to roaming state again. Show roaming notification. notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES) verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE, - ROAMING_NOTIFICATION_ID) + ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE) // No upstream. Clear roaming notification and show no upstream notification. notificationUpdater.onUpstreamCapabilitiesChanged(null) notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false) verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID) + NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, + FLAG_IMMUTABLE) // No downstream. notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) @@ -347,7 +411,8 @@ class TetheringNotificationUpdaterTest { notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS) verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false) verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE, - NO_UPSTREAM_NOTIFICATION_ID) + NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent, + FLAG_IMMUTABLE) // Set R.bool.config_upstream_roaming_notification to false and change upstream // network to roaming state again. No roaming notification. @@ -363,8 +428,7 @@ class TetheringNotificationUpdaterTest { val testSettingsPackageName = "com.android.test.settings" val pm = mock(PackageManager::class.java) doReturn(null).`when`(pm).resolveActivity(any(), anyInt()) - assertEquals(defaultSettingsPackageName, - TetheringNotificationUpdater.getSettingsPackageName(pm)) + assertEquals(defaultSettingsPackageName, getSettingsPackageName(pm)) val resolveInfo = ResolveInfo().apply { activityInfo = ActivityInfo().apply { @@ -375,7 +439,6 @@ class TetheringNotificationUpdaterTest { } } doReturn(resolveInfo).`when`(pm).resolveActivity(any(), anyInt()) - assertEquals(testSettingsPackageName, - TetheringNotificationUpdater.getSettingsPackageName(pm)) + assertEquals(testSettingsPackageName, getSettingsPackageName(pm)) } } 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 d37aad26d1fd..fb3940bfbad8 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 @@ -40,7 +40,6 @@ import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; @@ -49,6 +48,7 @@ import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; +import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES; @@ -337,11 +337,11 @@ public class TetheringTest { } public class MockTetheringDependencies extends TetheringDependencies { - StateMachine mUpstreamNetworkMonitorMasterSM; + StateMachine mUpstreamNetworkMonitorSM; ArrayList<IpServer> mIpv6CoordinatorNotifyList; public void reset() { - mUpstreamNetworkMonitorMasterSM = null; + mUpstreamNetworkMonitorSM = null; mIpv6CoordinatorNotifyList = null; } @@ -368,7 +368,7 @@ public class TetheringTest { @Override public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target, SharedLog log, int what) { - mUpstreamNetworkMonitorMasterSM = target; + mUpstreamNetworkMonitorSM = target; return mUpstreamNetworkMonitor; } @@ -911,8 +911,8 @@ public class TetheringTest { initTetheringUpstream(upstreamState); // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES. - mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage( - Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage( + Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK, UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0, upstreamState); @@ -1126,7 +1126,7 @@ public class TetheringTest { verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME); // This never gets called because of the exception thrown above. verify(mNetd, times(0)).tetherStartWithConfiguration(any()); - // When the master state machine transitions to an error state it tells + // When the main state machine transitions to an error state it tells // downstream interfaces, which causes us to tell Wi-Fi about the error // so it can take down AP mode. verify(mNetd, times(1)).tetherApplyDnsInterfaces(); @@ -1753,8 +1753,8 @@ public class TetheringTest { @Test public void testUpstreamNetworkChanged() { - final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM) - mTetheringDependencies.mUpstreamNetworkMonitorMasterSM; + final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM) + mTetheringDependencies.mUpstreamNetworkMonitorSM; final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); initTetheringUpstream(upstreamState); stateMachine.chooseUpstreamType(true); @@ -1765,8 +1765,8 @@ public class TetheringTest { @Test public void testUpstreamCapabilitiesChanged() { - final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM) - mTetheringDependencies.mUpstreamNetworkMonitorMasterSM; + final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM) + mTetheringDependencies.mUpstreamNetworkMonitorSM; final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); initTetheringUpstream(upstreamState); stateMachine.chooseUpstreamType(true); @@ -1891,8 +1891,8 @@ public class TetheringTest { any(), any()); reset(mNetd, mUsbManager); upstreamNetwork = buildV4WifiUpstreamState(ipv4Address, 30, wifiNetwork); - mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage( - Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage( + Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK, UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0, upstreamNetwork); @@ -1929,8 +1929,8 @@ public class TetheringTest { final UpstreamNetworkState upstreamNetwork = buildV4WifiUpstreamState( upstreamAddress, 16, wifiNetwork); - mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage( - Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage( + Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK, UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0, upstreamNetwork); diff --git a/packages/WAPPushManager/AndroidManifest.xml b/packages/WAPPushManager/AndroidManifest.xml index 14e6e91e3a25..a75fb2d47bbd 100644 --- a/packages/WAPPushManager/AndroidManifest.xml +++ b/packages/WAPPushManager/AndroidManifest.xml @@ -23,6 +23,8 @@ <permission android:name="com.android.smspush.WAPPUSH_MANAGER_BIND" android:protectionLevel="signatureOrSystem" /> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> + <original-package android:name="com.android.smspush" /> <application android:allowClearUserData="false"> diff --git a/services/Android.bp b/services/Android.bp index 581edceea1cb..a8c155c6fcbb 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -140,7 +140,14 @@ droidstubs { java_library { name: "android_system_server_stubs_current", + defaults: ["android_stubs_dists_default"], srcs: [":services-stubs.sources"], installable: false, static_libs: ["android_module_lib_stubs_current"], + sdk_version: "none", + system_modules: "none", + java_version: "1.8", + dist: { + dir: "apistubs/android/system-server", + }, } diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java index 4f49fb7578a1..f35d334b63a7 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java @@ -228,7 +228,7 @@ public class AppPredictionPerUserService extends if (connected) { synchronized (mLock) { if (mZombie) { - // Sanity check - shouldn't happen + // Validation check - shouldn't happen if (mRemoteService == null) { Slog.w(TAG, "Cannot resurrect sessions because remote service is null"); return; diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ce2bc82389ef..7d7c5703dd5d 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -1379,7 +1379,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if ((state & ViewState.STATE_AUTOFILLED_ONCE) != 0) { final String datasetId = viewState.getDatasetId(); if (datasetId == null) { - // Sanity check - should never happen. + // Validation check - should never happen. Slog.w(TAG, "logContextCommitted(): no dataset id on " + viewState); continue; } @@ -1513,7 +1513,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final ArrayMap<String, String> algorithms = userData.getFieldClassificationAlgorithms(); final ArrayMap<String, Bundle> args = userData.getFieldClassificationArgs(); - // Sanity check + // Validation check if (userValues == null || categoryIds == null || userValues.length != categoryIds.length) { final int valuesLength = userValues == null ? -1 : userValues.length; final int idsLength = categoryIds == null ? -1 : categoryIds.length; @@ -2312,12 +2312,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final String currentUrl = mUrlBar == null ? null : mUrlBar.getText().toString().trim(); if (currentUrl == null) { - // Sanity check - shouldn't happen. + // Validation check - shouldn't happen. wtf(null, "URL bar value changed, but current value is null"); return; } if (value == null || ! value.isText()) { - // Sanity check - shouldn't happen. + // Validation check - shouldn't happen. wtf(null, "URL bar value changed to null or non-text: %s", value); return; } diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 2554433fb659..c17aa4ecabbb 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -156,6 +156,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; @@ -1084,18 +1085,30 @@ public class UserBackupManagerService { private void parseLeftoverJournals() { ArrayList<DataChangedJournal> journals = DataChangedJournal.listJournals(mJournalDir); + // TODO(b/162022005): Fix DataChangedJournal implementing equals() but not hashCode(). + journals.removeAll(Collections.singletonList(mJournal)); + if (!journals.isEmpty()) { + Slog.i(TAG, "Found " + journals.size() + " stale backup journal(s), scheduling."); + } + Set<String> packageNames = new LinkedHashSet<>(); for (DataChangedJournal journal : journals) { - if (!journal.equals(mJournal)) { - try { - journal.forEach(packageName -> { - Slog.i(TAG, "Found stale backup journal, scheduling"); - if (MORE_DEBUG) Slog.i(TAG, " " + packageName); + try { + journal.forEach(packageName -> { + if (packageNames.add(packageName)) { dataChangedImpl(packageName); - }); - } catch (IOException e) { - Slog.e(TAG, "Can't read " + journal, e); - } + } + }); + } catch (IOException e) { + Slog.e(TAG, "Can't read " + journal, e); + } + } + if (!packageNames.isEmpty()) { + String msg = "Stale backup journals: Scheduled " + packageNames.size() + + " package(s) total"; + if (MORE_DEBUG) { + msg += ": " + packageNames; } + Slog.i(TAG, msg); } } diff --git a/services/core/Android.bp b/services/core/Android.bp index 2aa15d022468..e258735c17cd 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -54,6 +54,7 @@ java_library_static { "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-java", + "icu4j_calendar_astronomer", "netd_aidl_interfaces-platform-java", ], } diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index f2ce444a8b90..c771eb701b1d 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -58,16 +58,16 @@ public class BinderCallsStatsService extends Binder { /** Resolves the work source of an incoming binder transaction. */ static class AuthorizedWorkSourceProvider implements BinderInternal.WorkSourceProvider { - private ArraySet<Integer> mAppIdWhitelist; + private ArraySet<Integer> mAppIdTrustlist; AuthorizedWorkSourceProvider() { - mAppIdWhitelist = new ArraySet<>(); + mAppIdTrustlist = new ArraySet<>(); } public int resolveWorkSourceUid(int untrustedWorkSourceUid) { final int callingUid = getCallingUid(); final int appId = UserHandle.getAppId(callingUid); - if (mAppIdWhitelist.contains(appId)) { + if (mAppIdTrustlist.contains(appId)) { final int workSource = untrustedWorkSourceUid; final boolean isWorkSourceSet = workSource != Binder.UNSET_WORKSOURCE; return isWorkSourceSet ? workSource : callingUid; @@ -76,13 +76,13 @@ public class BinderCallsStatsService extends Binder { } public void systemReady(Context context) { - mAppIdWhitelist = createAppidWhitelist(context); + mAppIdTrustlist = createAppidTrustlist(context); } public void dump(PrintWriter pw, AppIdToPackageMap packageMap) { pw.println("AppIds of apps that can set the work source:"); - final ArraySet<Integer> whitelist = mAppIdWhitelist; - for (Integer appId : whitelist) { + final ArraySet<Integer> trustlist = mAppIdTrustlist; + for (Integer appId : trustlist) { pw.println("\t- " + packageMap.mapAppId(appId)); } } @@ -91,12 +91,12 @@ public class BinderCallsStatsService extends Binder { return Binder.getCallingUid(); } - private ArraySet<Integer> createAppidWhitelist(Context context) { - // Use a local copy instead of mAppIdWhitelist to prevent concurrent read access. - final ArraySet<Integer> whitelist = new ArraySet<>(); + private ArraySet<Integer> createAppidTrustlist(Context context) { + // Use a local copy instead of mAppIdTrustlist to prevent concurrent read access. + final ArraySet<Integer> trustlist = new ArraySet<>(); // We trust our own process. - whitelist.add(UserHandle.getAppId(Process.myUid())); + trustlist.add(UserHandle.getAppId(Process.myUid())); // We only need to initialize it once. UPDATE_DEVICE_STATS is a system permission. final PackageManager pm = context.getPackageManager(); final String[] permissions = { android.Manifest.permission.UPDATE_DEVICE_STATS }; @@ -109,12 +109,12 @@ public class BinderCallsStatsService extends Binder { try { final int uid = pm.getPackageUid(pkgInfo.packageName, queryFlags); final int appId = UserHandle.getAppId(uid); - whitelist.add(appId); + trustlist.add(appId); } catch (NameNotFoundException e) { Slog.e(TAG, "Cannot find uid for package name " + pkgInfo.packageName, e); } } - return whitelist; + return trustlist; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e1bcb0c21ce5..ecb935edde21 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -220,6 +220,8 @@ import com.android.server.utils.PriorityDump; import com.google.android.collect.Lists; +import libcore.io.IoUtils; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -4955,7 +4957,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.w(TAG, "User " + userId + " has no Vpn configuration"); return null; } - return vpn.getLockdownWhitelist(); + return vpn.getLockdownAllowlist(); } } @@ -7504,18 +7506,34 @@ public class ConnectivityService extends IConnectivityManager.Stub public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId, int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr, String dstAddr) { - mKeepaliveTracker.startNattKeepalive( - getNetworkAgentInfoForNetwork(network), fd, resourceId, - intervalSeconds, cb, - srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT); + try { + mKeepaliveTracker.startNattKeepalive( + getNetworkAgentInfoForNetwork(network), fd, resourceId, + intervalSeconds, cb, + srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT); + } finally { + // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks. + // startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately. + if (fd != null && Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(fd); + } + } } @Override public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds, ISocketKeepaliveCallback cb) { - enforceKeepalivePermission(); - mKeepaliveTracker.startTcpKeepalive( - getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb); + try { + enforceKeepalivePermission(); + mKeepaliveTracker.startTcpKeepalive( + getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb); + } finally { + // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks. + // startTcpKeepalive calls Os.dup(fd) before returning, so we can close immediately. + if (fd != null && Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(fd); + } + } } @Override diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 6402e07bddc3..b2f0c8376db1 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1477,7 +1477,7 @@ public class IpSecService extends IIpSecService.Stub { } /** - * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an + * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an * IllegalArgumentException if they are not. */ private void checkIpSecConfig(IpSecConfig config) { diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 82ce7b1002e3..276ce16f37f5 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -111,11 +111,11 @@ import java.util.NoSuchElementException; * Change-Id: I450c968bda93767554b5188ee63e10c9f43c5aa4 fixes bugs 16148026 * and 15973975 by saving the phoneId of the registrant and then using the * phoneId when deciding to to make a callback. This is necessary because - * a subId changes from to a dummy value when a SIM is removed and thus won't + * a subId changes from to a placeholder value when a SIM is removed and thus won't * compare properly. Because getPhoneIdFromSubId(int subId) handles - * the dummy value conversion we properly do the callbacks. + * the placeholder value conversion we properly do the callbacks. * - * Eventually we may want to remove the notion of dummy value but for now this + * Eventually we may want to remove the notion of placeholder value but for now this * looks like the best approach. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @@ -1457,7 +1457,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { public void notifyCarrierNetworkChange(boolean active) { // only CarrierService with carrier privilege rule should have the permission int[] subIds = Arrays.stream(SubscriptionManager.from(mContext) - .getActiveAndHiddenSubscriptionIdList()) + .getCompleteActiveSubscriptionIdList()) .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, i)).toArray(); if (ArrayUtils.isEmpty(subIds)) { diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 5f9d1d801441..25c8a3e6eafb 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.hidl.manager.V1_0.IServiceManager; import android.os.Binder; -import android.os.Build; import android.os.Debug; import android.os.Handler; import android.os.IPowerManager; @@ -32,10 +31,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; -import android.system.StructRlimit; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -48,13 +43,8 @@ import com.android.server.wm.SurfaceAnimationThread; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -132,7 +122,6 @@ public class Watchdog extends Thread { int mPhonePid; IActivityController mController; boolean mAllowRestart = true; - final OpenFdMonitor mOpenFdMonitor; /** * Used for checking status of handle threads and scheduling monitor callbacks. @@ -337,8 +326,6 @@ public class Watchdog extends Thread { // Initialize monitor for Binder threads. addMonitor(new BinderThreadMonitor()); - mOpenFdMonitor = OpenFdMonitor.create(); - // See the notes on DEFAULT_TIMEOUT. assert DB || DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS; @@ -560,41 +547,31 @@ public class Watchdog extends Thread { timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start); } - boolean fdLimitTriggered = false; - if (mOpenFdMonitor != null) { - fdLimitTriggered = mOpenFdMonitor.monitor(); - } - - if (!fdLimitTriggered) { - final int waitState = evaluateCheckerCompletionLocked(); - if (waitState == COMPLETED) { - // The monitors have returned; reset - waitedHalf = false; - continue; - } else if (waitState == WAITING) { - // still waiting but within their configured intervals; back off and recheck - continue; - } else if (waitState == WAITED_HALF) { - if (!waitedHalf) { - Slog.i(TAG, "WAITED_HALF"); - // We've waited half the deadlock-detection interval. Pull a stack - // trace and wait another half. - ArrayList<Integer> pids = new ArrayList<Integer>(); - pids.add(Process.myPid()); - ActivityManagerService.dumpStackTraces(pids, null, null, + final int waitState = evaluateCheckerCompletionLocked(); + if (waitState == COMPLETED) { + // The monitors have returned; reset + waitedHalf = false; + continue; + } else if (waitState == WAITING) { + // still waiting but within their configured intervals; back off and recheck + continue; + } else if (waitState == WAITED_HALF) { + if (!waitedHalf) { + Slog.i(TAG, "WAITED_HALF"); + // We've waited half the deadlock-detection interval. Pull a stack + // trace and wait another half. + ArrayList<Integer> pids = new ArrayList<Integer>(); + pids.add(Process.myPid()); + ActivityManagerService.dumpStackTraces(pids, null, null, getInterestingNativePids()); - waitedHalf = true; - } - continue; + waitedHalf = true; } - - // something is overdue! - blockedCheckers = getBlockedCheckersLocked(); - subject = describeCheckersLocked(blockedCheckers); - } else { - blockedCheckers = Collections.emptyList(); - subject = "Open FD high water mark reached"; + continue; } + + // something is overdue! + blockedCheckers = getBlockedCheckersLocked(); + subject = describeCheckersLocked(blockedCheckers); allowRestart = mAllowRestart; } @@ -688,94 +665,4 @@ public class Watchdog extends Thread { Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e); } } - - public static final class OpenFdMonitor { - /** - * Number of FDs below the soft limit that we trigger a runtime restart at. This was - * chosen arbitrarily, but will need to be at least 6 in order to have a sufficient number - * of FDs in reserve to complete a dump. - */ - private static final int FD_HIGH_WATER_MARK = 12; - - private final File mDumpDir; - private final File mFdHighWaterMark; - - public static OpenFdMonitor create() { - // Only run the FD monitor on debuggable builds (such as userdebug and eng builds). - if (!Build.IS_DEBUGGABLE) { - return null; - } - - final StructRlimit rlimit; - try { - rlimit = android.system.Os.getrlimit(OsConstants.RLIMIT_NOFILE); - } catch (ErrnoException errno) { - Slog.w(TAG, "Error thrown from getrlimit(RLIMIT_NOFILE)", errno); - return null; - } - - // The assumption we're making here is that FD numbers are allocated (more or less) - // sequentially, which is currently (and historically) true since open is currently - // specified to always return the lowest-numbered non-open file descriptor for the - // current process. - // - // We do this to avoid having to enumerate the contents of /proc/self/fd in order to - // count the number of descriptors open in the process. - final File fdThreshold = new File("/proc/self/fd/" + (rlimit.rlim_cur - FD_HIGH_WATER_MARK)); - return new OpenFdMonitor(new File("/data/anr"), fdThreshold); - } - - OpenFdMonitor(File dumpDir, File fdThreshold) { - mDumpDir = dumpDir; - mFdHighWaterMark = fdThreshold; - } - - /** - * Dumps open file descriptors and their full paths to a temporary file in {@code mDumpDir}. - */ - private void dumpOpenDescriptors() { - // We cannot exec lsof to get more info about open file descriptors because a newly - // forked process will not have the permissions to readlink. Instead list all open - // descriptors from /proc/pid/fd and resolve them. - List<String> dumpInfo = new ArrayList<>(); - String fdDirPath = String.format("/proc/%d/fd/", Process.myPid()); - File[] fds = new File(fdDirPath).listFiles(); - if (fds == null) { - dumpInfo.add("Unable to list " + fdDirPath); - } else { - for (File f : fds) { - String fdSymLink = f.getAbsolutePath(); - String resolvedPath = ""; - try { - resolvedPath = Os.readlink(fdSymLink); - } catch (ErrnoException ex) { - resolvedPath = ex.getMessage(); - } - dumpInfo.add(fdSymLink + "\t" + resolvedPath); - } - } - - // Dump the fds & paths to a temp file. - try { - File dumpFile = File.createTempFile("anr_fd_", "", mDumpDir); - Path out = Paths.get(dumpFile.getAbsolutePath()); - Files.write(out, dumpInfo, StandardCharsets.UTF_8); - } catch (IOException ex) { - Slog.w(TAG, "Unable to write open descriptors to file: " + ex); - } - } - - /** - * @return {@code true} if the high water mark was breached and a dump was written, - * {@code false} otherwise. - */ - public boolean monitor() { - if (mFdHighWaterMark.exists()) { - dumpOpenDescriptors(); - return true; - } - - return false; - } - } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 302d8e9f7335..e10c7118e3dd 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2376,7 +2376,7 @@ public class ActivityManagerService extends IActivityManager.Stub ? Collections.emptyList() : Arrays.asList(exemptions.split(",")); } - if (!ZYGOTE_PROCESS.setApiBlacklistExemptions(mExemptions)) { + if (!ZYGOTE_PROCESS.setApiDenylistExemptions(mExemptions)) { Slog.e(TAG, "Failed to set API blacklist exemptions!"); // leave mExemptionsStr as is, so we don't try to send the same list again. mExemptions = Collections.emptyList(); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index bbd2d34e92a6..055ee1e2a0c0 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -383,7 +383,11 @@ class AppErrors { // 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"), + () -> { + synchronized (mService) { + killAppImmediateLocked(p, "forced", "killed for invalid state"); + } + }, 5000L); } } diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index a75a80a606eb..7f9b3c9fcff7 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -21,14 +21,23 @@ import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.INTERNET; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.UPDATE_DEVICE_STATS; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.INetd.PERMISSION_INTERNET; +import static android.net.INetd.PERMISSION_NETWORK; +import static android.net.INetd.PERMISSION_NONE; +import static android.net.INetd.PERMISSION_SYSTEM; +import static android.net.INetd.PERMISSION_UNINSTALLED; +import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; +import static com.android.internal.util.ArrayUtils.convertToIntArray; + import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -47,11 +56,9 @@ import android.system.OsConstants; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; -import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemConfig; @@ -65,7 +72,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; - /** * A utility class to inform Netd of UID permisisons. * Does a mass update at boot and then monitors for app install/remove. @@ -114,9 +120,51 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse public int getDeviceFirstSdkInt() { return Build.VERSION.FIRST_SDK_INT; } + + /** + * Check whether given uid has specific permission. + */ + public int uidPermission(@NonNull final String permission, final int uid) { + return ActivityManager.checkUidPermission(permission, uid); + } } - public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { + /** + * A data class to store each uid Netd permission information. Netd permissions includes + * PERMISSION_NETWORK, PERMISSION_SYSTEM, PERMISSION_INTERNET, PERMISSION_UPDATE_DEVICE_STATS + * and OR'd with the others. Default permission is PERMISSION_NONE and PERMISSION_UNINSTALLED + * will be set if all packages are removed from the uid. + */ + public static class UidNetdPermissionInfo { + private final int mNetdPermissions; + + UidNetdPermissionInfo() { + this(PERMISSION_NONE); + } + + UidNetdPermissionInfo(int permissions) { + mNetdPermissions = permissions; + } + + /** Plus given permissions and return new UidNetdPermissionInfo instance. */ + public UidNetdPermissionInfo plusNetdPermissions(int permissions) { + return new UidNetdPermissionInfo(mNetdPermissions | permissions); + } + + /** Return whether package is uninstalled. */ + public boolean isPackageUninstalled() { + return mNetdPermissions == PERMISSION_UNINSTALLED; + } + + /** Check that uid has given permissions */ + public boolean hasNetdPermissions(final int permissions) { + if (isPackageUninstalled()) return false; + if (permissions == PERMISSION_NONE) return true; + return (mNetdPermissions & permissions) == permissions; + } + } + + public PermissionMonitor(Context context, INetd netd) { this(context, netd, new Dependencies()); } @@ -147,7 +195,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return; } - SparseIntArray netdPermsUids = new SparseIntArray(); + final SparseArray<UidNetdPermissionInfo> netdPermsUids = new SparseArray<>(); for (PackageInfo app : apps) { int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID; @@ -156,8 +204,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } mAllApps.add(UserHandle.getAppId(uid)); - boolean isNetwork = hasNetworkPermission(app); - boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); + final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); + final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(uid) + || isCarryoverPackage(app.applicationInfo); if (isNetwork || hasRestrictedPermission) { Boolean permission = mApps.get(uid); @@ -168,10 +217,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } + // Skip already checked uid. + if (netdPermsUids.get(uid) != null) continue; + //TODO: unify the management of the permissions into one codepath. - int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); - netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); + final UidNetdPermissionInfo permInfo = + new UidNetdPermissionInfo(getNetdPermissionMask(uid)); + netdPermsUids.put(uid, permInfo); } List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users @@ -186,15 +238,17 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse for (int i = 0; i < systemPermission.size(); i++) { ArraySet<String> perms = systemPermission.valueAt(i); int uid = systemPermission.keyAt(i); - int netdPermission = 0; + int netdPermission = PERMISSION_NONE; // Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission. if (perms != null) { netdPermission |= perms.contains(UPDATE_DEVICE_STATS) - ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0; - netdPermission |= perms.contains(INTERNET) - ? INetd.PERMISSION_INTERNET : 0; + ? PERMISSION_UPDATE_DEVICE_STATS : 0; + netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; } - netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); + final UidNetdPermissionInfo permInfo = netdPermsUids.get(uid); + netdPermsUids.put(uid, permInfo != null + ? permInfo.plusNetdPermissions(netdPermission) + : new UidNetdPermissionInfo(netdPermission)); } log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); update(mUsers, mApps, true); @@ -207,48 +261,34 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) { - if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { - return false; - } - final int index = ArrayUtils.indexOf(app.requestedPermissions, permission); - if (index < 0 || index >= app.requestedPermissionsFlags.length) return false; - return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0; + boolean hasPermission(@NonNull final String permission, final int uid) { + return mDeps.uidPermission(permission, uid) == PackageManager.PERMISSION_GRANTED; } @VisibleForTesting - boolean hasNetworkPermission(@NonNull final PackageInfo app) { - return hasPermission(app, CHANGE_NETWORK_STATE); + // TODO : remove this check in the future(b/162295056). All apps should just request the + // appropriate permission for their use case since android Q. + boolean isCarryoverPackage(@Nullable final ApplicationInfo appInfo) { + if (appInfo == null) return false; + return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo)) + // Backward compatibility for b/114245686, on devices that launched before Q daemons + // and apps running as the system UID are exempted from this check. + || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q); } @VisibleForTesting - boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) { - // TODO : remove this check in the future(b/31479477). All apps should just - // request the appropriate permission for their use case since android Q. - if (app.applicationInfo != null) { - // Backward compatibility for b/114245686, on devices that launched before Q daemons - // and apps running as the system UID are exempted from this check. - if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) { - return true; - } - - if (app.applicationInfo.targetSdkVersion < VERSION_Q - && isVendorApp(app.applicationInfo)) { - return true; - } - } - - return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) - || hasPermission(app, NETWORK_STACK) - || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); + boolean hasRestrictedNetworkPermission(final int uid) { + return hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, uid) + || hasPermission(PERMISSION_MAINLINE_NETWORK_STACK, uid) + || hasPermission(NETWORK_STACK, uid); } /** Returns whether the given uid has using background network permission. */ public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) { // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background - // networks. mApps contains the result of checks for both hasNetworkPermission and - // hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of + // networks. mApps contains the result of checks for both CHANGE_NETWORK_STATE permission + // and hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of // permissions at least. return mApps.containsKey(uid); } @@ -273,11 +313,11 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } try { if (add) { - mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network)); - mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system)); + mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, convertToIntArray(network)); + mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, convertToIntArray(system)); } else { - mNetd.networkClearPermissionForUser(toIntArray(network)); - mNetd.networkClearPermissionForUser(toIntArray(system)); + mNetd.networkClearPermissionForUser(convertToIntArray(network)); + mNetd.networkClearPermissionForUser(convertToIntArray(system)); } } catch (RemoteException e) { loge("Exception when updating permissions: " + e); @@ -323,14 +363,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - protected Boolean highestPermissionForUid(Boolean currentPermission, String name) { + protected Boolean highestPermissionForUid(Boolean currentPermission, String name, int uid) { if (currentPermission == SYSTEM) { return currentPermission; } try { final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS); - final boolean isNetwork = hasNetworkPermission(app); - final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); + final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); + final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(uid) + || isCarryoverPackage(app.applicationInfo); if (isNetwork || hasRestrictedPermission) { currentPermission = hasRestrictedPermission; } @@ -341,24 +382,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return currentPermission; } - private int getPermissionForUid(final int uid) { - int permission = INetd.PERMISSION_NONE; + private UidNetdPermissionInfo getPermissionForUid(final int uid) { // Check all the packages for this UID. The UID has the permission if any of the // packages in it has the permission. final String[] packages = mPackageManager.getPackagesForUid(uid); - if (packages != null && packages.length > 0) { - for (String name : packages) { - final PackageInfo app = getPackageInfo(name); - if (app != null && app.requestedPermissions != null) { - permission |= getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); - } - } - } else { + if (packages == null || packages.length <= 0) { // The last package of this uid is removed from device. Clean the package up. - permission = INetd.PERMISSION_UNINSTALLED; + return new UidNetdPermissionInfo(PERMISSION_UNINSTALLED); } - return permission; + return new UidNetdPermissionInfo(getNetdPermissionMask(uid)); } /** @@ -375,7 +407,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse // If multiple packages share a UID (cf: android:sharedUserId) and ask for different // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). - final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName); + final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName, uid); if (permission != mApps.get(uid)) { mApps.put(uid, permission); @@ -431,7 +463,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse String[] packages = mPackageManager.getPackagesForUid(uid); if (packages != null && packages.length > 0) { for (String name : packages) { - permission = highestPermissionForUid(permission, name); + permission = highestPermissionForUid(permission, name, uid); if (permission == SYSTEM) { // An app with this UID still has the SYSTEM permission. // Therefore, this UID must already have the SYSTEM permission. @@ -467,19 +499,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); } - private static int getNetdPermissionMask(String[] requestedPermissions, - int[] requestedPermissionsFlags) { - int permissions = 0; - if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions; - for (int i = 0; i < requestedPermissions.length; i++) { - if (requestedPermissions[i].equals(INTERNET) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_INTERNET; - } - if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS; - } + private int getNetdPermissionMask(final int uid) { + int permissions = PERMISSION_NONE; + if (hasPermission(INTERNET, uid)) { + permissions |= PERMISSION_INTERNET; + } + if (hasPermission(UPDATE_DEVICE_STATS, uid)) { + permissions |= PERMISSION_UPDATE_DEVICE_STATS; } return permissions; } @@ -614,28 +640,28 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * permission information to netd. * * @param uid the app uid of the package installed - * @param permissions the permissions the app requested and netd cares about. + * @param permissionInfo the permission info of given uid. * * @hide */ @VisibleForTesting - void sendPackagePermissionsForUid(int uid, int permissions) { - SparseIntArray netdPermissionsAppIds = new SparseIntArray(); - netdPermissionsAppIds.put(uid, permissions); - sendPackagePermissionsToNetd(netdPermissionsAppIds); + void sendPackagePermissionsForUid(int uid, UidNetdPermissionInfo permissionInfo) { + final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); + uidsPermInfo.put(uid, permissionInfo); + sendPackagePermissionsToNetd(uidsPermInfo); } /** * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET * and/or UPDATE_DEVICE_STATS permission of the uids in array. * - * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the - * permission is 0, revoke all permissions of that uid. - * + * @param uidsPermInfo permission info array generated from each uid. If the uid permission is + * PERMISSION_NONE or PERMISSION_UNINSTALLED, revoke all permissions of that + * uid. * @hide */ @VisibleForTesting - void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) { + void sendPackagePermissionsToNetd(final SparseArray<UidNetdPermissionInfo> uidsPermInfo) { if (mNetd == null) { Log.e(TAG, "Failed to get the netd service"); return; @@ -645,50 +671,44 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>(); ArrayList<Integer> noPermissionAppIds = new ArrayList<>(); ArrayList<Integer> uninstalledAppIds = new ArrayList<>(); - for (int i = 0; i < netdPermissionsAppIds.size(); i++) { - int permissions = netdPermissionsAppIds.valueAt(i); - switch(permissions) { - case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS): - allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_INTERNET: - internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_UPDATE_DEVICE_STATS: - updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_NONE: - noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_UNINSTALLED: - uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); - default: - Log.e(TAG, "unknown permission type: " + permissions + "for uid: " - + netdPermissionsAppIds.keyAt(i)); + for (int i = 0; i < uidsPermInfo.size(); i++) { + final int uid = uidsPermInfo.keyAt(i); + final UidNetdPermissionInfo permInfo = uidsPermInfo.valueAt(i); + if (permInfo.hasNetdPermissions( + PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)) { + allPermissionAppIds.add(uid); + } else if (permInfo.hasNetdPermissions(PERMISSION_INTERNET)) { + internetPermissionAppIds.add(uid); + } else if (permInfo.hasNetdPermissions(PERMISSION_UPDATE_DEVICE_STATS)) { + updateStatsPermissionAppIds.add(uid); + } else if (permInfo.isPackageUninstalled()) { + uninstalledAppIds.add(uid); + } else { + noPermissionAppIds.add(uid); } } try { // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids() if (allPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids( - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(allPermissionAppIds)); + PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, + convertToIntArray(allPermissionAppIds)); } if (internetPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET, - ArrayUtils.convertToIntArray(internetPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET, + convertToIntArray(internetPermissionAppIds)); } if (updateStatsPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(updateStatsPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, + convertToIntArray(updateStatsPermissionAppIds)); } if (noPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE, - ArrayUtils.convertToIntArray(noPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_NONE, + convertToIntArray(noPermissionAppIds)); } if (uninstalledAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED, - ArrayUtils.convertToIntArray(uninstalledAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED, + convertToIntArray(uninstalledAppIds)); } } catch (RemoteException e) { Log.e(TAG, "Pass appId list of special permission failed." + e); diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 0cde5b1c5b11..2c31cd3fd1e0 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -48,6 +48,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.ConnectivityManager; +import android.net.DnsResolver; import android.net.INetworkManagementEventObserver; import android.net.Ikev2VpnProfile; import android.net.IpPrefix; @@ -79,6 +80,7 @@ import android.net.ipsec.ike.IkeSessionParams; import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.os.CancellationSignal; import android.os.FileUtils; import android.os.IBinder; import android.os.INetworkManagementService; @@ -123,6 +125,7 @@ import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; +import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.util.ArrayList; @@ -134,6 +137,8 @@ import java.util.Objects; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -148,8 +153,8 @@ public class Vpn { private static final boolean LOGD = true; // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on - // the device idle whitelist during service launch and VPN bootstrap. - private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000; + // the device idle allowlist during service launch and VPN bootstrap. + private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000; // Settings for how much of the address space should be routed so that Vpn considers // "most" of the address space is routed. This is used to determine whether this Vpn @@ -175,7 +180,8 @@ public class Vpn { // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm // is actually O(n²)+O(n²). private static final int MAX_ROUTES_TO_EVALUATE = 150; - + private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME = + Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST; /** * Largest profile size allowable for Platform VPNs. * @@ -190,6 +196,7 @@ public class Vpn { // automated reconnection private final Context mContext; + @VisibleForTesting final Dependencies mDeps; private final NetworkInfo mNetworkInfo; @VisibleForTesting protected String mPackage; private int mOwnerUID; @@ -230,7 +237,7 @@ public class Vpn { * Set of packages in addition to the VPN app itself that can access the network directly when * VPN is not connected even if {@code mLockdown} is set. */ - private @NonNull List<String> mLockdownWhitelist = Collections.emptyList(); + private @NonNull List<String> mLockdownAllowlist = Collections.emptyList(); /** * A memory of what UIDs this class told netd to block for the lockdown feature. @@ -252,17 +259,143 @@ public class Vpn { // Handle of the user initiating VPN. private final int mUserHandle; + interface RetryScheduler { + void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; + } + + static class Dependencies { + public void startService(final String serviceName) { + SystemService.start(serviceName); + } + + public void stopService(final String serviceName) { + SystemService.stop(serviceName); + } + + public boolean isServiceRunning(final String serviceName) { + return SystemService.isRunning(serviceName); + } + + public boolean isServiceStopped(final String serviceName) { + return SystemService.isStopped(serviceName); + } + + public File getStateFile() { + return new File("/data/misc/vpn/state"); + } + + public void sendArgumentsToDaemon( + final String daemon, final LocalSocket socket, final String[] arguments, + final RetryScheduler retryScheduler) throws IOException, InterruptedException { + final LocalSocketAddress address = new LocalSocketAddress( + daemon, LocalSocketAddress.Namespace.RESERVED); + + // Wait for the socket to connect. + while (true) { + try { + socket.connect(address); + break; + } catch (Exception e) { + // ignore + } + retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); + } + socket.setSoTimeout(500); + + final OutputStream out = socket.getOutputStream(); + for (String argument : arguments) { + byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); + if (bytes.length >= 0xFFFF) { + throw new IllegalArgumentException("Argument is too large"); + } + out.write(bytes.length >> 8); + out.write(bytes.length); + out.write(bytes); + retryScheduler.checkInterruptAndDelay(false /* sleepLonger */); + } + out.write(0xFF); + out.write(0xFF); + + // Wait for End-of-File. + final InputStream in = socket.getInputStream(); + while (true) { + try { + if (in.read() == -1) { + break; + } + } catch (Exception e) { + // ignore + } + retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); + } + } + + @NonNull + public InetAddress resolve(final String endpoint) + throws ExecutionException, InterruptedException { + try { + return InetAddress.parseNumericAddress(endpoint); + } catch (IllegalArgumentException e) { + // Endpoint is not numeric : fall through and resolve + } + + final CancellationSignal cancellationSignal = new CancellationSignal(); + try { + final DnsResolver resolver = DnsResolver.getInstance(); + final CompletableFuture<InetAddress> result = new CompletableFuture(); + final DnsResolver.Callback<List<InetAddress>> cb = + new DnsResolver.Callback<List<InetAddress>>() { + @Override + public void onAnswer(@NonNull final List<InetAddress> answer, + final int rcode) { + if (answer.size() > 0) { + result.complete(answer.get(0)); + } else { + result.completeExceptionally( + new UnknownHostException(endpoint)); + } + } + + @Override + public void onError(@Nullable final DnsResolver.DnsException error) { + // Unfortunately UnknownHostException doesn't accept a cause, so + // print a message here instead. Only show the summary, not the + // full stack trace. + Log.e(TAG, "Async dns resolver error : " + error); + result.completeExceptionally(new UnknownHostException(endpoint)); + } + }; + resolver.query(null /* network, null for default */, endpoint, + DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb); + return result.get(); + } catch (final ExecutionException e) { + Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e); + throw e; + } catch (final InterruptedException e) { + Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e); + cancellationSignal.cancel(); + throw e; + } + } + + public boolean checkInterfacePresent(final Vpn vpn, final String iface) { + return vpn.jniCheck(iface) == 0; + } + } + public Vpn(Looper looper, Context context, INetworkManagementService netService, @UserIdInt int userHandle, @NonNull KeyStore keyStore) { - this(looper, context, netService, userHandle, keyStore, + this(looper, context, new Dependencies(), netService, userHandle, keyStore, new SystemServices(context), new Ikev2SessionCreator()); } @VisibleForTesting - protected Vpn(Looper looper, Context context, INetworkManagementService netService, + protected Vpn(Looper looper, Context context, Dependencies deps, + INetworkManagementService netService, int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator) { mContext = context; + mDeps = deps; mNetd = netService; mUserHandle = userHandle; mLooper = looper; @@ -388,7 +521,7 @@ public class Vpn { } } if (!hadUnderlyingNetworks) { - // No idea what the underlying networks are; assume sane defaults + // No idea what the underlying networks are; assume the safer defaults metered = true; roaming = false; congested = false; @@ -521,18 +654,18 @@ public class Vpn { * * @param packageName the package to designate as always-on VPN supplier. * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. - * @param lockdownWhitelist packages to be whitelisted from lockdown. + * @param lockdownAllowlist packages to be allowed from lockdown. * @param keyStore the Keystore instance to use for checking of PlatformVpnProfile(s) * @return {@code true} if the package has been set as always-on, {@code false} otherwise. */ public synchronized boolean setAlwaysOnPackage( @Nullable String packageName, boolean lockdown, - @Nullable List<String> lockdownWhitelist, + @Nullable List<String> lockdownAllowlist, @NonNull KeyStore keyStore) { enforceControlPermissionOrInternalCaller(); - if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist, keyStore)) { + if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist, keyStore)) { saveAlwaysOnPackage(); return true; } @@ -547,7 +680,7 @@ public class Vpn { * * @param packageName the package to designate as always-on VPN supplier. * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. - * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if + * @param lockdownAllowlist packages to be allowed to bypass lockdown. This is only used if * {@code lockdown} is {@code true}. Packages must not contain commas. * @param keyStore the system keystore instance to check for profiles * @return {@code true} if the package has been set as always-on, {@code false} otherwise. @@ -555,16 +688,16 @@ public class Vpn { @GuardedBy("this") private boolean setAlwaysOnPackageInternal( @Nullable String packageName, boolean lockdown, - @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore) { + @Nullable List<String> lockdownAllowlist, @NonNull KeyStore keyStore) { if (VpnConfig.LEGACY_VPN.equals(packageName)) { Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); return false; } - if (lockdownWhitelist != null) { - for (String pkg : lockdownWhitelist) { + if (lockdownAllowlist != null) { + for (String pkg : lockdownAllowlist) { if (pkg.contains(",")) { - Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg); + Log.w(TAG, "Not setting always-on vpn, invalid allowed package: " + pkg); return false; } } @@ -592,8 +725,8 @@ public class Vpn { } mLockdown = (mAlwaysOn && lockdown); - mLockdownWhitelist = (mLockdown && lockdownWhitelist != null) - ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist)) + mLockdownAllowlist = (mLockdown && lockdownAllowlist != null) + ? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist)) : Collections.emptyList(); if (isCurrentPreparedPackage(packageName)) { @@ -622,10 +755,10 @@ public class Vpn { } /** - * @return an immutable list of packages whitelisted from always-on VPN lockdown. + * @return an immutable list of packages allowed to bypass always-on VPN lockdown. */ - public synchronized List<String> getLockdownWhitelist() { - return mLockdown ? mLockdownWhitelist : null; + public synchronized List<String> getLockdownAllowlist() { + return mLockdown ? mLockdownAllowlist : null; } /** @@ -640,8 +773,8 @@ public class Vpn { mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); mSystemServices.settingsSecurePutStringForUser( - Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, - String.join(",", mLockdownWhitelist), mUserHandle); + LOCKDOWN_ALLOWLIST_SETTING_NAME, + String.join(",", mLockdownAllowlist), mUserHandle); } finally { Binder.restoreCallingIdentity(token); } @@ -656,12 +789,12 @@ public class Vpn { Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle); final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser( Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0; - final String whitelistString = mSystemServices.settingsSecureGetStringForUser( - Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle); - final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString) - ? Collections.emptyList() : Arrays.asList(whitelistString.split(",")); + final String allowlistString = mSystemServices.settingsSecureGetStringForUser( + LOCKDOWN_ALLOWLIST_SETTING_NAME, mUserHandle); + final List<String> allowedPackages = TextUtils.isEmpty(allowlistString) + ? Collections.emptyList() : Arrays.asList(allowlistString.split(",")); setAlwaysOnPackageInternal( - alwaysOnPackage, alwaysOnLockdown, whitelistedPackages, keyStore); + alwaysOnPackage, alwaysOnLockdown, allowedPackages, keyStore); } finally { Binder.restoreCallingIdentity(token); } @@ -717,7 +850,7 @@ public class Vpn { DeviceIdleController.LocalService idleController = LocalServices.getService(DeviceIdleController.LocalService.class); idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, - VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn"); + VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserHandle, false, "vpn"); // Start the VPN service declared in the app's manifest. Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); @@ -1080,7 +1213,7 @@ public class Vpn { // applications have changed. Consider diffing UID ranges and only applying the delta. if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) || !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) { - Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps"); + Log.i(TAG, "Handover not possible due to changes to allowed/denied apps"); return false; } @@ -1308,13 +1441,13 @@ public class Vpn { * associated with one user, and any restricted profiles attached to that user. * * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, - * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs + * the UID ranges will match the app list specified there. Otherwise, all UIDs * in each user and profile will be included. * * @param userHandle The userId to create UID ranges for along with any of its restricted * profiles. - * @param allowedApplications (optional) whitelist of applications to include. - * @param disallowedApplications (optional) blacklist of applications to exclude. + * @param allowedApplications (optional) List of applications to allow. + * @param disallowedApplications (optional) List of applications to deny. */ @VisibleForTesting Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle, @@ -1348,13 +1481,13 @@ public class Vpn { * associated with one user. * * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, - * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs + * the UID ranges will match the app allowlist or denylist specified there. Otherwise, all UIDs * in the user will be included. * * @param ranges {@link Set} of {@link UidRange}s to which to add. * @param userHandle The userId to add to {@param ranges}. - * @param allowedApplications (optional) whitelist of applications to include. - * @param disallowedApplications (optional) blacklist of applications to exclude. + * @param allowedApplications (optional) allowlist of applications to include. + * @param disallowedApplications (optional) denylist of applications to exclude. */ @VisibleForTesting void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle, @@ -1476,7 +1609,7 @@ public class Vpn { /** * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN - * service app itself and whitelisted packages, to only sockets that have had {@code protect()} + * service app itself and allowed packages, to only sockets that have had {@code protect()} * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the * kernel. * @@ -1498,7 +1631,7 @@ public class Vpn { if (isNullOrLegacyVpn(mPackage)) { exemptedPackages = null; } else { - exemptedPackages = new ArrayList<>(mLockdownWhitelist); + exemptedPackages = new ArrayList<>(mLockdownAllowlist); exemptedPackages.add(mPackage); } final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd); @@ -1543,7 +1676,7 @@ public class Vpn { * Tell netd to add or remove a list of {@link UidRange}s to the list of UIDs that are only * allowed to make connections through sockets that have had {@code protect()} called on them. * - * @param enforce {@code true} to add to the blacklist, {@code false} to remove. + * @param enforce {@code true} to add to the denylist, {@code false} to remove. * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is * {@code true}) or to remove. * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, @@ -2129,7 +2262,8 @@ public class Vpn { } /** This class represents the common interface for all VPN runners. */ - private abstract class VpnRunner extends Thread { + @VisibleForTesting + abstract class VpnRunner extends Thread { protected VpnRunner(String name) { super(name); @@ -2638,7 +2772,7 @@ public class Vpn { } catch (InterruptedException e) { } for (String daemon : mDaemons) { - SystemService.stop(daemon); + mDeps.stopService(daemon); } } agentDisconnect(); @@ -2655,21 +2789,55 @@ public class Vpn { } } + private void checkAndFixupArguments(@NonNull final InetAddress endpointAddress) { + final String endpointAddressString = endpointAddress.getHostAddress(); + // Perform some safety checks before inserting the address in place. + // Position 0 in mDaemons and mArguments must be racoon, and position 1 must be mtpd. + if (!"racoon".equals(mDaemons[0]) || !"mtpd".equals(mDaemons[1])) { + throw new IllegalStateException("Unexpected daemons order"); + } + + // Respectively, the positions at which racoon and mtpd take the server address + // argument are 1 and 2. Not all types of VPN require both daemons however, and + // in that case the corresponding argument array is null. + if (mArguments[0] != null) { + if (!mProfile.server.equals(mArguments[0][1])) { + throw new IllegalStateException("Invalid server argument for racoon"); + } + mArguments[0][1] = endpointAddressString; + } + + if (mArguments[1] != null) { + if (!mProfile.server.equals(mArguments[1][2])) { + throw new IllegalStateException("Invalid server argument for mtpd"); + } + mArguments[1][2] = endpointAddressString; + } + } + private void bringup() { // Catch all exceptions so we can clean up a few things. try { + // resolve never returns null. If it does because of some bug, it will be + // caught by the catch() block below and cleanup gracefully. + final InetAddress endpointAddress = mDeps.resolve(mProfile.server); + + // Big hack : dynamically replace the address of the server in the arguments + // with the resolved address. + checkAndFixupArguments(endpointAddress); + // Initialize the timer. mBringupStartTime = SystemClock.elapsedRealtime(); // Wait for the daemons to stop. for (String daemon : mDaemons) { - while (!SystemService.isStopped(daemon)) { + while (!mDeps.isServiceStopped(daemon)) { checkInterruptAndDelay(true); } } // Clear the previous state. - File state = new File("/data/misc/vpn/state"); + final File state = mDeps.getStateFile(); state.delete(); if (state.exists()) { throw new IllegalStateException("Cannot delete the state"); @@ -2696,57 +2864,19 @@ public class Vpn { // Start the daemon. String daemon = mDaemons[i]; - SystemService.start(daemon); + mDeps.startService(daemon); // Wait for the daemon to start. - while (!SystemService.isRunning(daemon)) { + while (!mDeps.isServiceRunning(daemon)) { checkInterruptAndDelay(true); } // Create the control socket. mSockets[i] = new LocalSocket(); - LocalSocketAddress address = new LocalSocketAddress( - daemon, LocalSocketAddress.Namespace.RESERVED); - - // Wait for the socket to connect. - while (true) { - try { - mSockets[i].connect(address); - break; - } catch (Exception e) { - // ignore - } - checkInterruptAndDelay(true); - } - mSockets[i].setSoTimeout(500); - - // Send over the arguments. - OutputStream out = mSockets[i].getOutputStream(); - for (String argument : arguments) { - byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); - if (bytes.length >= 0xFFFF) { - throw new IllegalArgumentException("Argument is too large"); - } - out.write(bytes.length >> 8); - out.write(bytes.length); - out.write(bytes); - checkInterruptAndDelay(false); - } - out.write(0xFF); - out.write(0xFF); - - // Wait for End-of-File. - InputStream in = mSockets[i].getInputStream(); - while (true) { - try { - if (in.read() == -1) { - break; - } - } catch (Exception e) { - // ignore - } - checkInterruptAndDelay(true); - } + + // Wait for the socket to connect and send over the arguments. + mDeps.sendArgumentsToDaemon(daemon, mSockets[i], arguments, + this::checkInterruptAndDelay); } // Wait for the daemons to create the new state. @@ -2754,7 +2884,7 @@ public class Vpn { // Check if a running daemon is dead. for (int i = 0; i < mDaemons.length; ++i) { String daemon = mDaemons[i]; - if (mArguments[i] != null && !SystemService.isRunning(daemon)) { + if (mArguments[i] != null && !mDeps.isServiceRunning(daemon)) { throw new IllegalStateException(daemon + " is dead"); } } @@ -2764,7 +2894,8 @@ public class Vpn { // Now we are connected. Read and parse the new state. String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); if (parameters.length != 7) { - throw new IllegalStateException("Cannot parse the state"); + throw new IllegalStateException("Cannot parse the state: '" + + String.join("', '", parameters) + "'"); } // Set the interface and the addresses in the config. @@ -2793,20 +2924,15 @@ public class Vpn { } // Add a throw route for the VPN server endpoint, if one was specified. - String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5]; - if (!endpoint.isEmpty()) { - try { - InetAddress addr = InetAddress.parseNumericAddress(endpoint); - if (addr instanceof Inet4Address) { - mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW)); - } else if (addr instanceof Inet6Address) { - mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW)); - } else { - Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint); - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e); - } + if (endpointAddress instanceof Inet4Address) { + mConfig.routes.add(new RouteInfo( + new IpPrefix(endpointAddress, 32), RTN_THROW)); + } else if (endpointAddress instanceof Inet6Address) { + mConfig.routes.add(new RouteInfo( + new IpPrefix(endpointAddress, 128), RTN_THROW)); + } else { + Log.e(TAG, "Unknown IP address family for VPN endpoint: " + + endpointAddress); } // Here is the last step and it must be done synchronously. @@ -2818,7 +2944,7 @@ public class Vpn { checkInterruptAndDelay(false); // Check if the interface is gone while we are waiting. - if (jniCheck(mConfig.interfaze) == 0) { + if (mDeps.checkInterfacePresent(Vpn.this, mConfig.interfaze)) { throw new IllegalStateException(mConfig.interfaze + " is gone"); } @@ -2849,7 +2975,7 @@ public class Vpn { while (true) { Thread.sleep(2000); for (int i = 0; i < mDaemons.length; i++) { - if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { + if (mArguments[i] != null && mDeps.isServiceStopped(mDaemons[i])) { return; } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 78b091e436ac..1c84eefe8d4d 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -241,7 +241,7 @@ abstract class HdmiCecLocalDevice { if (dest != mAddress && dest != Constants.ADDR_BROADCAST) { return false; } - // Cache incoming message. Note that it caches only white-listed one. + // Cache incoming message if it is included in the list of cacheable opcodes. mCecMessageCache.cacheMessage(message); return onMessage(message); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 603dfafc6ff5..19f9715e2b5d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -201,7 +201,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { if (SystemProperties.getBoolean(Constants.PROPERTY_KEEP_AWAKE, true)) { mWakeLock = new SystemWakeLock(); } else { - // Create a dummy lock object that doesn't do anything about wake lock, + // Create a stub lock object that doesn't do anything about wake lock, // hence allows the device to go to sleep even if it's the active source. mWakeLock = new ActiveWakeLock() { @Override diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index 944a95dda99b..75f51d82a8d6 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -81,7 +81,7 @@ public abstract class InputMethodManagerInternal { }; /** - * @return Global instance if exists. Otherwise, a dummy no-op instance. + * @return Global instance if exists. Otherwise, a fallback no-op instance. */ @NonNull public static InputMethodManagerInternal get() { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 69cbc22f41bf..70a3054d8ec3 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -1869,8 +1869,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * @param client {@link android.os.Binder} proxy that is associated with the singleton instance * of {@link android.view.inputmethod.InputMethodManager} that runs on the client * process - * @param inputContext communication channel for the dummy - * {@link android.view.inputmethod.InputConnection} + * @param inputContext communication channel for the fallback {@link InputConnection} * @param selfReportedDisplayId self-reported display ID to which the client is associated. * Whether the client is still allowed to access to this display * or not needs to be evaluated every time the client interacts diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 3dd730471dca..956de656ab65 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -1590,7 +1590,7 @@ public final class MultiClientInputMethodManagerService { } if (editorInfo == null) { - // So-called dummy InputConnection scenario. For app compatibility, we still + // So-called fallback InputConnection scenario. For app compatibility, we still // notify this to the IME. switch (clientInfo.mState) { case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT: diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS index b460cb5b23ea..2e2d812c058e 100644 --- a/services/core/java/com/android/server/media/OWNERS +++ b/services/core/java/com/android/server/media/OWNERS @@ -2,6 +2,7 @@ elaurent@google.com hdmoon@google.com insun@google.com jaewan@google.com +jinpark@google.com klhyun@google.com lajos@google.com sungsoo@google.com diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index ab525237db5c..ba3cea768c2d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -28,6 +28,7 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; +import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.server.net.NetworkStatsService.TAG; @@ -185,35 +186,6 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } - /** - * Safely multiple a value by a rational. - * <p> - * Internally it uses integer-based math whenever possible, but switches - * over to double-based math if values would overflow. - */ - @VisibleForTesting - public static long multiplySafe(long value, long num, long den) { - if (den == 0) den = 1; - long x = value; - long y = num; - - // Logic shamelessly borrowed from Math.multiplyExact() - long r = x * y; - long ax = Math.abs(x); - long ay = Math.abs(y); - if (((ax | ay) >>> 31 != 0)) { - // Some bits greater than 2^31 that might cause overflow - // Check the result using the divide operator - // and check for the special case of Long.MIN_VALUE * -1 - if (((y != 0) && (r / y != x)) || - (x == Long.MIN_VALUE && y == -1)) { - // Use double math to avoid overflowing - return (long) (((double) num / den) * value); - } - } - return r / den; - } - public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } @@ -311,11 +283,13 @@ public class NetworkStatsCollection implements FileRotator.Reader { } final long rawBytes = entry.rxBytes + entry.txBytes; - final long rawRxBytes = entry.rxBytes; - final long rawTxBytes = entry.txBytes; + final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes; + final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); - final long targetRxBytes = multiplySafe(targetBytes, rawRxBytes, rawBytes); - final long targetTxBytes = multiplySafe(targetBytes, rawTxBytes, rawBytes); + + final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes); + final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes); + // Scale all matching buckets to reach anchor target final long beforeTotal = combined.getTotalBytes(); @@ -323,8 +297,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { combined.getValues(i, entry); if (entry.bucketStart >= augmentStart && entry.bucketStart + entry.bucketDuration <= augmentEnd) { - entry.rxBytes = multiplySafe(targetRxBytes, entry.rxBytes, rawRxBytes); - entry.txBytes = multiplySafe(targetTxBytes, entry.txBytes, rawTxBytes); + entry.rxBytes = multiplySafeByRational( + targetRxBytes, entry.rxBytes, rawRxBytes); + entry.txBytes = multiplySafeByRational( + targetTxBytes, entry.txBytes, rawTxBytes); // We purposefully clear out packet counters to indicate // that this data has been augmented. entry.rxPackets = 0; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 86ad0b308676..e9868fde3059 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -59,7 +59,7 @@ public class NetworkStatsFactory { private static final String TAG = "NetworkStatsFactory"; private static final boolean USE_NATIVE_PARSING = true; - private static final boolean SANITY_CHECK_NATIVE = false; + private static final boolean VALIDATE_NATIVE_STATS = false; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; @@ -347,7 +347,7 @@ public class NetworkStatsFactory { INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); } - if (SANITY_CHECK_NATIVE) { + if (VALIDATE_NATIVE_STATS) { final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL, TAG_ALL); assertEquals(javaStats, stats); diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a94a2f79ab0f..66eda1fc2d93 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -227,7 +227,7 @@ public class NetworkStatsRecorder { for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); - // As a last-ditch sanity check, report any negative values and + // As a last-ditch check, report any negative values and // clamp them so recording below doesn't croak. if (entry.isNegative()) { if (mObserver != null) { diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 5f2c4a38b42a..0575ac6315a1 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -127,7 +127,7 @@ public class NetworkStatsSubscriptionsMonitor extends @NonNull private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { final ArrayList<Integer> ret = new ArrayList<>(); - final int[] ids = subscriptionManager.getActiveAndHiddenSubscriptionIdList(); + final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); for (int id : ids) ret.add(id); return ret; } diff --git a/services/core/java/com/android/server/notification/RankingReconsideration.java b/services/core/java/com/android/server/notification/RankingReconsideration.java index 057f0f111e5d..9b046b118aab 100644 --- a/services/core/java/com/android/server/notification/RankingReconsideration.java +++ b/services/core/java/com/android/server/notification/RankingReconsideration.java @@ -90,7 +90,7 @@ public abstract class RankingReconsideration implements Runnable { /** * Apply any computed changes to the notification record. This method will be - * called on the main service thread, synchronized on he mNotificationList. + * called on the main service thread, synchronized on the mNotificationList. * @param record The locked record to be updated. */ public abstract void applyChangesLocked(NotificationRecord record); diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index fe6aad70c31e..e48862e2e5e0 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -14,16 +14,16 @@ per-file ApexManager.java = dariofreni@google.com, ioffe@google.com, olilan@goog per-file StagingManager.java = dariofreni@google.com, ioffe@google.com, olilan@google.com # dex -per-file AbstractStatsBase.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file BackgroundDexOptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file CompilerStats.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file DynamicCodeLoggingService.java = alanstokes@google.com, agampe@google.com, calin@google.com, ngeoffray@google.com -per-file InstructionSets.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file OtaDexoptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file OtaDexoptShellCommand.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file PackageDexOptimizer.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, calin@google.com, ngeoffray@google.com -per-file PackageUsage.java = agampe@google.com, calin@google.com, ngeoffray@google.com +per-file AbstractStatsBase.java = calin@google.com, ngeoffray@google.com +per-file BackgroundDexOptService.java = calin@google.com, ngeoffray@google.com +per-file CompilerStats.java = calin@google.com, ngeoffray@google.com +per-file DynamicCodeLoggingService.java = alanstokes@google.com, calin@google.com, ngeoffray@google.com +per-file InstructionSets.java = calin@google.com, ngeoffray@google.com +per-file OtaDexoptService.java = calin@google.com, ngeoffray@google.com +per-file OtaDexoptShellCommand.java = calin@google.com, ngeoffray@google.com +per-file PackageDexOptimizer.java = calin@google.com, ngeoffray@google.com +per-file PackageManagerServiceCompilerMapping.java = calin@google.com, ngeoffray@google.com +per-file PackageUsage.java = calin@google.com, ngeoffray@google.com # multi user / cross profile per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 994fca80e672..2657751b9f29 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2649,7 +2649,7 @@ public final class Settings { private void writePackageListLPrInternal(int creatingUserId) { // Only derive GIDs for active users (not dying) - final List<UserInfo> users = getUsers(UserManagerService.getInstance(), true); + final List<UserInfo> users = getActiveUsers(UserManagerService.getInstance(), true); int[] userIds = new int[users.size()]; for (int i = 0; i < userIds.length; i++) { userIds[i] = users.get(i).id; @@ -4325,25 +4325,43 @@ public final class Settings { } /** - * Return all users on the device, including partial or dying users. + * Returns all users on the device, including pre-created and dying users. + * * @param userManager UserManagerService instance * @return the list of users */ private static List<UserInfo> getAllUsers(UserManagerService userManager) { - return getUsers(userManager, false); + return getUsers(userManager, /* excludeDying= */ false, /* excludePreCreated= */ false); + } + + /** + * Returns the list of users on the device, excluding pre-created ones. + * + * @param userManager UserManagerService instance + * @param excludeDying Indicates whether to exclude any users marked for deletion. + * + * @return the list of users + */ + private static List<UserInfo> getActiveUsers(UserManagerService userManager, + boolean excludeDying) { + return getUsers(userManager, excludeDying, /* excludePreCreated= */ true); } /** - * Return the list of users on the device. Clear the calling identity before calling into - * UserManagerService. + * Returns the list of users on the device. + * * @param userManager UserManagerService instance * @param excludeDying Indicates whether to exclude any users marked for deletion. + * @param excludePreCreated Indicates whether to exclude any pre-created users. + * * @return the list of users */ - private static List<UserInfo> getUsers(UserManagerService userManager, boolean excludeDying) { + private static List<UserInfo> getUsers(UserManagerService userManager, boolean excludeDying, + boolean excludePreCreated) { long id = Binder.clearCallingIdentity(); try { - return userManager.getUsers(excludeDying); + return userManager.getUsers(/* excludePartial= */ true, excludeDying, + excludePreCreated); } catch (NullPointerException npe) { // packagemanager not yet initialized } finally { diff --git a/services/core/java/com/android/server/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS index fcc1f6c10eac..5a4431ee8c89 100644 --- a/services/core/java/com/android/server/pm/dex/OWNERS +++ b/services/core/java/com/android/server/pm/dex/OWNERS @@ -1,4 +1,2 @@ -agampe@google.com calin@google.com ngeoffray@google.com -sehr@google.com diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java index e4cb19e3eb21..9464dbf44e9e 100644 --- a/services/core/java/com/android/server/twilight/TwilightService.java +++ b/services/core/java/com/android/server/twilight/TwilightService.java @@ -22,7 +22,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.icu.impl.CalendarAstronomer; import android.icu.util.Calendar; import android.location.Location; import android.location.LocationListener; @@ -37,6 +36,8 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.SystemService; +import com.ibm.icu.impl.CalendarAstronomer; + import java.util.Objects; /** diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 0e2f0ce991c7..8648e9fd2515 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -3038,7 +3038,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub mLockWallpaperMap.put(userId, wallpaper); ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY); } else { - // sanity fallback: we're in bad shape, but establishing a known + // rationality fallback: we're in bad shape, but establishing a known // valid system+lock WallpaperData will keep us from dying. Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!"); wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 549c5a2387b1..e7577a61ca1a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -61,6 +61,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; @@ -1297,6 +1298,13 @@ public class WindowManagerService extends IWindowManager.Stub return WindowManagerGlobal.ADD_PERMISSION_DENIED; } + if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) { + Slog.w(TAG_WM, + "Attempted to add presentation window to a non-suitable display. " + + "Aborting."); + return WindowManagerGlobal.ADD_INVALID_DISPLAY; + } + AppWindowToken atoken = null; final boolean hasParent = parentWindow != null; // Use existing parent window token for child windows since they go in the same token diff --git a/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp index 503f0cf993d4..3dfce3aec059 100644 --- a/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp +++ b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp @@ -235,7 +235,7 @@ static jint nativeOpenHal(JNIEnv* env, jobject clazz) { return 0; } - // Sanity check - remove + // Soundness check - remove if (gContext.device->notify != hal_notify_callback) { ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback); } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 1f445c9ca3bd..375a813639d1 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -424,6 +424,10 @@ void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportO AutoMutex _l(mLock); mLocked.viewports = viewports; mLocked.pointerDisplayId = pointerDisplayId; + std::shared_ptr<PointerController> controller = mLocked.pointerController.lock(); + if (controller != nullptr) { + controller->onDisplayViewportsUpdated(mLocked.viewports); + } } // release lock mInputManager->getReader()->requestRefreshConfiguration( @@ -847,8 +851,8 @@ void NativeInputManager::updateInactivityTimeoutLocked() REQUIRES(mLock) { } bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN; - controller->setInactivityTimeout(lightsOut ? PointerController::InactivityTimeout::SHORT - : PointerController::InactivityTimeout::NORMAL); + controller->setInactivityTimeout(lightsOut ? InactivityTimeout::SHORT + : InactivityTimeout::NORMAL); } void NativeInputManager::setPointerSpeed(int32_t speed) { diff --git a/services/net/Android.bp b/services/net/Android.bp index 8b444b0fed41..d071e0a5667b 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -19,46 +19,6 @@ java_library_static { ], } -// Version of services.net for usage by the wifi mainline module. -// Note: This is compiled against module_current. -// TODO(b/145825329): This should be moved to networkstack-client, -// with dependencies moved to frameworks/libs/net right. -java_library { - name: "services.net-module-wifi", - srcs: [ - ":framework-services-net-module-wifi-shared-srcs", - ":net-module-utils-srcs", - "java/android/net/ip/IpClientCallbacks.java", - "java/android/net/ip/IpClientManager.java", - "java/android/net/ip/IpClientUtil.java", - "java/android/net/util/KeepalivePacketDataUtil.java", - "java/android/net/util/NetworkConstants.java", - "java/android/net/IpMemoryStore.java", - "java/android/net/NetworkMonitorManager.java", - "java/android/net/TcpKeepalivePacketData.java", - ], - sdk_version: "module_current", - libs: [ - "unsupportedappusage", - "framework-wifi-util-lib", - ], - static_libs: [ - // 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", - "net-utils-services-common", - ], - apex_available: [ - "com.android.wifi", - ], - visibility: [ - "//frameworks/opt/net/wifi/service", - "//frameworks/opt/net/wifi/tests/wifitests", - ], -} - filegroup { name: "services-tethering-shared-srcs", srcs: [ diff --git a/services/net/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java index b172c4be7b0d..b17fcaa132a1 100644 --- a/services/net/java/android/net/ip/IpClientCallbacks.java +++ b/services/net/java/android/net/ip/IpClientCallbacks.java @@ -68,12 +68,13 @@ public class IpClientCallbacks { */ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { // In general callbacks would not use a parcelable directly (DhcpResultsParcelable), and - // would use a wrapper instead. But there are already two classes in the tree for DHCP - // information: DhcpInfo and DhcpResults, and each of them do not expose an appropriate API - // (they are bags of mutable fields and can't be changed because they are public API and - // @UnsupportedAppUsage). Adding a third class would cost more than the gain considering - // that the only client of this callback is WiFi, which will end up converting the results - // to DhcpInfo anyway. + // would use a wrapper instead, because of the lack of safety of stable parcelables. But + // there are already two classes in the tree for DHCP information: DhcpInfo and DhcpResults, + // and neither of them exposes an appropriate API (they are bags of mutable fields and can't + // be changed because they are public API and @UnsupportedAppUsage, being no better than the + // stable parcelable). Adding a third class would cost more than the gain considering that + // the only client of this callback is WiFi, which will end up converting the results to + // DhcpInfo anyway. } /** diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp index 17d0bbfad171..566e61e1a14f 100644 --- a/services/robotests/Android.bp +++ b/services/robotests/Android.bp @@ -43,6 +43,7 @@ android_robolectric_test { // Include the testing libraries libs: [ "platform-test-annotations", + "services.backup", "testng", ], diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java index e4c9cc3c05d9..1d914ec083fa 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java @@ -88,36 +88,36 @@ public class InputMethodUtilsTest { public void testVoiceImes() throws Exception { // locale: en_US assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); // locale: en_GB assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); // locale: ja_JP assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme"); + "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme"); assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0", - "DummyNonDefaultAutoVoiceIme1"); + "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0", + "FakeNonDefaultAutoVoiceIme1"); assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP, - "DummyDefaultEnKeyboardIme"); + "FakeDefaultEnKeyboardIme"); } @Test @@ -189,67 +189,67 @@ public class InputMethodUtilsTest { @Test public void testGetImplicitlyApplicableSubtypesLocked() throws Exception { - final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnIN = createDummyInputMethodSubtype("en_IN", + final InputMethodSubtype nonAutoEnIN = createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA", + final InputMethodSubtype nonAutoFrCA = createFakeInputMethodSubtype("fr_CA", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA", + final InputMethodSubtype nonAutoFr = createFakeInputMethodSubtype("fr_CA", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto", + final InputMethodSubtype autoSubtype = createFakeInputMethodSubtype("auto", SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja", + final InputMethodSubtype nonAutoJa = createFakeInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi", + final InputMethodSubtype nonAutoHi = createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoSrCyrl = createDummyInputMethodSubtype("sr", + final InputMethodSubtype nonAutoSrCyrl = createFakeInputMethodSubtype("sr", "sr-Cyrl", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoSrLatn = createDummyInputMethodSubtype("sr_ZZ", + final InputMethodSubtype nonAutoSrLatn = createFakeInputMethodSubtype("sr_ZZ", "sr-Latn", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en", + final InputMethodSubtype nonAutoHandwritingEn = createFakeInputMethodSubtype("en", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingFr = createDummyInputMethodSubtype("fr", + final InputMethodSubtype nonAutoHandwritingFr = createFakeInputMethodSubtype("fr", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingSrCyrl = createDummyInputMethodSubtype("sr", + final InputMethodSubtype nonAutoHandwritingSrCyrl = createFakeInputMethodSubtype("sr", "sr-Cyrl", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoHandwritingSrLatn = createDummyInputMethodSubtype("sr_ZZ", + final InputMethodSubtype nonAutoHandwritingSrLatn = createFakeInputMethodSubtype("sr_ZZ", "sr-Latn", SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype = - createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 = - createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); @@ -266,9 +266,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -290,9 +290,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -314,9 +314,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -339,9 +339,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -360,9 +360,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -382,9 +382,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -404,9 +404,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -421,9 +421,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingEn); subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -438,9 +438,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoEnUS); subtypes.add(nonAutoHi); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -460,9 +460,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -480,9 +480,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -506,9 +506,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoHandwritingFr); subtypes.add(nonAutoHandwritingSrCyrl); subtypes.add(nonAutoHandwritingSrLatn); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -533,9 +533,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoEnUS); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -551,9 +551,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoJa); subtypes.add(nonAutoEnUS); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -567,9 +567,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -581,9 +581,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -595,9 +595,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -609,9 +609,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -631,9 +631,9 @@ public class InputMethodUtilsTest { subtypes.add(nonAutoFil); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( @@ -649,22 +649,22 @@ public class InputMethodUtilsTest { @Test public void testContainsSubtypeOf() throws Exception { - final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH", + final InputMethodSubtype nonAutoFilPH = createFakeInputMethodSubtype("fil_PH", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); - final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); @@ -673,9 +673,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY, @@ -705,9 +705,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoFil); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -732,9 +732,9 @@ public class InputMethodUtilsTest { { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoFilPH); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -760,9 +760,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoIn); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -779,9 +779,9 @@ public class InputMethodUtilsTest { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); subtypes.add(nonAutoId); subtypes.add(nonAutoEnUS); - final InputMethodInfo imi = createDummyInputMethodInfo( + final InputMethodInfo imi = createFakeInputMethodInfo( "com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, SUBTYPE_MODE_KEYBOARD)); @@ -866,7 +866,7 @@ public class InputMethodUtilsTest { assertEquals(expected.hashCode(), actual.hashCode()); } - private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, + private static InputMethodInfo createFakeInputMethodInfo(String packageName, String name, CharSequence label, boolean isAuxIme, boolean isDefault, List<InputMethodSubtype> subtypes) { final ResolveInfo ri = new ResolveInfo(); @@ -885,15 +885,15 @@ public class InputMethodUtilsTest { return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault); } - private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, + private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String mode, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { - return createDummyInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary, + return createFakeInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable, isEnabledWhenDefaultIsNotAsciiCapable); } - private static InputMethodSubtype createDummyInputMethodSubtype(String locale, + private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String languageTag, String mode, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { @@ -920,14 +920,14 @@ public class InputMethodUtilsTest { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", - "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultAutoVoiceIme", + "fake.voice0", "FakeVoice0", IS_AUX, IS_DEFAULT, subtypes)); } preinstalledImes.addAll(getImesWithoutDefaultVoiceIme()); return preinstalledImes; @@ -937,41 +937,41 @@ public class InputMethodUtilsTest { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", - "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme0", + "fake.voice1", "FakeVoice1", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", - "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme1", + "fake.voice2", "FakeVoice2", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", - "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultVoiceIme2", + "fake.voice3", "FakeVoice3", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", - "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); + preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultEnKeyboardIme", + "fake.keyboard0", "FakeKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); } return preinstalledImes; } @@ -991,91 +991,91 @@ public class InputMethodUtilsTest { private static ArrayList<InputMethodInfo> getSamplePreinstalledImes(final String localeString) { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); - // a dummy Voice IME + // a fake Voice IME { final boolean isDefaultIme = false; final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, + subtypes.add(createFakeInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice", - "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.voice", + "com.android.inputmethod.voice", "FakeVoiceIme", IS_AUX, isDefaultIme, subtypes)); } - // a dummy Hindi IME + // a fake Hindi IME { final boolean isDefaultIme = contains(new String[]{ "hi", "en-rIN" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); // TODO: This subtype should be marked as IS_ASCII_CAPABLE - subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi", - "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.hindi", + "com.android.inputmethod.hindi", "FakeHindiIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Pinyin IME + // a fake Pinyin IME { final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin", - "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.pinyin", + "com.android.apps.inputmethod.pinyin", "FakePinyinIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Korean IME + // a fake Korean IME { final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean", - "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.korean", + "com.android.apps.inputmethod.korean", "FakeKoreanIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Latin IME + // a fake Latin IME { final boolean isDefaultIme = contains( new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin", - "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, isDefaultIme, subtypes)); } - // a dummy Japanese IME + // a fake Japanese IME { final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); - subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + subtypes.add(createFakeInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); - preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese", - "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX, + preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.japanese", + "com.android.apps.inputmethod.japanese", "FakeJapaneseIme", !IS_AUX, isDefaultIme, subtypes)); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java index 0d44318e4aaa..f8d78b4a734d 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java @@ -214,20 +214,14 @@ public class NotificationShellCmdTest extends UiServiceTestCase { "Charlotte" }; static final String[] MESSAGES = { - "Shall I compare thee to a summer's day?", - "Thou art more lovely and more temperate:", - "Rough winds do shake the darling buds of May,", - "And summer's lease hath all too short a date;", - "Sometime too hot the eye of heaven shines,", - "And often is his gold complexion dimm'd;", - "And every fair from fair sometime declines,", - "By chance or nature's changing course untrimm'd;", - "But thy eternal summer shall not fade,", - "Nor lose possession of that fair thou ow'st;", - "Nor shall death brag thou wander'st in his shade,", - "When in eternal lines to time thou grow'st:", - " So long as men can breathe or eyes can see,", - " So long lives this, and this gives life to thee.", + "Who has seen the wind?", + "Neither I nor you.", + "But when the leaves hang trembling,", + "The wind is passing through.", + "Who has seen the wind?", + "Neither you nor I.", + "But when the trees bow down their heads,", + "The wind is passing by." }; @Test diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java index 6861ad1b2e2d..4986d1883307 100644 --- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java +++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java @@ -307,7 +307,7 @@ public class AppTimeLimitController { } } else { if (mActives > mObserved.length) { - // Try to get to a sane state and log the issue + // Try to get to a valid state and log the issue mActives = mObserved.length; final UserData user = mUserRef.get(); if (user == null) return; @@ -334,7 +334,7 @@ public class AppTimeLimitController { cancelCheckTimeoutLocked(this); } else { if (mActives < 0) { - // Try to get to a sane state and log the issue + // Try to get to a valid state and log the issue mActives = 0; final UserData user = mUserRef.get(); if (user == null) return; diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index 5239d976e66f..22629dd52608 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -64,7 +64,7 @@ public final class UsbAlsaManager { private UsbAlsaDevice mSelectedDevice; // - // Device Blacklist + // Device Denylist // // This exists due to problems with Sony game controllers which present as an audio device // even if no headset is connected and have no way to set the volume on the unit. @@ -73,31 +73,31 @@ public final class UsbAlsaManager { private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4; private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC; - private static final int USB_BLACKLIST_OUTPUT = 0x0001; - private static final int USB_BLACKLIST_INPUT = 0x0002; + private static final int USB_DENYLIST_OUTPUT = 0x0001; + private static final int USB_DENYLIST_INPUT = 0x0002; - private static class BlackListEntry { + private static class DenyListEntry { final int mVendorId; final int mProductId; final int mFlags; - BlackListEntry(int vendorId, int productId, int flags) { + DenyListEntry(int vendorId, int productId, int flags) { mVendorId = vendorId; mProductId = productId; mFlags = flags; } } - static final List<BlackListEntry> sDeviceBlacklist = Arrays.asList( - new BlackListEntry(USB_VENDORID_SONY, + static final List<DenyListEntry> sDeviceDenylist = Arrays.asList( + new DenyListEntry(USB_VENDORID_SONY, USB_PRODUCTID_PS4CONTROLLER_ZCT1, - USB_BLACKLIST_OUTPUT), - new BlackListEntry(USB_VENDORID_SONY, + USB_DENYLIST_OUTPUT), + new DenyListEntry(USB_VENDORID_SONY, USB_PRODUCTID_PS4CONTROLLER_ZCT2, - USB_BLACKLIST_OUTPUT)); + USB_DENYLIST_OUTPUT)); - private static boolean isDeviceBlacklisted(int vendorId, int productId, int flags) { - for (BlackListEntry entry : sDeviceBlacklist) { + private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) { + for (DenyListEntry entry : sDeviceDenylist) { if (entry.mVendorId == vendorId && entry.mProductId == productId) { // see if the type flag is set return (entry.mFlags & flags) != 0; @@ -226,11 +226,11 @@ public final class UsbAlsaManager { // Add it to the devices list boolean hasInput = parser.hasInput() - && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(), - USB_BLACKLIST_INPUT); + && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(), + USB_DENYLIST_INPUT); boolean hasOutput = parser.hasOutput() - && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(), - USB_BLACKLIST_OUTPUT); + && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(), + USB_DENYLIST_OUTPUT); if (DEBUG) { Slog.d(TAG, "hasInput: " + hasInput + " hasOutput:" + hasOutput); } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 121a5b57a69c..68bd301498ad 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -190,22 +190,22 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private String[] mAccessoryStrings; private final UEventObserver mUEventObserver; - private static Set<Integer> sBlackListedInterfaces; + private static Set<Integer> sDenyInterfaces; private HashMap<Long, FileDescriptor> mControlFds; static { - sBlackListedInterfaces = new HashSet<>(); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_AUDIO); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_COMM); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HID); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_PRINTER); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HUB); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CSCID); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_VIDEO); - sBlackListedInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER); + sDenyInterfaces = new HashSet<>(); + sDenyInterfaces.add(UsbConstants.USB_CLASS_AUDIO); + sDenyInterfaces.add(UsbConstants.USB_CLASS_COMM); + sDenyInterfaces.add(UsbConstants.USB_CLASS_HID); + sDenyInterfaces.add(UsbConstants.USB_CLASS_PRINTER); + sDenyInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE); + sDenyInterfaces.add(UsbConstants.USB_CLASS_HUB); + sDenyInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA); + sDenyInterfaces.add(UsbConstants.USB_CLASS_CSCID); + sDenyInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC); + sDenyInterfaces.add(UsbConstants.USB_CLASS_VIDEO); + sDenyInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER); } /* @@ -884,7 +884,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser while (interfaceCount >= 0) { UsbInterface intrface = config.getInterface(interfaceCount); interfaceCount--; - if (sBlackListedInterfaces.contains(intrface.getInterfaceClass())) { + if (sDenyInterfaces.contains(intrface.getInterfaceClass())) { mHideUsbNotification = true; break; } diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index 812237489063..c0097bfc6f81 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -62,7 +62,7 @@ public class UsbHostManager { private final Context mContext; // USB busses to exclude from USB host support - private final String[] mHostBlacklist; + private final String[] mHostDenyList; private final UsbAlsaManager mUsbAlsaManager; private final UsbSettingsManager mSettingsManager; @@ -235,8 +235,8 @@ public class UsbHostManager { UsbSettingsManager settingsManager) { mContext = context; - mHostBlacklist = context.getResources().getStringArray( - com.android.internal.R.array.config_usbHostBlacklist); + mHostDenyList = context.getResources().getStringArray( + com.android.internal.R.array.config_usbHostDenylist); mUsbAlsaManager = alsaManager; mSettingsManager = settingsManager; String deviceConnectionHandler = context.getResources().getString( @@ -271,10 +271,10 @@ public class UsbHostManager { } } - private boolean isBlackListed(String deviceAddress) { - int count = mHostBlacklist.length; + private boolean isDenyListed(String deviceAddress) { + int count = mHostDenyList.length; for (int i = 0; i < count; i++) { - if (deviceAddress.startsWith(mHostBlacklist[i])) { + if (deviceAddress.startsWith(mHostDenyList[i])) { return true; } } @@ -282,11 +282,11 @@ public class UsbHostManager { } /* returns true if the USB device should not be accessible by applications */ - private boolean isBlackListed(int clazz, int subClass) { - // blacklist hubs + private boolean isDenyListed(int clazz, int subClass) { + // deny hubs if (clazz == UsbConstants.USB_CLASS_HUB) return true; - // blacklist HID boot devices (mouse and keyboard) + // deny HID boot devices (mouse and keyboard) return clazz == UsbConstants.USB_CLASS_HID && subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT; @@ -355,23 +355,23 @@ public class UsbHostManager { Slog.d(TAG, "usbDeviceAdded(" + deviceAddress + ") - start"); } - if (isBlackListed(deviceAddress)) { + if (isDenyListed(deviceAddress)) { if (DEBUG) { - Slog.d(TAG, "device address is black listed"); + Slog.d(TAG, "device address is Deny listed"); } return false; } - if (isBlackListed(deviceClass, deviceSubclass)) { + if (isDenyListed(deviceClass, deviceSubclass)) { if (DEBUG) { - Slog.d(TAG, "device class is black listed"); + Slog.d(TAG, "device class is deny listed"); } return false; } UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress, descriptors); if (deviceClass == UsbConstants.USB_CLASS_PER_INTERFACE - && !checkUsbInterfacesBlackListed(parser)) { + && !checkUsbInterfacesDenyListed(parser)) { return false; } @@ -488,12 +488,12 @@ public class UsbHostManager { public ParcelFileDescriptor openDevice(String deviceAddress, UsbUserSettingsManager settings, String packageName, int pid, int uid) { synchronized (mLock) { - if (isBlackListed(deviceAddress)) { + if (isDenyListed(deviceAddress)) { throw new SecurityException("USB device is on a restricted bus"); } UsbDevice device = mDevices.get(deviceAddress); if (device == null) { - // if it is not in mDevices, it either does not exist or is blacklisted + // if it is not in mDevices, it either does not exist or is denylisted throw new IllegalArgumentException( "device " + deviceAddress + " does not exist or is restricted"); } @@ -551,23 +551,23 @@ public class UsbHostManager { } } - private boolean checkUsbInterfacesBlackListed(UsbDescriptorParser parser) { + private boolean checkUsbInterfacesDenyListed(UsbDescriptorParser parser) { // Device class needs to be obtained through the device interface. Ignore device only - // if ALL interfaces are black-listed. + // if ALL interfaces are deny-listed. boolean shouldIgnoreDevice = false; for (UsbDescriptor descriptor: parser.getDescriptors()) { if (!(descriptor instanceof UsbInterfaceDescriptor)) { continue; } UsbInterfaceDescriptor iface = (UsbInterfaceDescriptor) descriptor; - shouldIgnoreDevice = isBlackListed(iface.getUsbClass(), iface.getUsbSubclass()); + shouldIgnoreDevice = isDenyListed(iface.getUsbClass(), iface.getUsbSubclass()); if (!shouldIgnoreDevice) { break; } } if (shouldIgnoreDevice) { if (DEBUG) { - Slog.d(TAG, "usb interface class is black listed"); + Slog.d(TAG, "usb interface class is deny listed"); } return false; } diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index 749258e76f79..0e30f9380ff3 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -921,7 +921,7 @@ public class UsbPortManager { contaminantDetectionStatus); mPorts.put(portId, portInfo); } else { - // Sanity check that ports aren't changing definition out from under us. + // Validate that ports aren't changing definition out from under us. if (supportedModes != portInfo.mUsbPort.getSupportedModes()) { logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from " + "USB port driver (should be immutable): " diff --git a/startop/OWNERS b/startop/OWNERS index 5cf95825d11b..2d1eb38952ed 100644 --- a/startop/OWNERS +++ b/startop/OWNERS @@ -1,6 +1,7 @@ # mailing list: startop-eng@google.com +calin@google.com chriswailes@google.com eholk@google.com iam@google.com mathieuc@google.com -sehr@google.com +yawanng@google.com diff --git a/telecomm/TEST_MAPPING b/telecomm/TEST_MAPPING index d58566673eec..c9903f9fa901 100644 --- a/telecomm/TEST_MAPPING +++ b/telecomm/TEST_MAPPING @@ -23,6 +23,14 @@ "exclude-annotation": "androidx.test.filters.FlakyTest" } ] + }, + { + "name": "CtsTelecomTestCases", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] } ] } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index ead90bb4561f..4b9a9abac88f 100755 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -461,15 +461,15 @@ public final class Call { /** * Call supports adding participants to the call via - * {@link #addConferenceParticipants(List)}. - * @hide + * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes + * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}). */ public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000; /** * When set for a call, indicates that this {@code Call} can be transferred to another * number. - * Call supports the blind and assured call transfer feature. + * Call supports the confirmed and unconfirmed call transfer feature. * * @hide */ @@ -598,8 +598,11 @@ public final class Call { /** * Indicates that the call is an adhoc conference call. This property can be set for both - * incoming and outgoing calls. - * @hide + * incoming and outgoing calls. An adhoc conference call is formed using + * {@link #addConferenceParticipants(List)}, + * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or + * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing + * call using {@link #conference(Call)}. */ public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000; @@ -1592,8 +1595,8 @@ public final class Call { * Instructs this {@code Call} to be transferred to another number. * * @param targetNumber The address to which the call will be transferred. - * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer, - * if {@code false}, it will initiate BLIND transfer. + * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer, + * if {@code false}, it will initiate an unconfirmed transfer. * * @hide */ @@ -1766,7 +1769,6 @@ public final class Call { * See {@link Details#CAPABILITY_ADD_PARTICIPANT}. * * @param participants participants to be pulled to existing call. - * @hide */ public void addConferenceParticipants(@NonNull List<Uri> participants) { mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants); diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index d9605522b3b0..39c3ff9e8839 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -181,8 +181,8 @@ public abstract class Conference extends Conferenceable { /** * Returns whether this conference is requesting that the system play a ringback tone - * on its behalf. - * @hide + * on its behalf. A ringback tone may be played when an outgoing conference is in the process of + * connecting to give the user an audible indication of that process. */ public final boolean isRingbackRequested() { return mRingbackRequested; @@ -329,7 +329,6 @@ public abstract class Conference extends Conferenceable { /** * Notifies the {@link Conference} of a request to add a new participants to the conference call * @param participants that will be added to this conference call - * @hide */ public void onAddConferenceParticipants(@NonNull List<Uri> participants) {} @@ -340,7 +339,6 @@ public abstract class Conference extends Conferenceable { * the default dialer's {@link InCallService}. * * @param videoState The video state in which to answer the connection. - * @hide */ public void onAnswer(int videoState) {} @@ -360,7 +358,6 @@ public abstract class Conference extends Conferenceable { * a request to reject. * For managed {@link ConnectionService}s, this will be called when the user rejects a call via * the default dialer's {@link InCallService}. - * @hide */ public void onReject() {} @@ -380,7 +377,6 @@ public abstract class Conference extends Conferenceable { /** * Sets state to be ringing. - * @hide */ public final void setRinging() { setState(Connection.STATE_RINGING); @@ -506,7 +502,6 @@ public abstract class Conference extends Conferenceable { * that do not play a ringback tone themselves in the conference's audio stream. * * @param ringback Whether the ringback tone is to be played. - * @hide */ public final void setRingbackRequested(boolean ringback) { if (mRingbackRequested != ringback) { @@ -773,7 +768,6 @@ public abstract class Conference extends Conferenceable { * * @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}). * @return A {@code Conference} which indicates failure. - * @hide */ public @NonNull static Conference createFailedConference( @NonNull DisconnectCause disconnectCause, @NonNull PhoneAccountHandle phoneAccount) { diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 9dfa3ac7a5d8..00b711643fe6 100755 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -383,15 +383,17 @@ public abstract class Connection extends Conferenceable { /** * When set, indicates that this {@link Connection} supports initiation of a conference call - * by directly adding participants using {@link #onAddConferenceParticipants(List)}. - * @hide + * by directly adding participants using {@link #onAddConferenceParticipants(List)}. When + * participants are added to a {@link Connection}, it will be replaced by a {@link Conference} + * instance with {@link #PROPERTY_IS_ADHOC_CONFERENCE} set to indicate that it is an adhoc + * conference call. */ public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000; /** * Indicates that this {@code Connection} can be transferred to another * number. - * Connection supports the blind and assured call transfer feature. + * Connection supports the confirmed and unconfirmed call transfer feature. * @hide */ public static final int CAPABILITY_TRANSFER = 0x08000000; @@ -526,10 +528,9 @@ public abstract class Connection extends Conferenceable { public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11; /** - * Set by the framework to indicate that it is an adhoc conference call. + * Set by the framework to indicate that a call is an adhoc conference call. * <p> - * This is used for Outgoing and incoming conference calls. - * @hide + * This is used for outgoing and incoming conference calls. */ public static final int PROPERTY_IS_ADHOC_CONFERENCE = 1 << 12; @@ -734,6 +735,31 @@ public abstract class Connection extends Conferenceable { "android.telecom.extra.ORIGINAL_CONNECTION_ID"; /** + * Extra key set on a {@link Connection} when it was created via a remote connection service. + * For example, if a connection manager requests a remote connection service to create a call + * using one of the remote connection service's phone account handle, this extra will be set so + * that Telecom knows that the wrapped remote connection originated in a remote connection + * service. We stash this in the extras since connection managers will typically copy the + * extras from a {@link RemoteConnection} to a {@link Connection} (there is ultimately not + * other way to relate a {@link RemoteConnection} to a {@link Connection}. + * @hide + */ + public static final String EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE = + "android.telecom.extra.REMOTE_PHONE_ACCOUNT_HANDLE"; + + /** + * Extra key set from a {@link ConnectionService} when using the remote connection APIs + * (e.g. {@link RemoteConnectionService#createRemoteConnection(PhoneAccountHandle, + * ConnectionRequest, boolean)}) to create a remote connection. Provides the receiving + * {@link ConnectionService} with a means to know the package name of the requesting + * {@link ConnectionService} so that {@link #EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE} can be set for + * better visibility in Telecom of where a connection ultimately originated. + * @hide + */ + public static final String EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME = + "android.telecom.extra.REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME"; + + /** * Boolean connection extra key set on the extras passed to * {@link Connection#sendConnectionEvent} which indicates that audio is present * on the RTT call when the extra value is true. @@ -3009,7 +3035,6 @@ public abstract class Connection extends Conferenceable { * Supports initiation of a conference call by directly adding participants to an ongoing call. * * @param participants with which conference call will be formed. - * @hide */ public void onAddConferenceParticipants(@NonNull List<Uri> participants) {} diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 1b60e4820ad0..315293eb719b 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -1859,11 +1859,28 @@ public abstract class ConnectionService extends Service { new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONFERENCE"), request.getAccountHandle()); } - if (conference.getExtras() != null) { - conference.getExtras().putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId); + + Bundle extras = request.getExtras(); + Bundle newExtras = new Bundle(); + newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId); + if (extras != null) { + // If the request originated from a remote connection service, we will add some + // tracking information that Telecom can use to keep informed of which package + // made the remote request, and which remote connection service was used. + if (extras.containsKey(Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME)) { + newExtras.putString( + Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME, + extras.getString( + Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME)); + newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE, + request.getAccountHandle()); + } } + conference.putExtras(newExtras); + mConferenceById.put(callId, conference); mIdByConference.put(conference, callId); + conference.addListener(mConferenceListener); ParcelableConference parcelableConference = new ParcelableConference.Builder( request.getAccountHandle(), conference.getState()) @@ -1936,6 +1953,30 @@ public abstract class ConnectionService extends Service { Log.i(this, "createConnection, implementation returned null connection."); connection = Connection.createFailedConnection( new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONNECTION")); + } else { + try { + Bundle extras = request.getExtras(); + if (extras != null) { + // If the request originated from a remote connection service, we will add some + // tracking information that Telecom can use to keep informed of which package + // made the remote request, and which remote connection service was used. + if (extras.containsKey( + Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME)) { + Bundle newExtras = new Bundle(); + newExtras.putString( + Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME, + extras.getString( + Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME + )); + newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE, + request.getAccountHandle()); + connection.putExtras(newExtras); + } + } + } catch (UnsupportedOperationException ose) { + // Do nothing; if the ConnectionService reported a failure it will be an instance + // of an immutable Connection which we cannot edit, so we're out of luck. + } } boolean isSelfManaged = @@ -2638,15 +2679,15 @@ public abstract class ConnectionService extends Service { return null; } /** - * Create a {@code Connection} given an incoming request. This is used to attach to existing - * incoming conference call. + * Create a {@code Conference} given an incoming request. This is used to attach to an incoming + * conference call initiated via + * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}. * * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. - * @param request Details about the incoming call. - * @return The {@code Connection} object to satisfy this call, or {@code null} to + * @param request Details about the incoming conference call. + * @return The {@code Conference} object to satisfy this call, or {@code null} to * not handle the call. - * @hide */ public @Nullable Conference onCreateIncomingConference( @Nullable PhoneAccountHandle connectionManagerPhoneAccount, @@ -2731,7 +2772,6 @@ public abstract class ConnectionService extends Service { * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. * @param request The incoming connection request. - * @hide */ public void onCreateIncomingConferenceFailed( @Nullable PhoneAccountHandle connectionManagerPhoneAccount, @@ -2752,7 +2792,6 @@ public abstract class ConnectionService extends Service { * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. * @param request The outgoing connection request. - * @hide */ public void onCreateOutgoingConferenceFailed( @Nullable PhoneAccountHandle connectionManagerPhoneAccount, @@ -2801,7 +2840,8 @@ public abstract class ConnectionService extends Service { /** * Create a {@code Conference} given an outgoing request. This is used to initiate new - * outgoing conference call. + * outgoing conference call requested via + * {@link TelecomManager#startConference(List, Bundle)}. * * @param connectionManagerPhoneAccount The connection manager account to use for managing * this call. @@ -2821,7 +2861,6 @@ public abstract class ConnectionService extends Service { * @param request Details about the outgoing call. * @return The {@code Conference} object to satisfy this call, or the result of an invocation * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call. - * @hide */ public @Nullable Conference onCreateOutgoingConference( @Nullable PhoneAccountHandle connectionManagerPhoneAccount, diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index dd6c15311651..ab35affe9099 100755 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -107,8 +107,8 @@ public final class InCallAdapter { * * @param callId The identifier of the call to transfer. * @param targetNumber The address to transfer to. - * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer, - * if {@code false}, it will initiate BLIND transfer. + * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer, + * if {@code false}, it will initiate unconfirmed transfer. */ public void transferCall(@NonNull String callId, @NonNull Uri targetNumber, boolean isConfirmationRequired) { diff --git a/telecomm/java/android/telecom/Logging/Session.java b/telecomm/java/android/telecom/Logging/Session.java index d82e93fac76d..8d3f4e1df8bc 100644 --- a/telecomm/java/android/telecom/Logging/Session.java +++ b/telecomm/java/android/telecom/Logging/Session.java @@ -427,7 +427,7 @@ public class Session { StringBuilder methodName = new StringBuilder(); methodName.append(getFullMethodPath(false /*truncatePath*/)); if (mOwnerInfo != null && !mOwnerInfo.isEmpty()) { - methodName.append("(InCall package: "); + methodName.append("("); methodName.append(mOwnerInfo); methodName.append(")"); } diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index cad5b707a146..a0833011715d 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -258,6 +258,9 @@ final class RemoteConnectionService { // See comments on Connection.EXTRA_ORIGINAL_CONNECTION_ID for more information. Bundle newExtras = new Bundle(); newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId); + // Track the fact this request was relayed through the remote connection service. + newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE, + parcel.getPhoneAccount()); conference.putExtras(newExtras); conference.registerCallback(new RemoteConference.Callback() { @@ -383,6 +386,11 @@ final class RemoteConnectionService { RemoteConnection remoteConnection = new RemoteConnection(callId, mOutgoingConnectionServiceRpc, connection, callingPackage, callingTargetSdkVersion); + // Track that it is via a remote connection. + Bundle newExtras = new Bundle(); + newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE, + connection.getPhoneAccount()); + remoteConnection.putExtras(newExtras); mConnectionById.put(callId, remoteConnection); remoteConnection.registerCallback(new RemoteConnection.Callback() { @Override @@ -535,10 +543,20 @@ final class RemoteConnectionService { ConnectionRequest request, boolean isIncoming) { final String id = UUID.randomUUID().toString(); + Bundle extras = new Bundle(); + if (request.getExtras() != null) { + extras.putAll(request.getExtras()); + } + // We will set the package name for the originator of the remote request; this lets the + // receiving ConnectionService know that the request originated from a remote connection + // service so that it can provide tracking information for Telecom. + extras.putString(Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME, + mOurConnectionServiceImpl.getApplicationContext().getOpPackageName()); + final ConnectionRequest newRequest = new ConnectionRequest.Builder() .setAccountHandle(request.getAccountHandle()) .setAddress(request.getAddress()) - .setExtras(request.getExtras()) + .setExtras(extras) .setVideoState(request.getVideoState()) .setRttPipeFromInCall(request.getRttPipeFromInCall()) .setRttPipeToInCall(request.getRttPipeToInCall()) diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index b3bf507d701e..08f31a9ea9eb 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1850,11 +1850,13 @@ public class TelecomManager { /** * Registers a new incoming conference. A {@link ConnectionService} should invoke this method - * when it has an incoming conference. For managed {@link ConnectionService}s, the specified - * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and - * the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using - * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have - * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call. + * when it has an incoming conference. An incoming {@link Conference} is an adhoc conference + * call initiated on another device which the user is being invited to join in. For managed + * {@link ConnectionService}s, the specified {@link PhoneAccountHandle} must have been + * registered with {@link #registerPhoneAccount} and the user must have enabled the + * corresponding {@link PhoneAccount}. This can be checked using + * {@link #getPhoneAccount(PhoneAccountHandle)}. Self-managed {@link ConnectionService}s must + * have {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call. * <p> * The incoming conference you are adding is assumed to have a video state of * {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value @@ -1862,8 +1864,9 @@ public class TelecomManager { * <p> * Once invoked, this method will cause the system to bind to the {@link ConnectionService} * associated with the {@link PhoneAccountHandle} and request additional information about the - * call (See {@link ConnectionService#onCreateIncomingConference}) before starting the incoming - * call UI. + * call (See + * {@link ConnectionService#onCreateIncomingConference(PhoneAccountHandle, ConnectionRequest)}) + * before starting the incoming call UI. * <p> * For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either * the {@link PhoneAccountHandle} does not correspond to a registered {@link PhoneAccount} or @@ -1873,7 +1876,6 @@ public class TelecomManager { * {@link #registerPhoneAccount}. * @param extras A bundle that will be passed through to * {@link ConnectionService#onCreateIncomingConference}. - * @hide */ public void addNewIncomingConference(@NonNull PhoneAccountHandle phoneAccount, @NonNull Bundle extras) { @@ -2093,8 +2095,8 @@ public class TelecomManager { /** - * Place a new conference call with the provided participants using the system telecom service - * This method doesn't support placing of emergency calls. + * Place a new adhoc conference call with the provided participants using the system telecom + * service. This method doesn't support placing of emergency calls. * * An adhoc conference call is established by providing a list of addresses to * {@code TelecomManager#startConference(List<Uri>, int videoState)} where the @@ -2112,7 +2114,6 @@ public class TelecomManager { * * @param participants List of participants to start conference with * @param extras Bundle of extras to use with the call - * @hide */ @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull List<Uri> participants, @@ -2201,15 +2202,23 @@ public class TelecomManager { @NonNull public Intent createLaunchEmergencyDialerIntent(@Nullable String number) { ITelecomService service = getTelecomService(); - Intent result = null; if (service != null) { try { - result = service.createLaunchEmergencyDialerIntent(number); + return service.createLaunchEmergencyDialerIntent(number); } catch (RemoteException e) { Log.e(TAG, "Error createLaunchEmergencyDialerIntent", e); } + } else { + Log.w(TAG, "createLaunchEmergencyDialerIntent - Telecom service not available."); } - return result; + + // Telecom service knows the package name of the expected emergency dialer package; if it + // is not available, then fallback to not targeting a specific package. + Intent intent = new Intent(Intent.ACTION_DIAL_EMERGENCY); + if (!TextUtils.isEmpty(number) && TextUtils.isDigitsOnly(number)) { + intent.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)); + } + return intent; } /** diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 0965249cdad3..19cb7f453fe2 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -322,6 +322,8 @@ interface ITelecomService { */ void handleCallIntent(in Intent intent, in String callingPackageProxy); + void cleanupStuckCalls(); + void setTestDefaultCallRedirectionApp(String packageName); void setTestPhoneAcctSuggestionComponent(String flattenedComponentName); diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java index b1dc1da76272..892e55942d3f 100644 --- a/telephony/common/android/telephony/LocationAccessPolicy.java +++ b/telephony/common/android/telephony/LocationAccessPolicy.java @@ -51,7 +51,7 @@ public final class LocationAccessPolicy { ALLOWED, /** * Indicates that the denial is due to a transient device state - * (e.g. app-ops, location master switch) + * (e.g. app-ops, location main switch) */ DENIED_SOFT, /** @@ -259,7 +259,7 @@ public final class LocationAccessPolicy { return LocationPermissionResult.ALLOWED; } - // Check the system-wide requirements. If the location master switch is off or + // Check the system-wide requirements. If the location main switch is off or // the app's profile isn't in foreground, return a soft denial. if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid)) { return LocationPermissionResult.DENIED_SOFT; @@ -283,7 +283,7 @@ public final class LocationAccessPolicy { } // At this point, we're out of location checks to do. If the app bypassed all the previous - // ones due to the SDK grandfathering schemes, allow it access. + // ones due to the SDK backwards compatibility schemes, allow it access. return LocationPermissionResult.ALLOWED; } diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index fff6696604dc..0f53fe65463f 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -75,7 +75,8 @@ public final class TelephonyPermissions { * <li>return false: if the caller lacks all of these permissions and doesn't support runtime * permissions. This implies that the user revoked the ability to read phone state * manually (via AppOps). In this case we can't throw as it would break app compatibility, - * so we return false to indicate that the calling function should return dummy data. + * so we return false to indicate that the calling function should return placeholder + * data. * </ul> * * <p>Note: for simplicity, this method always returns false for callers using legacy @@ -120,7 +121,8 @@ public final class TelephonyPermissions { * <li>return false: if the caller lacks all of these permissions and doesn't support runtime * permissions. This implies that the user revoked the ability to read phone state * manually (via AppOps). In this case we can't throw as it would break app compatibility, - * so we return false to indicate that the calling function should return dummy data. + * so we return false to indicate that the calling function should return placeholder + * data. * </ul> * * <p>Note: for simplicity, this method always returns false for callers using legacy @@ -226,7 +228,7 @@ public final class TelephonyPermissions { * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission. In this case the caller would expect to have access to the device * identifiers so false is returned instead of throwing a SecurityException to indicate - * the calling function should return dummy data. + * the calling function should return placeholder data. * </ul> */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, @@ -250,7 +252,7 @@ public final class TelephonyPermissions { * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission or carrier privileges. In this case the caller would expect to have access * to the device identifiers so false is returned instead of throwing a SecurityException - * to indicate the calling function should return dummy data. + * to indicate the calling function should return placeholder data. * </ul> */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, @@ -272,7 +274,7 @@ public final class TelephonyPermissions { * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission. In this case the caller would expect to have access to the device * identifiers so false is returned instead of throwing a SecurityException to indicate - * the calling function should return dummy data. + * the calling function should return placeholder data. * </ul> */ public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, @@ -296,7 +298,7 @@ public final class TelephonyPermissions { * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission. In this case the caller would expect to have access to the device * identifiers so false is returned instead of throwing a SecurityException to indicate - * the calling function should return dummy data. + * the calling function should return placeholder data. * </ul> */ private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission( @@ -648,7 +650,7 @@ public final class TelephonyPermissions { private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) { SubscriptionManager sm = (SubscriptionManager) context.getSystemService( Context.TELEPHONY_SUBSCRIPTION_SERVICE); - int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false); + int[] activeSubIds = sm.getCompleteActiveSubscriptionIdList(); for (int activeSubId : activeSubIds) { if (getCarrierPrivilegeStatus(context, activeSubId, uid) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { @@ -659,6 +661,10 @@ public final class TelephonyPermissions { } private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) { + if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) { + // Skip the check if it's one of these special uids + return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; + } final long identity = Binder.clearCallingIdentity(); try { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( diff --git a/telephony/common/com/google/android/mms/pdu/PduComposer.java b/telephony/common/com/google/android/mms/pdu/PduComposer.java index 5e1f556f4c4a..7af0d1b09eed 100644 --- a/telephony/common/com/google/android/mms/pdu/PduComposer.java +++ b/telephony/common/com/google/android/mms/pdu/PduComposer.java @@ -1051,7 +1051,7 @@ public class PduComposer { } if (dataLength != (attachment.getLength() - headerLength)) { - throw new RuntimeException("BUG: Length sanity check failed"); + throw new RuntimeException("BUG: Length correctness check failed"); } mStack.pop(); diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java index fcd5b8ff57a8..b61ad3680c6c 100755 --- a/telephony/common/com/google/android/mms/pdu/PduPersister.java +++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java @@ -72,7 +72,7 @@ public class PduPersister { private static final boolean DEBUG = false; private static final boolean LOCAL_LOGV = false; - private static final long DUMMY_THREAD_ID = Long.MAX_VALUE; + private static final long PLACEHOLDER_THREAD_ID = Long.MAX_VALUE; /** * The uri of temporary drm objects. @@ -1340,7 +1340,7 @@ public class PduPersister { // Save parts first to avoid inconsistent message is loaded // while saving the parts. - long dummyId = System.currentTimeMillis(); // Dummy ID of the msg. + long placeholderId = System.currentTimeMillis(); // Placeholder ID of the msg. // Figure out if this PDU is a text-only message boolean textOnly = true; @@ -1364,7 +1364,7 @@ public class PduPersister { for (int i = 0; i < partsNum; i++) { PduPart part = body.getPart(i); messageSize += part.getDataLength(); - persistPart(part, dummyId, preOpenedFiles); + persistPart(part, placeholderId, preOpenedFiles); // If we've got anything besides text/plain or SMIL part, then we've got // an mms message with some other type of attachment. @@ -1395,14 +1395,14 @@ public class PduPersister { throw new MmsException("persist() failed: return null."); } // Get the real ID of the PDU and update all parts which were - // saved with the dummy ID. + // saved with the placeholder ID. msgId = ContentUris.parseId(res); } values = new ContentValues(1); values.put(Part.MSG_ID, msgId); SqliteWrapper.update(mContext, mContentResolver, - Uri.parse("content://mms/" + dummyId + "/part"), + Uri.parse("content://mms/" + placeholderId + "/part"), values, null, null); // We should return the longest URI of the persisted PDU, for // example, if input URI is "content://mms/inbox" and the _ID of diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index b75f9a15f66f..0f7344009db1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -773,7 +773,7 @@ public class CarrierConfigManager { * {@link #KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL}). If false, this device will fallback to * circuit switch for supplementary services and will disable this capability for IMS entirely. * - * The default value for this key is {@code true}. + * The default value for this key is {@code false}. */ public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool"; @@ -1086,6 +1086,15 @@ public class CarrierConfigManager { "show_signal_strength_in_sim_status_bool"; /** + * Flag specifying if we should interpret all signal strength as one bar higher + * This is a replacement for the former resource config_inflateSignalStrength + * The default value is false. + * @hide + */ + public static final String KEY_INFLATE_SIGNAL_STRENGTH_BOOL = + "inflate_signal_strength_bool"; + + /** * Flag specifying whether an additional (client initiated) intent needs to be sent on System * update */ @@ -1157,15 +1166,14 @@ public class CarrierConfigManager { /** * Determines whether adhoc conference calls are supported by a carrier. When {@code true}, * adhoc conference calling is supported, {@code false otherwise}. - * @hide */ public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool"; /** - * Determines whether conference participants can be added to existing call. When {@code true}, + * Determines whether conference participants can be added to existing call to form an adhoc + * conference call (in contrast to merging calls to form a conference). When {@code true}, * adding conference participants to existing call is supported, {@code false otherwise}. - * @hide */ public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool"; @@ -3163,6 +3171,17 @@ public class CarrierConfigManager { "5g_icon_display_secondary_grace_period_string"; /** + * Whether device reset all of NR timers when device camped on a network that haven't 5G + * capability and RRC currently in IDLE state. + * + * The default value is false; + * + * @hide + */ + public static final String KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL = + "nr_timers_reset_if_non_endc_and_rrc_idle_bool"; + + /** * Controls time in milliseconds until DcTracker reevaluates 5G connection state. * @hide */ @@ -3777,6 +3796,15 @@ public class CarrierConfigManager { public static final String KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY = "missed_incoming_call_sms_pattern_string_array"; + /** + * Indicating whether DUN APN should be disabled when the device is roaming. In that case, + * the default APN (i.e. internet) will be used for tethering. + * + * @hide + */ + public static final String KEY_DISABLE_DUN_APN_WHILE_ROAMING = + "disable_dun_apn_while_roaming"; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -3895,6 +3923,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY, null); sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false); sDefaults.putBoolean(KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, true); + sDefaults.putBoolean(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false); sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false); sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, ""); sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, ""); @@ -4230,6 +4259,7 @@ public class CarrierConfigManager { + "not_restricted_rrc_con:5G"); sDefaults.putString(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING, ""); sDefaults.putString(KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING, ""); + sDefaults.putBoolean(KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL, false); /* Default value is 1 hour. */ sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000); sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false); @@ -4304,6 +4334,7 @@ public class CarrierConfigManager { "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]); + sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING, false); } /** diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java index 61f68ce32287..427721f40e47 100644 --- a/telephony/java/android/telephony/CellLocation.java +++ b/telephony/java/android/telephony/CellLocation.java @@ -34,10 +34,12 @@ import com.android.internal.telephony.PhoneConstants; public abstract class CellLocation { /** - * This method will not do anything. + * Request an updated CellLocation for callers targeting SDK 30 or older. * - * Whenever location changes, a callback will automatically be be sent to - * all registrants of {@link PhoneStateListener#LISTEN_CELL_LOCATION}. + * Whenever Android is aware of location changes, a callback will automatically be sent to + * all registrants of {@link PhoneStateListener#LISTEN_CELL_LOCATION}. This API requests an + * additional location update for cases where power saving might cause location updates to be + * missed. * * <p>This method is a no-op for callers targeting SDK level 31 or greater. * <p>This method is a no-op for callers that target SDK level 29 or 30 and lack @@ -45,14 +47,7 @@ public abstract class CellLocation { * <p>This method is a no-op for callers that target SDK level 28 or below and lack * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. * - * Callers wishing to request a single location update should use - * {@link TelephonyManager#requestCellInfoUpdate}. - * - * @deprecated this method has undesirable side-effects, and it calls into the OS without - * access to a {@link android.content.Context Context}, meaning that certain safety checks and - * attribution are error-prone. Given that this method has numerous downsides, and given that - * there are long-available superior alternatives, callers are strongly discouraged from using - * this method. + * @deprecated use {@link TelephonyManager#requestCellInfoUpdate}. */ @Deprecated public static void requestLocationUpdate() { diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index 8e50bba38e84..766019ec382a 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -149,7 +149,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3); mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23); mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44); - mSsRsrq = inRangeOrUnavailable(ssRsrq, -20, -3); + mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20); mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40); updateLevel(null, null); } diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index 3f671ca2d809..18d6f467ba7b 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -509,7 +509,7 @@ public class MbmsDownloadSession implements AutoCloseable { * provided directory is the same as what has been previously configured. * * The {@link File} supplied as a root temp file directory must already exist. If not, an - * {@link IllegalArgumentException} will be thrown. In addition, as an additional sanity + * {@link IllegalArgumentException} will be thrown. In addition, as an additional correctness * check, an {@link IllegalArgumentException} will be thrown if you attempt to set the temp * file root directory to one of your data roots (the value of {@link Context#getDataDir()}, * {@link Context#getFilesDir()}, or {@link Context#getCacheDir()}). diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 68753e11d395..aee1e84ca356 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -594,7 +594,8 @@ public final class NetworkRegistrationInfo implements Parcelable { return "Unknown reg state " + registrationState; } - private static String nrStateToString(@NRState int nrState) { + /** @hide */ + public static String nrStateToString(@NRState int nrState) { switch (nrState) { case NR_STATE_RESTRICTED: return "RESTRICTED"; diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index 4273f5a4a16e..af62ba4b93a1 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -19,8 +19,8 @@ package android.telephony; import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; - import android.telephony.Annotation.NetworkType; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; @@ -241,13 +241,13 @@ public final class PhysicalChannelConfig implements Parcelable { .append(",mCellBandwidthDownlinkKhz=") .append(mCellBandwidthDownlinkKhz) .append(",mRat=") - .append(mRat) + .append(TelephonyManager.getNetworkTypeName(mRat)) .append(",mFrequencyRange=") - .append(mFrequencyRange) + .append(ServiceState.frequencyRangeToString(mFrequencyRange)) .append(",mChannelNumber=") .append(mChannelNumber) .append(",mContextIds=") - .append(mContextIds.toString()) + .append(Arrays.toString(mContextIds)) .append(",mPhysicalCellId=") .append(mPhysicalCellId) .append("}") diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 243b24b667c7..c831ae9d6a04 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1033,6 +1033,26 @@ public class ServiceState implements Parcelable { } /** + * Convert frequency range into string + * + * @param range The cellular frequency range + * @return Frequency range in string format + * + * @hide + */ + public static @NonNull String frequencyRangeToString(@FrequencyRange int range) { + switch (range) { + case FREQUENCY_RANGE_UNKNOWN: return "UNKNOWN"; + case FREQUENCY_RANGE_LOW: return "LOW"; + case FREQUENCY_RANGE_MID: return "MID"; + case FREQUENCY_RANGE_HIGH: return "HIGH"; + case FREQUENCY_RANGE_MMWAVE: return "MMWAVE"; + default: + return Integer.toString(range); + } + } + + /** * Convert RIL Service State to String * * @param serviceState diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index abcc82bcdfe7..1dbec2c0f443 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -1656,8 +1656,7 @@ public final class SmsManager { * operation is performed on the correct subscription. * </p> * - * @param messageIndex This is the same index used to access a message - * from {@link #getMessagesFromIcc()}. + * @param messageIndex the message index of the message in the ICC (1-based index). * @return true for success, false if the operation fails. Failure can be due to IPC failure, * RIL/modem error which results in SMS failed to be deleted on SIM * @@ -1740,7 +1739,7 @@ public final class SmsManager { * operation is performed on the correct subscription. * </p> * - * @return <code>List</code> of <code>SmsMessage</code> objects + * @return <code>List</code> of <code>SmsMessage</code> objects for valid records only. * * {@hide} */ diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 7f2c6c17d508..bcde7160c1c5 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -95,10 +95,9 @@ public class SubscriptionManager { /** An invalid subscription identifier */ public static final int INVALID_SUBSCRIPTION_ID = -1; - /** Base value for Dummy SUBSCRIPTION_ID's. */ - /** FIXME: Remove DummySubId's, but for now have them map just below INVALID_SUBSCRIPTION_ID - /** @hide */ - public static final int DUMMY_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1; + /** Base value for placeholder SUBSCRIPTION_ID's. */ + /** @hide */ + public static final int PLACEHOLDER_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1; /** An invalid phone identifier */ /** @hide */ @@ -2183,6 +2182,7 @@ public class SubscriptionManager { * @hide */ @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @NonNull int[] getActiveSubscriptionIdList() { return getActiveSubscriptionIdList(/* visibleOnly */ true); } @@ -2200,7 +2200,8 @@ public class SubscriptionManager { * @hide */ @SystemApi - public @NonNull int[] getActiveAndHiddenSubscriptionIdList() { + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public @NonNull int[] getCompleteActiveSubscriptionIdList() { return getActiveSubscriptionIdList(/* visibleOnly */false); } diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java index e8f3f1ebb6cf..eadb726bf63b 100644 --- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java +++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java @@ -92,8 +92,8 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable { } /** - * Sets the originating number whitelist for the visual voicemail SMS filter. If the list is - * not null only the SMS messages from a number in the list can be considered as a visual + * Sets the originating number allow list for the visual voicemail SMS filter. If the list + * is not null only the SMS messages from a number in the list can be considered as a visual * voicemail SMS. Otherwise, messages from any address will be considered. */ public Builder setOriginatingNumbers(List<String> originatingNumbers) { @@ -133,7 +133,7 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable { public final String clientPrefix; /** - * The originating number whitelist for the visual voicemail SMS filter of a phone account. If + * The originating number allow list for the visual voicemail SMS filter of a phone account. If * the list is not null only the SMS messages from a number in the list can be considered as a * visual voicemail SMS. Otherwise, messages from any address will be considered. */ diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index 158ada94e3c6..d44d29f3aefb 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -1640,7 +1640,7 @@ public class ApnSetting implements Parcelable { * * <pre><code> * // Create an MMS proxy address with a hostname. A network might not be - * // available, so supply a dummy (0.0.0.0) IPv4 address to avoid DNS lookup. + * // available, so supply a placeholder (0.0.0.0) IPv4 address to avoid DNS lookup. * String host = "mms.example.com"; * byte[] ipAddress = new byte[4]; * InetAddress mmsProxy; @@ -1825,7 +1825,8 @@ public class ApnSetting implements Parcelable { * {@link java.net.InetAddress#getAllByName getAllByName()} require DNS for hostname * resolution. To avoid this requirement when setting a hostname, call * {@link java.net.InetAddress#getByAddress(java.lang.String, byte[])} with both the - * hostname and a dummy IP address. See {@link ApnSetting.Builder above} for an example. + * hostname and a placeholder IP address. See {@link ApnSetting.Builder above} for an + * example. * * @param proxy the proxy address to set for the APN * @deprecated use {@link #setProxyAddress(String)} instead. @@ -1879,7 +1880,8 @@ public class ApnSetting implements Parcelable { * {@link java.net.InetAddress#getAllByName getAllByName()} require DNS for hostname * resolution. To avoid this requirement when setting a hostname, call * {@link java.net.InetAddress#getByAddress(java.lang.String, byte[])} with both the - * hostname and a dummy IP address. See {@link ApnSetting.Builder above} for an example. + * hostname and a placeholder IP address. See {@link ApnSetting.Builder above} for an + * example. * * @param mmsProxy the MMS proxy address to set for the APN * @deprecated use {@link #setMmsProxyAddress(String)} instead. diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java index 80c38cbfc39a..8857b9b36d0c 100755 --- a/telephony/java/android/telephony/ims/ImsCallSession.java +++ b/telephony/java/android/telephony/ims/ImsCallSession.java @@ -815,7 +815,7 @@ public class ImsCallSession { * Transfers an ongoing call. * * @param number number to be transferred to. - * @param isConfirmationRequired indicates blind or assured transfer. + * @param isConfirmationRequired indicates whether confirmation of the transfer is required. */ public void transfer(@NonNull String number, boolean isConfirmationRequired) { if (mClosed) { diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java index 0d6b31d349e1..30389a290368 100644 --- a/telephony/java/android/telephony/ims/ImsReasonInfo.java +++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java @@ -27,7 +27,8 @@ import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; - +import java.util.HashMap; +import java.util.Map; /** * Provides details on why an IMS call failed. Applications can use the methods in this class to * get local or network fault behind an IMS services failure. For example, if the code is @@ -1095,6 +1096,196 @@ public final class ImsReasonInfo implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface ImsCode {} + + private static final Map<Integer, String> sImsCodeMap; + static { + sImsCodeMap = new HashMap<>(); + sImsCodeMap.put(CODE_UNSPECIFIED, "CODE_UNSPECIFIED"); + sImsCodeMap.put(CODE_LOCAL_ILLEGAL_ARGUMENT, "CODE_LOCAL_ILLEGAL_ARGUMENT"); + sImsCodeMap.put(CODE_LOCAL_ILLEGAL_STATE, "CODE_LOCAL_ILLEGAL_STATE"); + sImsCodeMap.put(CODE_LOCAL_INTERNAL_ERROR, "CODE_LOCAL_INTERNAL_ERROR"); + sImsCodeMap.put(CODE_LOCAL_IMS_SERVICE_DOWN, "CODE_LOCAL_IMS_SERVICE_DOWN"); + sImsCodeMap.put(CODE_LOCAL_NO_PENDING_CALL, "CODE_LOCAL_NO_PENDING_CALL"); + sImsCodeMap.put(CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE, + "CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE"); + sImsCodeMap.put(CODE_LOCAL_POWER_OFF, "CODE_LOCAL_POWER_OFF"); + sImsCodeMap.put(CODE_LOCAL_LOW_BATTERY, "CODE_LOCAL_LOW_BATTERY"); + sImsCodeMap.put(CODE_LOCAL_NETWORK_NO_SERVICE, "CODE_LOCAL_NETWORK_NO_SERVICE"); + sImsCodeMap.put(CODE_LOCAL_NETWORK_NO_LTE_COVERAGE, "CODE_LOCAL_NETWORK_NO_LTE_COVERAGE"); + sImsCodeMap.put(CODE_LOCAL_NETWORK_ROAMING, "CODE_LOCAL_NETWORK_ROAMING"); + sImsCodeMap.put(CODE_LOCAL_NETWORK_IP_CHANGED, "CODE_LOCAL_NETWORK_IP_CHANGED"); + sImsCodeMap.put(CODE_LOCAL_SERVICE_UNAVAILABLE, "CODE_LOCAL_SERVICE_UNAVAILABLE"); + sImsCodeMap.put(CODE_LOCAL_NOT_REGISTERED, "CODE_LOCAL_NOT_REGISTERED"); + sImsCodeMap.put(CODE_LOCAL_CALL_EXCEEDED, "CODE_LOCAL_CALL_EXCEEDED"); + sImsCodeMap.put(CODE_LOCAL_CALL_BUSY, "CODE_LOCAL_CALL_BUSY"); + sImsCodeMap.put(CODE_LOCAL_CALL_DECLINE, "CODE_LOCAL_CALL_DECLINE"); + sImsCodeMap.put(CODE_LOCAL_CALL_VCC_ON_PROGRESSING, "CODE_LOCAL_CALL_VCC_ON_PROGRESSING"); + sImsCodeMap.put(CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED, + "CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED"); + sImsCodeMap.put(CODE_LOCAL_CALL_CS_RETRY_REQUIRED, "CODE_LOCAL_CALL_CS_RETRY_REQUIRED"); + sImsCodeMap.put(CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED, + "CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED"); + sImsCodeMap.put(CODE_LOCAL_CALL_TERMINATED, "CODE_LOCAL_CALL_TERMINATED"); + sImsCodeMap.put(CODE_LOCAL_HO_NOT_FEASIBLE, "CODE_LOCAL_HO_NOT_FEASIBLE"); + sImsCodeMap.put(CODE_TIMEOUT_1XX_WAITING, "CODE_TIMEOUT_1XX_WAITING"); + sImsCodeMap.put(CODE_TIMEOUT_NO_ANSWER, "CODE_TIMEOUT_NO_ANSWER"); + sImsCodeMap.put(CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE, "CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE"); + sImsCodeMap.put(CODE_CALL_BARRED, "CODE_CALL_BARRED"); + sImsCodeMap.put(CODE_FDN_BLOCKED, "CODE_FDN_BLOCKED"); + sImsCodeMap.put(CODE_IMEI_NOT_ACCEPTED, "CODE_IMEI_NOT_ACCEPTED"); + sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_USSD, "CODE_DIAL_MODIFIED_TO_USSD"); + sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_SS, "CODE_DIAL_MODIFIED_TO_SS"); + sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_DIAL, "CODE_DIAL_MODIFIED_TO_DIAL"); + sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_DIAL_VIDEO, "CODE_DIAL_MODIFIED_TO_DIAL_VIDEO"); + sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_DIAL, "CODE_DIAL_VIDEO_MODIFIED_TO_DIAL"); + sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO, + "CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO"); + sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_SS, "CODE_DIAL_VIDEO_MODIFIED_TO_SS"); + sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_USSD, "CODE_DIAL_VIDEO_MODIFIED_TO_USSD"); + sImsCodeMap.put(CODE_SIP_REDIRECTED, "CODE_SIP_REDIRECTED"); + sImsCodeMap.put(CODE_SIP_BAD_REQUEST, "CODE_SIP_BAD_REQUEST"); + sImsCodeMap.put(CODE_SIP_FORBIDDEN, "CODE_SIP_FORBIDDEN"); + sImsCodeMap.put(CODE_SIP_NOT_FOUND, "CODE_SIP_NOT_FOUND"); + sImsCodeMap.put(CODE_SIP_NOT_SUPPORTED, "CODE_SIP_NOT_SUPPORTED"); + sImsCodeMap.put(CODE_SIP_REQUEST_TIMEOUT, "CODE_SIP_REQUEST_TIMEOUT"); + sImsCodeMap.put(CODE_SIP_TEMPRARILY_UNAVAILABLE, "CODE_SIP_TEMPRARILY_UNAVAILABLE"); + sImsCodeMap.put(CODE_SIP_BAD_ADDRESS, "CODE_SIP_BAD_ADDRESS"); + sImsCodeMap.put(CODE_SIP_BUSY, "CODE_SIP_BUSY"); + sImsCodeMap.put(CODE_SIP_REQUEST_CANCELLED, "CODE_SIP_REQUEST_CANCELLED"); + sImsCodeMap.put(CODE_SIP_NOT_ACCEPTABLE, "CODE_SIP_NOT_ACCEPTABLE"); + sImsCodeMap.put(CODE_SIP_NOT_REACHABLE, "CODE_SIP_NOT_REACHABLE"); + sImsCodeMap.put(CODE_SIP_CLIENT_ERROR, "CODE_SIP_CLIENT_ERROR"); + sImsCodeMap.put(CODE_SIP_TRANSACTION_DOES_NOT_EXIST, "CODE_SIP_TRANSACTION_DOES_NOT_EXIST"); + sImsCodeMap.put(CODE_SIP_SERVER_INTERNAL_ERROR, "CODE_SIP_SERVER_INTERNAL_ERROR"); + sImsCodeMap.put(CODE_SIP_SERVICE_UNAVAILABLE, "CODE_SIP_SERVICE_UNAVAILABLE"); + sImsCodeMap.put(CODE_SIP_SERVER_TIMEOUT, "CODE_SIP_SERVER_TIMEOUT"); + sImsCodeMap.put(CODE_SIP_SERVER_ERROR, "CODE_SIP_SERVER_ERROR"); + sImsCodeMap.put(CODE_SIP_USER_REJECTED, "CODE_SIP_USER_REJECTED"); + sImsCodeMap.put(CODE_SIP_GLOBAL_ERROR, "CODE_SIP_GLOBAL_ERROR"); + sImsCodeMap.put(CODE_EMERGENCY_TEMP_FAILURE, "CODE_EMERGENCY_TEMP_FAILURE"); + sImsCodeMap.put(CODE_EMERGENCY_PERM_FAILURE, "CODE_EMERGENCY_PERM_FAILURE"); + sImsCodeMap.put(CODE_SIP_USER_MARKED_UNWANTED, "CODE_SIP_USER_MARKED_UNWANTED"); + sImsCodeMap.put(CODE_SIP_METHOD_NOT_ALLOWED, "CODE_SIP_METHOD_NOT_ALLOWED"); + sImsCodeMap.put(CODE_SIP_PROXY_AUTHENTICATION_REQUIRED, + "CODE_SIP_PROXY_AUTHENTICATION_REQUIRED"); + sImsCodeMap.put(CODE_SIP_REQUEST_ENTITY_TOO_LARGE, "CODE_SIP_REQUEST_ENTITY_TOO_LARGE"); + sImsCodeMap.put(CODE_SIP_REQUEST_URI_TOO_LARGE, "CODE_SIP_REQUEST_URI_TOO_LARGE"); + sImsCodeMap.put(CODE_SIP_EXTENSION_REQUIRED, "CODE_SIP_EXTENSION_REQUIRED"); + sImsCodeMap.put(CODE_SIP_INTERVAL_TOO_BRIEF, "CODE_SIP_INTERVAL_TOO_BRIEF"); + sImsCodeMap.put(CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST, + "CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST"); + sImsCodeMap.put(CODE_SIP_LOOP_DETECTED, "CODE_SIP_LOOP_DETECTED"); + sImsCodeMap.put(CODE_SIP_TOO_MANY_HOPS, "CODE_SIP_TOO_MANY_HOPS"); + sImsCodeMap.put(CODE_SIP_AMBIGUOUS, "CODE_SIP_AMBIGUOUS"); + sImsCodeMap.put(CODE_SIP_REQUEST_PENDING, "CODE_SIP_REQUEST_PENDING"); + sImsCodeMap.put(CODE_SIP_UNDECIPHERABLE, "CODE_SIP_UNDECIPHERABLE"); + sImsCodeMap.put(CODE_MEDIA_INIT_FAILED, "CODE_MEDIA_INIT_FAILED"); + sImsCodeMap.put(CODE_MEDIA_NO_DATA, "CODE_MEDIA_NO_DATA"); + sImsCodeMap.put(CODE_MEDIA_NOT_ACCEPTABLE, "CODE_MEDIA_NOT_ACCEPTABLE"); + sImsCodeMap.put(CODE_MEDIA_UNSPECIFIED, "CODE_MEDIA_UNSPECIFIED"); + sImsCodeMap.put(CODE_USER_TERMINATED, "CODE_USER_TERMINATED"); + sImsCodeMap.put(CODE_USER_NOANSWER, "CODE_USER_NOANSWER"); + sImsCodeMap.put(CODE_USER_IGNORE, "CODE_USER_IGNORE"); + sImsCodeMap.put(CODE_USER_DECLINE, "CODE_USER_DECLINE"); + sImsCodeMap.put(CODE_LOW_BATTERY, "CODE_LOW_BATTERY"); + sImsCodeMap.put(CODE_BLACKLISTED_CALL_ID, "CODE_BLACKLISTED_CALL_ID"); + sImsCodeMap.put(CODE_USER_TERMINATED_BY_REMOTE, "CODE_USER_TERMINATED_BY_REMOTE"); + sImsCodeMap.put(CODE_USER_REJECTED_SESSION_MODIFICATION, + "CODE_USER_REJECTED_SESSION_MODIFICATION"); + sImsCodeMap.put(CODE_USER_CANCELLED_SESSION_MODIFICATION, + "CODE_USER_CANCELLED_SESSION_MODIFICATION"); + sImsCodeMap.put(CODE_SESSION_MODIFICATION_FAILED, "CODE_SESSION_MODIFICATION_FAILED"); + sImsCodeMap.put(CODE_UT_NOT_SUPPORTED, "CODE_UT_NOT_SUPPORTED"); + sImsCodeMap.put(CODE_UT_SERVICE_UNAVAILABLE, "CODE_UT_SERVICE_UNAVAILABLE"); + sImsCodeMap.put(CODE_UT_OPERATION_NOT_ALLOWED, "CODE_UT_OPERATION_NOT_ALLOWED"); + sImsCodeMap.put(CODE_UT_NETWORK_ERROR, "CODE_UT_NETWORK_ERROR"); + sImsCodeMap.put(CODE_UT_CB_PASSWORD_MISMATCH, "CODE_UT_CB_PASSWORD_MISMATCH"); + sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_DIAL, "CODE_UT_SS_MODIFIED_TO_DIAL"); + sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_USSD, "CODE_UT_SS_MODIFIED_TO_USSD"); + sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_SS, "CODE_UT_SS_MODIFIED_TO_SS"); + sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO, "CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO"); + sImsCodeMap.put(CODE_ECBM_NOT_SUPPORTED, "CODE_ECBM_NOT_SUPPORTED"); + sImsCodeMap.put(CODE_MULTIENDPOINT_NOT_SUPPORTED, "CODE_MULTIENDPOINT_NOT_SUPPORTED"); + sImsCodeMap.put(CODE_REGISTRATION_ERROR, "CODE_REGISTRATION_ERROR"); + sImsCodeMap.put(CODE_ANSWERED_ELSEWHERE, "CODE_ANSWERED_ELSEWHERE"); + sImsCodeMap.put(CODE_CALL_PULL_OUT_OF_SYNC, "CODE_CALL_PULL_OUT_OF_SYNC"); + sImsCodeMap.put(CODE_CALL_END_CAUSE_CALL_PULL, "CODE_CALL_END_CAUSE_CALL_PULL"); + sImsCodeMap.put(CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE, + "CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE"); + sImsCodeMap.put(CODE_REJECTED_ELSEWHERE, "CODE_REJECTED_ELSEWHERE"); + sImsCodeMap.put(CODE_SUPP_SVC_FAILED, "CODE_SUPP_SVC_FAILED"); + sImsCodeMap.put(CODE_SUPP_SVC_CANCELLED, "CODE_SUPP_SVC_CANCELLED"); + sImsCodeMap.put(CODE_SUPP_SVC_REINVITE_COLLISION, "CODE_SUPP_SVC_REINVITE_COLLISION"); + sImsCodeMap.put(CODE_IWLAN_DPD_FAILURE, "CODE_IWLAN_DPD_FAILURE"); + sImsCodeMap.put(CODE_EPDG_TUNNEL_ESTABLISH_FAILURE, "CODE_EPDG_TUNNEL_ESTABLISH_FAILURE"); + sImsCodeMap.put(CODE_EPDG_TUNNEL_REKEY_FAILURE, "CODE_EPDG_TUNNEL_REKEY_FAILURE"); + sImsCodeMap.put(CODE_EPDG_TUNNEL_LOST_CONNECTION, "CODE_EPDG_TUNNEL_LOST_CONNECTION"); + sImsCodeMap.put(CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED, + "CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED"); + sImsCodeMap.put(CODE_REMOTE_CALL_DECLINE, "CODE_REMOTE_CALL_DECLINE"); + sImsCodeMap.put(CODE_DATA_LIMIT_REACHED, "CODE_DATA_LIMIT_REACHED"); + sImsCodeMap.put(CODE_DATA_DISABLED, "CODE_DATA_DISABLED"); + sImsCodeMap.put(CODE_WIFI_LOST, "CODE_WIFI_LOST"); + sImsCodeMap.put(CODE_IKEV2_AUTH_FAILURE, "CODE_IKEV2_AUTH_FAILURE"); + sImsCodeMap.put(CODE_RADIO_OFF, "CODE_RADIO_OFF"); + sImsCodeMap.put(CODE_NO_VALID_SIM, "CODE_NO_VALID_SIM"); + sImsCodeMap.put(CODE_RADIO_INTERNAL_ERROR, "CODE_RADIO_INTERNAL_ERROR"); + sImsCodeMap.put(CODE_NETWORK_RESP_TIMEOUT, "CODE_NETWORK_RESP_TIMEOUT"); + sImsCodeMap.put(CODE_NETWORK_REJECT, "CODE_NETWORK_REJECT"); + sImsCodeMap.put(CODE_RADIO_ACCESS_FAILURE, "CODE_RADIO_ACCESS_FAILURE"); + sImsCodeMap.put(CODE_RADIO_LINK_FAILURE, "CODE_RADIO_LINK_FAILURE"); + sImsCodeMap.put(CODE_RADIO_LINK_LOST, "CODE_RADIO_LINK_LOST"); + sImsCodeMap.put(CODE_RADIO_UPLINK_FAILURE, "CODE_RADIO_UPLINK_FAILURE"); + sImsCodeMap.put(CODE_RADIO_SETUP_FAILURE, "CODE_RADIO_SETUP_FAILURE"); + sImsCodeMap.put(CODE_RADIO_RELEASE_NORMAL, "CODE_RADIO_RELEASE_NORMAL"); + sImsCodeMap.put(CODE_RADIO_RELEASE_ABNORMAL, "CODE_RADIO_RELEASE_ABNORMAL"); + sImsCodeMap.put(CODE_ACCESS_CLASS_BLOCKED, "CODE_ACCESS_CLASS_BLOCKED"); + sImsCodeMap.put(CODE_NETWORK_DETACH, "CODE_NETWORK_DETACH"); + sImsCodeMap.put(CODE_SIP_ALTERNATE_EMERGENCY_CALL, "CODE_SIP_ALTERNATE_EMERGENCY_CALL"); + sImsCodeMap.put(CODE_UNOBTAINABLE_NUMBER, "CODE_UNOBTAINABLE_NUMBER"); + sImsCodeMap.put(CODE_NO_CSFB_IN_CS_ROAM, "CODE_NO_CSFB_IN_CS_ROAM"); + sImsCodeMap.put(CODE_REJECT_UNKNOWN, "CODE_REJECT_UNKNOWN"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_WAITING_DISABLED, + "CODE_REJECT_ONGOING_CALL_WAITING_DISABLED"); + sImsCodeMap.put(CODE_REJECT_CALL_ON_OTHER_SUB, "CODE_REJECT_CALL_ON_OTHER_SUB"); + sImsCodeMap.put(CODE_REJECT_1X_COLLISION, "CODE_REJECT_1X_COLLISION"); + sImsCodeMap.put(CODE_REJECT_SERVICE_NOT_REGISTERED, "CODE_REJECT_SERVICE_NOT_REGISTERED"); + sImsCodeMap.put(CODE_REJECT_CALL_TYPE_NOT_ALLOWED, "CODE_REJECT_CALL_TYPE_NOT_ALLOWED"); + sImsCodeMap.put(CODE_REJECT_ONGOING_E911_CALL, "CODE_REJECT_ONGOING_E911_CALL"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_SETUP, "CODE_REJECT_ONGOING_CALL_SETUP"); + sImsCodeMap.put(CODE_REJECT_MAX_CALL_LIMIT_REACHED, "CODE_REJECT_MAX_CALL_LIMIT_REACHED"); + sImsCodeMap.put(CODE_REJECT_UNSUPPORTED_SIP_HEADERS, "CODE_REJECT_UNSUPPORTED_SIP_HEADERS"); + sImsCodeMap.put(CODE_REJECT_UNSUPPORTED_SDP_HEADERS, "CODE_REJECT_UNSUPPORTED_SDP_HEADERS"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_TRANSFER, "CODE_REJECT_ONGOING_CALL_TRANSFER"); + sImsCodeMap.put(CODE_REJECT_INTERNAL_ERROR, "CODE_REJECT_INTERNAL_ERROR"); + sImsCodeMap.put(CODE_REJECT_QOS_FAILURE, "CODE_REJECT_QOS_FAILURE"); + sImsCodeMap.put(CODE_REJECT_ONGOING_HANDOVER, "CODE_REJECT_ONGOING_HANDOVER"); + sImsCodeMap.put(CODE_REJECT_VT_TTY_NOT_ALLOWED, "CODE_REJECT_VT_TTY_NOT_ALLOWED"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_UPGRADE, "CODE_REJECT_ONGOING_CALL_UPGRADE"); + sImsCodeMap.put(CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED, + "CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CONFERENCE_CALL, "CODE_REJECT_ONGOING_CONFERENCE_CALL"); + sImsCodeMap.put(CODE_REJECT_VT_AVPF_NOT_ALLOWED, "CODE_REJECT_VT_AVPF_NOT_ALLOWED"); + sImsCodeMap.put(CODE_REJECT_ONGOING_ENCRYPTED_CALL, "CODE_REJECT_ONGOING_ENCRYPTED_CALL"); + sImsCodeMap.put(CODE_REJECT_ONGOING_CS_CALL, "CODE_REJECT_ONGOING_CS_CALL"); + sImsCodeMap.put(CODE_RETRY_ON_IMS_WITHOUT_RTT, "CODE_RETRY_ON_IMS_WITHOUT_RTT"); + sImsCodeMap.put(CODE_OEM_CAUSE_1, "CODE_OEM_CAUSE_1"); + sImsCodeMap.put(CODE_OEM_CAUSE_2, "CODE_OEM_CAUSE_2"); + sImsCodeMap.put(CODE_OEM_CAUSE_3, "CODE_OEM_CAUSE_3"); + sImsCodeMap.put(CODE_OEM_CAUSE_4, "CODE_OEM_CAUSE_4"); + sImsCodeMap.put(CODE_OEM_CAUSE_5, "CODE_OEM_CAUSE_5"); + sImsCodeMap.put(CODE_OEM_CAUSE_6, "CODE_OEM_CAUSE_6"); + sImsCodeMap.put(CODE_OEM_CAUSE_7, "CODE_OEM_CAUSE_7"); + sImsCodeMap.put(CODE_OEM_CAUSE_8, "CODE_OEM_CAUSE_8"); + sImsCodeMap.put(CODE_OEM_CAUSE_9, "CODE_OEM_CAUSE_9"); + sImsCodeMap.put(CODE_OEM_CAUSE_10, "CODE_OEM_CAUSE_10"); + sImsCodeMap.put(CODE_OEM_CAUSE_11, "CODE_OEM_CAUSE_11"); + sImsCodeMap.put(CODE_OEM_CAUSE_12, "CODE_OEM_CAUSE_12"); + sImsCodeMap.put(CODE_OEM_CAUSE_13, "CODE_OEM_CAUSE_13"); + sImsCodeMap.put(CODE_OEM_CAUSE_14, "CODE_OEM_CAUSE_14"); + sImsCodeMap.put(CODE_OEM_CAUSE_15, "CODE_OEM_CAUSE_15"); + } + /** * Network string error messages. * mExtraMessage may have these values. @@ -1203,7 +1394,9 @@ public final class ImsReasonInfo implements Parcelable { @NonNull @Override public String toString() { - return "ImsReasonInfo :: {" + mCode + ", " + mExtraCode + ", " + mExtraMessage + "}"; + String imsCode = (sImsCodeMap.containsKey(mCode)) ? sImsCodeMap.get(mCode) : "UNKNOWN_CODE"; + return "ImsReasonInfo :: {" + mCode + " : " + imsCode + ", " + + mExtraCode + ", " + mExtraMessage + "}"; } @Override diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java index aae6f9214c70..0c7264697cd3 100644 --- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java @@ -89,7 +89,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * from which the main value is derived. Synchronous blocking call. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in Integer format. @@ -102,7 +102,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * from which the main value is derived. Synchronous blocking call. * * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in String format. @@ -114,7 +114,7 @@ public class ImsConfigImplBase { /** * Gets the value of the specified IMS feature item for specified network type. - * This operation gets the feature config value from the master storage (i.e. final + * This operation gets the feature config value from the main storage (i.e. final * value). Asynchronous non-blocking call. * * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. @@ -127,7 +127,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS feature item for specified network type. - * This operation stores the user setting in setting db from which master db + * This operation stores the user setting in setting db from which main db * is derived. * * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. @@ -268,7 +268,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived, and write it into local cache. + * from which the main value is derived, and write it into local cache. * Synchronous blocking call. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. @@ -292,7 +292,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived, and write it into local cache. + * from which the main value is derived, and write it into local cache. * Synchronous blocking call. * * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java index 73ba0e393e78..8f738d216cbe 100644 --- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java @@ -439,8 +439,8 @@ public class ImsCallSessionImplBase implements AutoCloseable { * Transfer an established call to given number * * @param number number to transfer the call - * @param isConfirmationRequired if {@code True}, indicates Assured transfer, - * if {@code False} it indicates Blind transfer. + * @param isConfirmationRequired if {@code True}, indicates a confirmed transfer, + * if {@code False} it indicates an unconfirmed transfer. * @hide */ public void transfer(@NonNull String number, boolean isConfirmationRequired) { diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 6a2638bc7221..4ef44d3ec9ef 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -142,7 +142,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived, and write it into local cache. + * from which the main value is derived, and write it into local cache. * Synchronous blocking call. * * @param item integer key @@ -167,7 +167,7 @@ public class ImsConfigImplBase { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived, and write it into local cache. + * from which the main value is derived, and write it into local cache. * Synchronous blocking call. * * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. diff --git a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java index 689becd7169a..17adede86c51 100644 --- a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java +++ b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java @@ -91,7 +91,7 @@ public class MbmsTempFileProvider extends ContentProvider { public void attachInfo(Context context, ProviderInfo info) { super.attachInfo(context, info); - // Sanity check our security + // Correctness check our security if (info.exported) { throw new SecurityException("Provider must not be exported"); } diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl index 0466efc2f6c6..ab14e82b7087 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl @@ -153,8 +153,8 @@ interface IImsCallSession { * Transfer an established call to given number * * @param number number to transfer the call - * @param isConfirmationRequired if {@code True}, indicates Assured transfer, - * if {@code False} it indicates Blind transfer. + * @param isConfirmationRequired if {@code True}, indicates a confirmed transfer, + * if {@code False} it indicates an unconfirmed transfer. */ void transfer(String number, boolean isConfirmationRequired); diff --git a/telephony/java/com/android/ims/internal/IImsConfig.aidl b/telephony/java/com/android/ims/internal/IImsConfig.aidl index 7324814ae5a4..1a14e8780664 100644 --- a/telephony/java/com/android/ims/internal/IImsConfig.aidl +++ b/telephony/java/com/android/ims/internal/IImsConfig.aidl @@ -49,7 +49,7 @@ interface IImsConfig { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * from which the main value is derived. Synchronous blocking call. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in Integer format. @@ -60,7 +60,7 @@ interface IImsConfig { /** * Sets the value for IMS service/capabilities parameters by the operator device * management entity. It sets the config item value in the provisioned storage - * from which the master value is derived. Synchronous blocking call. + * from which the main value is derived. Synchronous blocking call. * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in String format. @@ -70,7 +70,7 @@ interface IImsConfig { /** * Gets the value of the specified IMS feature item for specified network type. - * This operation gets the feature config value from the master storage (i.e. final + * This operation gets the feature config value from the main storage (i.e. final * value). Asynchronous non-blocking call. * * @param feature. as defined in com.android.ims.ImsConfig#FeatureConstants. @@ -82,7 +82,7 @@ interface IImsConfig { /** * Sets the value for IMS feature item for specified network type. - * This operation stores the user setting in setting db from which master db + * This operation stores the user setting in setting db from which main db * is dervied. * * @param feature. as defined in com.android.ims.ImsConfig#FeatureConstants. diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 542e08d743ab..a34e474e666e 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -479,7 +479,7 @@ public class SmsMessage extends SmsMessageBase { length = dis.readUnsignedByte(); addr.numberOfDigits = length; - // sanity check on the length + // Correctness check on the length if (length > pdu.length) { throw new RuntimeException( "createFromPdu: Invalid pdu, addr.numberOfDigits " + length @@ -496,7 +496,7 @@ public class SmsMessage extends SmsMessageBase { //encoded BearerData: bearerDataLength = dis.readInt(); - // sanity check on the length + // Correctness check on the length if (bearerDataLength > pdu.length) { throw new RuntimeException( "createFromPdu: Invalid pdu, bearerDataLength " + bearerDataLength diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 7d5710e32194..7dd2f6dd8e32 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -354,7 +354,7 @@ public class SmsMessage extends SmsMessageBase { statusReportRequested, ret); // Skip encoding pdu if error occurs when create pdu head and the error will be handled - // properly later on encodedMessage sanity check. + // properly later on encodedMessage correctness check. if (bo == null) return ret; // User Data (and length) @@ -536,7 +536,7 @@ public class SmsMessage extends SmsMessageBase { scAddress, destinationAddress, (byte) 0x41, /* TP-MTI=SMS-SUBMIT, TP-UDHI=true */ statusReportRequested, ret); // Skip encoding pdu if error occurs when create pdu head and the error will be handled - // properly later on encodedMessage sanity check. + // properly later on encodedMessage correctness check. if (bo == null) return ret; // TP-Data-Coding-Scheme diff --git a/test-runner/src/android/test/AndroidTestRunner.java b/test-runner/src/android/test/AndroidTestRunner.java index f898516a001b..b2fdc5084834 100644 --- a/test-runner/src/android/test/AndroidTestRunner.java +++ b/test-runner/src/android/test/AndroidTestRunner.java @@ -125,7 +125,7 @@ public class AndroidTestRunner extends BaseTestRunner { } catch (IllegalArgumentException e) { runFailed("Illegal argument passed to constructor. Class: " + testClass.getName()); } catch (InvocationTargetException e) { - runFailed("Constructor thew an exception. Class: " + testClass.getName()); + runFailed("Constructor threw an exception. Class: " + testClass.getName()); } return null; } diff --git a/tests/BootImageProfileTest/OWNERS b/tests/BootImageProfileTest/OWNERS index 657b3f2add2e..7ee0d9a5e77e 100644 --- a/tests/BootImageProfileTest/OWNERS +++ b/tests/BootImageProfileTest/OWNERS @@ -1,4 +1,4 @@ -mathieuc@google.com calin@google.com +mathieuc@google.com +ngeoffray@google.com yawanng@google.com -sehr@google.com diff --git a/tests/LocalizationTest/Android.bp b/tests/LocalizationTest/Android.bp new file mode 100644 index 000000000000..c4bfcb1d2261 --- /dev/null +++ b/tests/LocalizationTest/Android.bp @@ -0,0 +1,41 @@ +// 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. + +android_test { + name: "LocalizationTest", + srcs: ["java/**/*.kt"], + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + ], + static_libs: [ + "androidx.test.core", + "androidx.test.ext.junit", + "androidx.test.rules", + "mockito-target-extended-minus-junit4", + "truth-prebuilt", + ], + jni_libs: [ + // For mockito extended + "libdexmakerjvmtiagent", + "libstaticjvmtiagent", + ], + certificate: "platform", + platform_apis: true, + test_suites: ["device-tests"], + optimize: { + enabled: false, + }, +} diff --git a/tests/LocalizationTest/AndroidManifest.xml b/tests/LocalizationTest/AndroidManifest.xml new file mode 100644 index 000000000000..b135443960f5 --- /dev/null +++ b/tests/LocalizationTest/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.android.internal.app"> + + <application android:debuggable="true" android:testOnly="true"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.android.internal.app" + android:label="Localization Tests" /> + +</manifest> diff --git a/tests/LocalizationTest/AndroidTest.xml b/tests/LocalizationTest/AndroidTest.xml new file mode 100644 index 000000000000..8309b4f611f8 --- /dev/null +++ b/tests/LocalizationTest/AndroidTest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> +<configuration description="Localization Tests."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="install-arg" value="-t" /> + <option name="test-file-name" value="LocalizationTest.apk" /> + </target_preparer> + + <option name="test-tag" value="LocalizationTest" /> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.android.internal.app" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration>
\ No newline at end of file diff --git a/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt b/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt new file mode 100644 index 000000000000..22ea97167326 --- /dev/null +++ b/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package com.android.android.internal.app + +import android.os.SystemProperties +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn +import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession +import com.android.internal.R +import com.android.internal.app.LocalePicker +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.After +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.eq +import org.mockito.MockitoSession + +@RunWith(AndroidJUnit4::class) +class LocalizationTest { + private val mContext = InstrumentationRegistry.getInstrumentation().context + private val mUnfilteredLocales = + mContext.getResources().getStringArray(R.array.supported_locales) + + private lateinit var mMockitoSession: MockitoSession + + @Before + fun setUp() { + mMockitoSession = mockitoSession() + .initMocks(this) + .spyStatic(SystemProperties::class.java) + .startMocking() + } + + @After + fun tearDown() { + mMockitoSession.finishMocking() + } + + @Test + fun testGetSupportedLocales_noFilter() { + // Filter not set. + setTestLocaleFilter(null) + + val locales1 = LocalePicker.getSupportedLocales(mContext) + + assertThat(locales1).isEqualTo(mUnfilteredLocales) + + // Empty filter. + setTestLocaleFilter("") + + val locales2 = LocalePicker.getSupportedLocales(mContext) + + assertThat(locales2).isEqualTo(mUnfilteredLocales) + } + + @Test + fun testGetSupportedLocales_invalidFilter() { + setTestLocaleFilter("**") + + val locales = LocalePicker.getSupportedLocales(mContext) + + assertThat(locales).isEqualTo(mUnfilteredLocales) + } + + @Test + fun testGetSupportedLocales_inclusiveFilter() { + setTestLocaleFilter("^(de-AT|de-DE|en|ru).*") + + val locales = LocalePicker.getSupportedLocales(mContext) + + assertThat(locales).isEqualTo( + mUnfilteredLocales + .filter { it.startsWithAnyOf("de-AT", "de-DE", "en", "ru") } + .toTypedArray() + ) + } + + @Test + fun testGetSupportedLocales_exclusiveFilter() { + setTestLocaleFilter("^(?!de-IT|es|fr).*") + + val locales = LocalePicker.getSupportedLocales(mContext) + + assertThat(locales).isEqualTo( + mUnfilteredLocales + .filter { !it.startsWithAnyOf("de-IT", "es", "fr") } + .toTypedArray() + ) + } + + private fun setTestLocaleFilter(localeFilter: String?) { + doReturn(localeFilter).`when` { SystemProperties.get(eq("ro.localization.locale_filter")) } + } + + private fun String.startsWithAnyOf(vararg prefixes: String): Boolean { + prefixes.forEach { + if (startsWith(it)) return true + } + + return false + } +} diff --git a/tests/RollbackTest/README.txt b/tests/RollbackTest/README.txt index c0b718a3e2c1..bc3b3bc3a1ee 100644 --- a/tests/RollbackTest/README.txt +++ b/tests/RollbackTest/README.txt @@ -9,10 +9,10 @@ StagedRollbackTest - device driven test for staged rollbacks. TestApp - - source for dummy apks used in testing. + - source for fake apks used in testing. TestApex - - source for dummy apex modules used in testing. + - source for fake apex modules used in testing. Running the tests ================= diff --git a/tests/net/common/java/android/net/DhcpInfoTest.java b/tests/net/common/java/android/net/DhcpInfoTest.java index bd5533f33910..4d45ad72a9b8 100644 --- a/tests/net/common/java/android/net/DhcpInfoTest.java +++ b/tests/net/common/java/android/net/DhcpInfoTest.java @@ -16,8 +16,7 @@ package android.net; -import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL; - +import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL; import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip; diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt index b7c47c2bc223..dd3f5bebdb8e 100644 --- a/tests/net/common/java/android/net/NetworkProviderTest.kt +++ b/tests/net/common/java/android/net/NetworkProviderTest.kt @@ -19,23 +19,23 @@ package android.net import android.app.Instrumentation import android.content.Context import android.net.NetworkCapabilities.TRANSPORT_TEST +import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable +import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn +import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested import android.os.Build import android.os.HandlerThread import android.os.Looper -import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable -import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested -import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn import androidx.test.InstrumentationRegistry -import com.android.testutils.ArrayTrackRecord +import com.android.net.module.util.ArrayTrackRecord import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner -import java.util.UUID -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import java.util.UUID +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals private const val DEFAULT_TIMEOUT_MS = 5000L private val instrumentation: Instrumentation diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index bc853749e294..e6346ea52548 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -4226,7 +4226,7 @@ public class ConnectivityServiceTest { callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); } - // Sanity check before testing started keepalive. + // Basic check before testing started keepalive. try (SocketKeepalive ka = mCm.createSocketKeepalive( myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { ka.start(validKaInterval); diff --git a/tests/net/java/com/android/server/NetIdManagerTest.kt b/tests/net/java/com/android/server/NetIdManagerTest.kt index 045f89f85e3b..6f5e740d344c 100644 --- a/tests/net/java/com/android/server/NetIdManagerTest.kt +++ b/tests/net/java/com/android/server/NetIdManagerTest.kt @@ -19,8 +19,8 @@ package com.android.server import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import com.android.server.NetIdManager.MIN_NET_ID -import com.android.testutils.ExceptionUtils.ThrowingRunnable import com.android.testutils.assertThrows +import com.android.testutils.ExceptionUtils.ThrowingRunnable import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index fdc6084884f6..912460a1b172 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -26,14 +26,19 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.INetd.PERMISSION_INTERNET; +import static android.net.INetd.PERMISSION_NONE; +import static android.net.INetd.PERMISSION_SYSTEM; +import static android.net.INetd.PERMISSION_UNINSTALLED; +import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.SYSTEM_UID; import static com.android.server.connectivity.PermissionMonitor.NETWORK; import static com.android.server.connectivity.PermissionMonitor.SYSTEM; +import static com.android.server.connectivity.PermissionMonitor.UidNetdPermissionInfo; import static junit.framework.Assert.fail; @@ -65,7 +70,7 @@ import android.net.UidRange; import android.os.Build; import android.os.UserHandle; import android.os.UserManager; -import android.util.SparseIntArray; +import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -97,7 +102,6 @@ public class PermissionMonitorTest { private static final int SYSTEM_UID1 = 1000; private static final int SYSTEM_UID2 = 1008; private static final int VPN_UID = 10002; - private static final String REAL_SYSTEM_PACKAGE_NAME = "android"; private static final String MOCK_PACKAGE1 = "appName1"; private static final String MOCK_PACKAGE2 = "appName2"; private static final String SYSTEM_PACKAGE1 = "sysName1"; @@ -128,6 +132,7 @@ public class PermissionMonitorTest { new UserInfo(MOCK_USER1, "", 0), new UserInfo(MOCK_USER2, "", 0), })); + doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), anyInt()); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); @@ -140,35 +145,15 @@ public class PermissionMonitorTest { verify(mMockPmi).getPackageList(mPermissionMonitor); } - private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, - String... permissions) { - final PackageInfo packageInfo = - packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); + private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) { + final PackageInfo packageInfo = buildPackageInfo(partition, uid, MOCK_USER1); packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; - packageInfo.applicationInfo.uid = uid; - return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); - } - - private static PackageInfo systemPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); + return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo); } - private static PackageInfo vendorPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_VENDOR); - } - - private static PackageInfo packageInfoWithPermissions(int permissionsFlags, - String[] permissions, String partition) { - int[] requestedPermissionsFlags = new int[permissions.length]; - for (int i = 0; i < permissions.length; i++) { - requestedPermissionsFlags[i] = permissionsFlags; - } + private static PackageInfo packageInfoWithPartition(String partition) { final PackageInfo packageInfo = new PackageInfo(); - packageInfo.requestedPermissions = permissions; packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.requestedPermissionsFlags = requestedPermissionsFlags; int privateFlags = 0; switch (partition) { case PARTITION_OEM: @@ -185,168 +170,145 @@ public class PermissionMonitorTest { return packageInfo; } - private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) { - final PackageInfo pkgInfo; - if (hasSystemPermission) { - pkgInfo = systemPackageInfoWithPermissions( - CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - } else { - pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, ""); - } + private static PackageInfo buildPackageInfo(String partition, int uid, int userId) { + final PackageInfo pkgInfo = packageInfoWithPartition(partition); pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); return pkgInfo; } + /** This will REMOVE all previously set permissions from given uid. */ + private void removeAllPermissions(int uid) { + doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), eq(uid)); + } + + /** Set up mocks so that given UID has the requested permissions. */ + private void addPermissions(int uid, String... permissions) { + for (String permission : permissions) { + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mDeps).uidPermission(eq(permission), eq(uid)); + } + } + @Test public void testHasPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE, NETWORK_STACK); - assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions( - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = packageInfoWithPermissions(REQUESTED_PERMISSION_REQUIRED, new String[] { - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL, NETWORK_STACK }, - PARTITION_SYSTEM); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissions = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissionsFlags = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); + addPermissions(MOCK_UID1); + assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + + addPermissions(MOCK_UID1, CHANGE_NETWORK_STATE, NETWORK_STACK); + assertTrue(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1)); + assertTrue(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID2)); + assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID2)); + + addPermissions(MOCK_UID2, CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + assertTrue(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID2)); + assertTrue(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID2)); } @Test public void testIsVendorApp() { - PackageInfo app = systemPackageInfoWithPermissions(); + PackageInfo app = packageInfoWithPartition(PARTITION_SYSTEM); assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_OEM); + app = packageInfoWithPartition(PARTITION_OEM); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_PRODUCT); + app = packageInfoWithPartition(PARTITION_PRODUCT); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = vendorPackageInfoWithPermissions(); + app = packageInfoWithPartition(PARTITION_VENDOR); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); } - @Test - public void testHasNetworkPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - assertTrue(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(NETWORK_STACK); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); + /** + * Remove all permissions from the uid then setup permissions to uid for checking restricted + * network permission. + */ + private void assertRestrictedNetworkPermission(boolean hasPermission, int uid, + String... permissions) { + removeAllPermissions(uid); + addPermissions(uid, permissions); + assertEquals(hasPermission, mPermissionMonitor.hasRestrictedNetworkPermission(uid)); } @Test public void testHasRestrictedNetworkPermission() { - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); + assertRestrictedNetworkPermission(false, MOCK_UID1); + assertRestrictedNetworkPermission(false, MOCK_UID1, CHANGE_NETWORK_STATE); + assertRestrictedNetworkPermission(true, MOCK_UID1, NETWORK_STACK); + assertRestrictedNetworkPermission(false, MOCK_UID1, CONNECTIVITY_INTERNAL); + assertRestrictedNetworkPermission(true, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS); + assertRestrictedNetworkPermission(false, MOCK_UID1, CHANGE_WIFI_STATE); + assertRestrictedNetworkPermission(true, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK); + + assertFalse(mPermissionMonitor.hasRestrictedNetworkPermission(MOCK_UID2)); + assertFalse(mPermissionMonitor.hasRestrictedNetworkPermission(SYSTEM_UID)); } @Test - public void testHasRestrictedNetworkPermissionSystemUid() { + public void testIsCarryoverPackage() { doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt(); - assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - } - - @Test - public void testHasRestrictedNetworkPermissionVendorApp() { - assertTrue(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - - assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); + + assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1)); } private void assertBackgroundPermission(boolean hasPermission, String name, int uid, String... permissions) throws Exception { when(mPackageManager.getPackageInfo(eq(name), anyInt())) - .thenReturn(packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM)); + .thenReturn(buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1)); + addPermissions(uid, permissions); mPermissionMonitor.onPackageAdded(name, uid); assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid)); } @Test public void testHasUseBackgroundNetworksPermission() throws Exception { - assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK); - assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1)); - assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1); - assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1, - CONNECTIVITY_USE_RESTRICTED_NETWORKS); + assertBackgroundPermission(false, "mock1", MOCK_UID1); + assertBackgroundPermission(false, "mock2", MOCK_UID1, CONNECTIVITY_INTERNAL); + assertBackgroundPermission(true, "mock3", MOCK_UID1, NETWORK_STACK); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2, - CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK); + assertBackgroundPermission(false, "mock4", MOCK_UID2); + assertBackgroundPermission(true, "mock5", MOCK_UID2, + CONNECTIVITY_USE_RESTRICTED_NETWORKS); + + doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); + assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); + assertBackgroundPermission(false, "system1", SYSTEM_UID); + assertBackgroundPermission(true, "system2", SYSTEM_UID, CHANGE_NETWORK_STATE); + doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt(); + removeAllPermissions(SYSTEM_UID); + assertBackgroundPermission(true, "system3", SYSTEM_UID); } private class NetdMonitor { @@ -356,7 +318,7 @@ public class PermissionMonitorTest { // Add hook to verify and track result of setPermission. doAnswer((InvocationOnMock invocation) -> { final Object[] args = invocation.getArguments(); - final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM); + final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM); for (final int uid : (int[]) args[1]) { // TODO: Currently, permission monitor will send duplicate commands for each uid // corresponding to each user. Need to fix that and uncomment below test. @@ -416,13 +378,14 @@ public class PermissionMonitorTest { // MOCK_UID1: MOCK_PACKAGE1 only has network permission. // SYSTEM_UID: SYSTEM_PACKAGE1 has system permission. // SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission. - doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString()); + doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), + anyString(), anyInt()); doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE1)); + eq(SYSTEM_PACKAGE1), anyInt()); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE2)); + eq(SYSTEM_PACKAGE2), anyInt()); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(MOCK_PACKAGE1)); + eq(MOCK_PACKAGE1), anyInt()); // Add SYSTEM_PACKAGE2, expect only have network permission. mPermissionMonitor.onUserAdded(MOCK_USER1); @@ -473,13 +436,15 @@ public class PermissionMonitorTest { public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - buildPackageInfo(/* SYSTEM */ true, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, MOCK_UID1, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, MOCK_UID2, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, VPN_UID, MOCK_USER1) + buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID2, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); + addPermissions(SYSTEM_UID, + CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); mPermissionMonitor.startMonitoring(); // Every app on user 0 except MOCK_UID2 are under VPN. final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] { @@ -524,11 +489,11 @@ public class PermissionMonitorTest { public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - buildPackageInfo(true, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(false, VPN_UID, MOCK_USER1) + buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); mPermissionMonitor.startMonitoring(); final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1)); @@ -596,47 +561,48 @@ public class PermissionMonitorTest { // SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission. // SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission. - SparseIntArray netdPermissionsAppIds = new SparseIntArray(); - netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET); - netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE); - netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS); - netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS); + final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); + uidsPermInfo.put(MOCK_UID1, new UidNetdPermissionInfo(PERMISSION_INTERNET)); + uidsPermInfo.put(MOCK_UID2, new UidNetdPermissionInfo(PERMISSION_NONE)); + uidsPermInfo.put(SYSTEM_UID1, new UidNetdPermissionInfo( + PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); + uidsPermInfo.put(SYSTEM_UID2, new UidNetdPermissionInfo(PERMISSION_UPDATE_DEVICE_STATS)); // Send the permission information to netd, expect permission updated. - mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds); + mPermissionMonitor.sendPackagePermissionsToNetd(uidsPermInfo); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS, + mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID2}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID2}); // Update permission of MOCK_UID1, expect new permission show up. - mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, new UidNetdPermissionInfo( + PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Change permissions of SYSTEM_UID2, expect new permission show up and old permission // revoked. - mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, - INetd.PERMISSION_INTERNET); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); + mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, new UidNetdPermissionInfo( + PERMISSION_INTERNET)); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); // Revoke permission from SYSTEM_UID1, expect no permission stored. - mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1}); + mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, new UidNetdPermissionInfo( + PERMISSION_NONE)); + mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{SYSTEM_UID1}); } private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) throws Exception { - PackageInfo packageInfo = packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); + final PackageInfo packageInfo = buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo); when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName}); + addPermissions(uid, permissions); return packageInfo; } @@ -652,31 +618,30 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID2}); } @Test public void testPackageInstallSharedUid() throws Exception { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1, - new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Install another package with the same uid and no permissions should not cause the UID to // lose permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(); + final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); } @Test @@ -684,12 +649,12 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); } @Test @@ -697,15 +662,16 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); + removeAllPermissions(MOCK_UID1); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test @@ -713,10 +679,10 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test @@ -724,17 +690,19 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET + | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Mock another package with the same uid but different permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET); + final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{ MOCK_PACKAGE2}); + removeAllPermissions(MOCK_UID1); + addPermissions(MOCK_UID1, INTERNET); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); + mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test @@ -743,9 +711,6 @@ public class PermissionMonitorTest { // necessary permission. final Context realContext = InstrumentationRegistry.getContext(); final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService); - final PackageManager manager = realContext.getPackageManager(); - final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME, - GET_PERMISSIONS | MATCH_ANY_USER); - assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertTrue(monitor.hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, SYSTEM_UID)); } } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 4ccf79a0cb37..e8c4ee9c628d 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -30,6 +30,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -49,6 +50,7 @@ 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.UserIdInt; import android.app.AppOpsManager; import android.app.NotificationManager; @@ -65,6 +67,7 @@ import android.net.InetAddresses; import android.net.IpPrefix; import android.net.IpSecManager; import android.net.LinkProperties; +import android.net.LocalSocket; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; @@ -74,6 +77,7 @@ import android.net.VpnManager; import android.net.VpnService; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.os.ConditionVariable; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Process; @@ -101,13 +105,20 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.net.Inet4Address; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.stream.Stream; /** @@ -133,7 +144,8 @@ public class VpnTest { managedProfileA.profileGroupId = primaryUser.id; } - static final String TEST_VPN_PKG = "com.dummy.vpn"; + static final String EGRESS_IFACE = "wlan0"; + static final String TEST_VPN_PKG = "com.testvpn.vpn"; private static final String TEST_VPN_SERVER = "1.2.3.4"; private static final String TEST_VPN_IDENTITY = "identity"; private static final byte[] TEST_VPN_PSK = "psk".getBytes(); @@ -258,12 +270,12 @@ public class VpnTest { } @Test - public void testUidWhiteAndBlacklist() throws Exception { + public void testUidAllowAndDenylist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; - // Whitelist + // Allowed list final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, Arrays.asList(packages), null); assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { @@ -271,7 +283,7 @@ public class VpnTest { new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]) })), allow); - // Blacklist + // Denied list final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, Arrays.asList(packages)); assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { @@ -342,11 +354,11 @@ public class VpnTest { } @Test - public void testLockdownWhitelist() throws Exception { + public void testLockdownAllowlist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); - // Set always-on with lockdown and whitelist app PKGS[2] from lockdown. + // Set always-on with lockdown and allow app PKGS[2] from lockdown. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { @@ -356,7 +368,7 @@ public class VpnTest { assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - // Change whitelisted app to PKGS[3]. + // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { @@ -383,7 +395,7 @@ public class VpnTest { assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); - // Remove the whitelist. + // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), @@ -396,7 +408,7 @@ public class VpnTest { user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0]); - // Add the whitelist. + // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { @@ -409,12 +421,12 @@ public class VpnTest { assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); - // Try whitelisting a package with a comma, should be rejected. + // Try allowing a package with a comma, should be rejected. assertFalse(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore)); - // Pass a non-existent packages in the whitelist, they (and only they) should be ignored. - // Whitelisted package should change from PGKS[1] to PKGS[2]. + // Pass a non-existent packages in the allowlist, they (and only they) should be ignored. + // allowed package should change from PGKS[1] to PKGS[2]. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{ @@ -1012,31 +1024,190 @@ public class VpnTest { // a subsequent CL. } - @Test - public void testStartLegacyVpn() throws Exception { + public Vpn startLegacyVpn(final VpnProfile vpnProfile) throws Exception { final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); // Dummy egress interface - final String egressIface = "DUMMY0"; final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(egressIface); + lp.setInterfaceName(EGRESS_IFACE); final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - InetAddresses.parseNumericAddress("192.0.2.0"), egressIface); + InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE); lp.addRoute(defaultRoute); - vpn.startLegacyVpn(mVpnProfile, mKeyStore, lp); + vpn.startLegacyVpn(vpnProfile, mKeyStore, lp); + return vpn; + } + @Test + public void testStartPlatformVpn() throws Exception { + startLegacyVpn(mVpnProfile); // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in - // a subsequent CL. + // a subsequent patch. + } + + @Test + public void testStartRacoonNumericAddress() throws Exception { + startRacoon("1.2.3.4", "1.2.3.4"); + } + + @Test + public void testStartRacoonHostname() throws Exception { + startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve + } + + public void startRacoon(final String serverAddr, final String expectedAddr) + throws Exception { + final ConditionVariable legacyRunnerReady = new ConditionVariable(); + final VpnProfile profile = new VpnProfile("testProfile" /* key */); + profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK; + profile.name = "testProfileName"; + profile.username = "userName"; + profile.password = "thePassword"; + profile.server = serverAddr; + profile.ipsecIdentifier = "id"; + profile.ipsecSecret = "secret"; + profile.l2tpSecret = "l2tpsecret"; + when(mConnectivityManager.getAllNetworks()) + .thenReturn(new Network[] { new Network(101) }); + when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), + anyInt(), any(), anyInt())).thenAnswer(invocation -> { + // The runner has registered an agent and is now ready. + legacyRunnerReady.open(); + return new Network(102); + }); + final Vpn vpn = startLegacyVpn(profile); + final TestDeps deps = (TestDeps) vpn.mDeps; + try { + // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK + assertArrayEquals( + new String[] { EGRESS_IFACE, expectedAddr, "udppsk", + profile.ipsecIdentifier, profile.ipsecSecret, "1701" }, + deps.racoonArgs.get(10, TimeUnit.SECONDS)); + // literal values are hardcoded in Vpn.java for mtpd args + assertArrayEquals( + new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret, + "name", profile.username, "password", profile.password, + "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns", + "idle", "1800", "mtu", "1400", "mru", "1400" }, + deps.mtpdArgs.get(10, TimeUnit.SECONDS)); + // Now wait for the runner to be ready before testing for the route. + legacyRunnerReady.block(10_000); + // In this test the expected address is always v4 so /32 + final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"), + RouteInfo.RTN_THROW); + assertTrue("Routes lack the expected throw route (" + expectedRoute + ") : " + + vpn.mConfig.routes, + vpn.mConfig.routes.contains(expectedRoute)); + } finally { + // Now interrupt the thread, unblock the runner and clean up. + vpn.mVpnRunner.exitVpnRunner(); + deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier + vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup + } + } + + private static final class TestDeps extends Vpn.Dependencies { + public final CompletableFuture<String[]> racoonArgs = new CompletableFuture(); + public final CompletableFuture<String[]> mtpdArgs = new CompletableFuture(); + public final File mStateFile; + + private final HashMap<String, Boolean> mRunningServices = new HashMap<>(); + + TestDeps() { + try { + mStateFile = File.createTempFile("vpnTest", ".tmp"); + mStateFile.deleteOnExit(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void startService(final String serviceName) { + mRunningServices.put(serviceName, true); + } + + @Override + public void stopService(final String serviceName) { + mRunningServices.put(serviceName, false); + } + + @Override + public boolean isServiceRunning(final String serviceName) { + return mRunningServices.getOrDefault(serviceName, false); + } + + @Override + public boolean isServiceStopped(final String serviceName) { + return !isServiceRunning(serviceName); + } + + @Override + public File getStateFile() { + return mStateFile; + } + + @Override + public void sendArgumentsToDaemon( + final String daemon, final LocalSocket socket, final String[] arguments, + final Vpn.RetryScheduler interruptChecker) throws IOException { + if ("racoon".equals(daemon)) { + racoonArgs.complete(arguments); + } else if ("mtpd".equals(daemon)) { + writeStateFile(arguments); + mtpdArgs.complete(arguments); + } else { + throw new UnsupportedOperationException("Unsupported daemon : " + daemon); + } + } + + private void writeStateFile(final String[] arguments) throws IOException { + mStateFile.delete(); + mStateFile.createNewFile(); + mStateFile.deleteOnExit(); + final BufferedWriter writer = new BufferedWriter( + new FileWriter(mStateFile, false /* append */)); + writer.write(EGRESS_IFACE); + writer.write("\n"); + // addresses + writer.write("10.0.0.1/24\n"); + // routes + writer.write("192.168.6.0/24\n"); + // dns servers + writer.write("192.168.6.1\n"); + // search domains + writer.write("vpn.searchdomains.com\n"); + // endpoint - intentionally empty + writer.write("\n"); + writer.flush(); + writer.close(); + } + + @Override + @NonNull + public InetAddress resolve(final String endpoint) { + try { + // If a numeric IP address, return it. + return InetAddress.parseNumericAddress(endpoint); + } catch (IllegalArgumentException e) { + // Otherwise, return some token IP to test for. + return InetAddress.parseNumericAddress("5.6.7.8"); + } + } + + @Override + public boolean checkInterfacePresent(final Vpn vpn, final String iface) { + return true; + } } /** * Mock some methods of vpn object. */ private Vpn createVpn(@UserIdInt int userId) { - return new Vpn(Looper.myLooper(), mContext, mNetService, + return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService, userId, mKeyStore, mSystemServices, mIkev2SessionCreator); } diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java index 551498f2c0cc..e83d2a90bffa 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java @@ -23,11 +23,12 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileAll; +import static android.net.NetworkUtils.multiplySafeByRational; import static android.os.Process.myUid; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; -import static com.android.server.net.NetworkStatsCollection.multiplySafe; +import static com.android.testutils.MiscAssertsKt.assertThrows; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -505,23 +506,25 @@ public class NetworkStatsCollectionTest { } @Test - public void testMultiplySafe() { - assertEquals(25, multiplySafe(50, 1, 2)); - assertEquals(100, multiplySafe(50, 2, 1)); + public void testMultiplySafeRational() { + assertEquals(25, multiplySafeByRational(50, 1, 2)); + assertEquals(100, multiplySafeByRational(50, 2, 1)); - assertEquals(-10, multiplySafe(30, -1, 3)); - assertEquals(0, multiplySafe(30, 0, 3)); - assertEquals(10, multiplySafe(30, 1, 3)); - assertEquals(20, multiplySafe(30, 2, 3)); - assertEquals(30, multiplySafe(30, 3, 3)); - assertEquals(40, multiplySafe(30, 4, 3)); + assertEquals(-10, multiplySafeByRational(30, -1, 3)); + assertEquals(0, multiplySafeByRational(30, 0, 3)); + assertEquals(10, multiplySafeByRational(30, 1, 3)); + assertEquals(20, multiplySafeByRational(30, 2, 3)); + assertEquals(30, multiplySafeByRational(30, 3, 3)); + assertEquals(40, multiplySafeByRational(30, 4, 3)); assertEquals(100_000_000_000L, - multiplySafe(300_000_000_000L, 10_000_000_000L, 30_000_000_000L)); + multiplySafeByRational(300_000_000_000L, 10_000_000_000L, 30_000_000_000L)); assertEquals(100_000_000_010L, - multiplySafe(300_000_000_000L, 10_000_000_001L, 30_000_000_000L)); + multiplySafeByRational(300_000_000_000L, 10_000_000_001L, 30_000_000_000L)); assertEquals(823_202_048L, - multiplySafe(4_939_212_288L, 2_121_815_528L, 12_730_893_165L)); + multiplySafeByRational(4_939_212_288L, 2_121_815_528L, 12_730_893_165L)); + + assertThrows(ArithmeticException.class, () -> multiplySafeByRational(30, 3, 0)); } /** diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java index 9531b0a5bb66..6dc4fced19a2 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java @@ -130,7 +130,7 @@ public final class NetworkStatsSubscriptionsMonitorTest { mTestSubList.add(subId); final int[] subList = convertArrayListToIntArray(mTestSubList); - when(mSubscriptionManager.getActiveAndHiddenSubscriptionIdList()).thenReturn(subList); + when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId); mMonitor.onSubscriptionsChanged(); } @@ -139,7 +139,7 @@ public final class NetworkStatsSubscriptionsMonitorTest { // Remove subId from TestSubList. mTestSubList.removeIf(it -> it == subId); final int[] subList = convertArrayListToIntArray(mTestSubList); - when(mSubscriptionManager.getActiveAndHiddenSubscriptionIdList()).thenReturn(subList); + when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); mMonitor.onSubscriptionsChanged(); } diff --git a/tests/utils/DummyIME/Android.bp b/tests/utils/StubIME/Android.bp index 4a44b3b27992..668c92c86c51 100644 --- a/tests/utils/DummyIME/Android.bp +++ b/tests/utils/StubIME/Android.bp @@ -15,7 +15,7 @@ // android_test { - name: "DummyIME", + name: "StubIME", srcs: ["src/**/*.java"], sdk_version: "current", } diff --git a/tests/utils/DummyIME/AndroidManifest.xml b/tests/utils/StubIME/AndroidManifest.xml index fd17a52cb7d9..04502d331d6a 100644 --- a/tests/utils/DummyIME/AndroidManifest.xml +++ b/tests/utils/StubIME/AndroidManifest.xml @@ -17,16 +17,16 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.testing.dummyime"> - <application android:label="Dummy IME"> - <service android:name="DummyIme" + package="com.android.testing.stubime"> + <application android:label="Stub IME"> + <service android:name="StubIme" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service> - <activity android:name=".ImePreferences" android:label="Dummy IME Settings"> + <activity android:name=".ImePreferences" android:label="Stub IME Settings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> </intent-filter> diff --git a/tests/utils/DummyIME/res/xml/method.xml b/tests/utils/StubIME/res/xml/method.xml index 43a330e2bc93..1bb4bcd3480b 100644 --- a/tests/utils/DummyIME/res/xml/method.xml +++ b/tests/utils/StubIME/res/xml/method.xml @@ -21,9 +21,9 @@ <!-- for the Search Manager. --> <input-method xmlns:android="http://schemas.android.com/apk/res/android" - android:settingsActivity="com.android.testing.dummyime.ImePreferences"> + android:settingsActivity="com.android.testing.stubime.ImePreferences"> <subtype android:label="Generic" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" /> -</input-method>
\ No newline at end of file +</input-method> diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java b/tests/utils/StubIME/src/com/android/testing/stubime/ImePreferences.java index 41036ab86596..b77525ad0a43 100644 --- a/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java +++ b/tests/utils/StubIME/src/com/android/testing/stubime/ImePreferences.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.testing.dummyime; +package com.android.testing.stubime; import android.preference.PreferenceActivity; /** - * Dummy IME preference activity + * Stub IME preference activity */ public class ImePreferences extends PreferenceActivity { diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java b/tests/utils/StubIME/src/com/android/testing/stubime/StubIme.java index 7b7a39a702e5..8795202b3283 100644 --- a/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java +++ b/tests/utils/StubIME/src/com/android/testing/stubime/StubIme.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.testing.dummyime; +package com.android.testing.stubime; import android.inputmethodservice.InputMethodService; /** - * Dummy IME implementation that basically does nothing + * Stub IME implementation that basically does nothing */ -public class DummyIme extends InputMethodService { +public class StubIme extends InputMethodService { @Override public boolean onEvaluateFullscreenMode() { diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index de6b4785ec37..8a282e5f0821 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -13,9 +13,7 @@ # 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. -""" -Generate API lists for non-SDK API enforcement. -""" +"""Generate API lists for non-SDK API enforcement.""" import argparse from collections import defaultdict import functools @@ -24,27 +22,47 @@ import re import sys # Names of flags recognized by the `hiddenapi` tool. -FLAG_WHITELIST = "whitelist" -FLAG_GREYLIST = "greylist" -FLAG_BLACKLIST = "blacklist" -FLAG_GREYLIST_MAX_O = "greylist-max-o" -FLAG_GREYLIST_MAX_P = "greylist-max-p" -FLAG_GREYLIST_MAX_Q = "greylist-max-q" -FLAG_GREYLIST_MAX_R = "greylist-max-r" -FLAG_CORE_PLATFORM_API = "core-platform-api" -FLAG_PUBLIC_API = "public-api" -FLAG_SYSTEM_API = "system-api" -FLAG_TEST_API = "test-api" +FLAG_SDK = 'sdk' +FLAG_UNSUPPORTED = 'unsupported' +FLAG_BLOCKED = 'blocked' +FLAG_MAX_TARGET_O = 'max-target-o' +FLAG_MAX_TARGET_P = 'max-target-p' +FLAG_MAX_TARGET_Q = 'max-target-q' +FLAG_MAX_TARGET_R = 'max-target-r' +FLAG_CORE_PLATFORM_API = 'core-platform-api' +FLAG_PUBLIC_API = 'public-api' +FLAG_SYSTEM_API = 'system-api' +FLAG_TEST_API = 'test-api' + +OLD_FLAG_SDK = "whitelist" +OLD_FLAG_UNSUPPORTED = "greylist" +OLD_FLAG_BLOCKED = "blacklist" +OLD_FLAG_MAX_TARGET_O = "greylist-max-o" +OLD_FLAG_MAX_TARGET_P = "greylist-max-p" +OLD_FLAG_MAX_TARGET_Q = "greylist-max-q" +OLD_FLAG_MAX_TARGET_R = "greylist-max-r" + +OLD_FLAGS_TO_NEW = { + OLD_FLAG_SDK: FLAG_SDK, + OLD_FLAG_UNSUPPORTED: FLAG_UNSUPPORTED, + OLD_FLAG_BLOCKED: FLAG_BLOCKED, + OLD_FLAG_MAX_TARGET_O: FLAG_MAX_TARGET_O, + OLD_FLAG_MAX_TARGET_P: FLAG_MAX_TARGET_P, + OLD_FLAG_MAX_TARGET_Q: FLAG_MAX_TARGET_Q, + OLD_FLAG_MAX_TARGET_R: FLAG_MAX_TARGET_R, +} + +NEW_FLAGS_TO_OLD = dict(zip(OLD_FLAGS_TO_NEW.values(), OLD_FLAGS_TO_NEW.keys())) # List of all known flags. FLAGS_API_LIST = [ - FLAG_WHITELIST, - FLAG_GREYLIST, - FLAG_BLACKLIST, - FLAG_GREYLIST_MAX_O, - FLAG_GREYLIST_MAX_P, - FLAG_GREYLIST_MAX_Q, - FLAG_GREYLIST_MAX_R, + FLAG_SDK, + FLAG_UNSUPPORTED, + FLAG_BLOCKED, + FLAG_MAX_TARGET_O, + FLAG_MAX_TARGET_P, + FLAG_MAX_TARGET_Q, + FLAG_MAX_TARGET_R, ] ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API, @@ -58,7 +76,7 @@ ALL_FLAGS_SET = set(ALL_FLAGS) # Suffix used in command line args to express that only known and # otherwise unassigned entries should be assign the given flag. -# For example, the P dark greylist is checked in as it was in P, +# For example, the max-target-P list is checked in as it was in P, # but signatures have changes since then. The flag instructs this # script to skip any entries which do not exist any more. FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts" @@ -87,6 +105,7 @@ SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags) IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) + def get_args(): """Parses command line arguments. @@ -113,6 +132,7 @@ def get_args(): return parser.parse_args() + def read_lines(filename): """Reads entire file and return it as a list of lines. @@ -130,8 +150,9 @@ def read_lines(filename): lines = map(lambda line: line.strip(), lines) return set(lines) + def write_lines(filename, lines): - """Writes list of lines into a file, overwriting the file it it exists. + """Writes list of lines into a file, overwriting the file if it exists. Args: filename (string): Path to the file to be writting into. @@ -141,6 +162,7 @@ def write_lines(filename, lines): with open(filename, 'w') as f: f.writelines(lines) + def extract_package(signature): """Extracts the package from a signature. @@ -159,6 +181,7 @@ def extract_package(signature): package_name = full_class_name.rpartition("/")[0] return package_name.replace('/', '.') + class FlagsDict: def __init__(self): self._dict_keyset = set() @@ -182,6 +205,36 @@ class FlagsDict: "Please visit go/hiddenapi for more information.").format( source, "\n".join(flags_subset - ALL_FLAGS_SET)) + def convert_to_new_flag(self, flag): + """Converts old flag to a new variant. + + Flags that are considered old are replaced with new versions. + Otherwise, it is a no-op. + + Args: + flag: a string, representing SDK flag. + + Returns: + A string. Result of conversion. + + """ + return OLD_FLAGS_TO_NEW.get(flag, flag) + + def convert_to_old_flag(self, flag): + """Converts a new flag to a old variant. + + No-op if there is no suitable old flag. + Only used to support backwards compatibility. + + Args: + flag: a string, representing SDK flag. + + Returns: + A string. Result of conversion. + + """ + return NEW_FLAGS_TO_OLD.get(flag, flag) + def filter_apis(self, filter_fn): """Returns APIs which match a given predicate. @@ -212,10 +265,16 @@ class FlagsDict: def generate_csv(self): """Constructs CSV entries from a dictionary. + Old versions of flags are used to generate the file. + Returns: List of lines comprising a CSV file. See "parse_and_merge_csv" for format description. """ - return sorted(map(lambda api: ",".join([api] + sorted(self._dict[api])), self._dict)) + lines = [] + for api in self._dict: + flags = sorted([self.convert_to_old_flag(flag) for flag in self._dict[api]]) + lines.append(",".join([api] + flags)) + return sorted(lines) def parse_and_merge_csv(self, csv_lines, source = "<unknown>"): """Parses CSV entries and merges them into a given dictionary. @@ -237,17 +296,16 @@ class FlagsDict: self._dict_keyset.update([ csv[0] for csv in csv_values ]) # Check that all flags are known. - csv_flags = set(functools.reduce( - lambda x, y: set(x).union(y), - [ csv[1:] for csv in csv_values ], - [])) + csv_flags = set() + for csv in csv_values: + csv_flags.update([self.convert_to_new_flag(flag) for flag in csv[1:]]) self._check_flags_set(csv_flags, source) # Iterate over all CSV lines, find entry in dict and append flags to it. for csv in csv_values: - flags = csv[1:] + flags = [self.convert_to_new_flag(flag) for flag in csv[1:]] if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags): - flags.append(FLAG_WHITELIST) + flags.append(FLAG_SDK) self._dict[csv[0]].update(flags) def assign_flag(self, flag, apis, source="<unknown>"): @@ -271,6 +329,7 @@ class FlagsDict: for api in apis: self._dict[api].add(flag) + def main(argv): # Parse arguments. args = vars(get_args()) @@ -287,8 +346,8 @@ def main(argv): flags.parse_and_merge_csv(read_lines(filename), filename) # Combine inputs which do not require any particular order. - # (1) Assign serialization API to whitelist. - flags.assign_flag(FLAG_WHITELIST, flags.filter_apis(IS_SERIALIZATION)) + # (1) Assign serialization API to SDK. + flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION)) # (2) Merge text files with a known flag into the dictionary. for flag in ALL_FLAGS: @@ -314,8 +373,8 @@ def main(argv): valid_entries = flags.filter_apis(should_add_signature_to_list) flags.assign_flag(flag, valid_entries) - # Assign all remaining entries to the blacklist. - flags.assign_flag(FLAG_BLACKLIST, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) + # Mark all remaining entries as blocked. + flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) # Write output. write_lines(args["output"], flags.generate_csv()) diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py index 55c3a7d718db..321c400ef898 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists_test.py +++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py @@ -23,7 +23,7 @@ class TestHiddenapiListGeneration(unittest.TestCase): # Initialize flags so that A and B are put on the whitelist and # C, D, E are left unassigned. Try filtering for the unassigned ones. flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B,' + FLAG_WHITELIST, + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK, 'C', 'D', 'E']) filter_set = flags.filter_apis(lambda api, flags: not flags) self.assertTrue(isinstance(filter_set, set)) @@ -32,10 +32,10 @@ class TestHiddenapiListGeneration(unittest.TestCase): def test_get_valid_subset_of_unassigned_keys(self): # Create flags where only A is unassigned. flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B', 'C']) - flags.assign_flag(FLAG_GREYLIST, set(['C'])) + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C']) + flags.assign_flag(FLAG_UNSUPPORTED, set(['C'])) self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_WHITELIST, 'B', 'C,' + FLAG_GREYLIST ]) + [ 'A,' + OLD_FLAG_SDK, 'B', 'C,' + OLD_FLAG_UNSUPPORTED ]) # Check three things: # (1) B is selected as valid unassigned @@ -50,20 +50,21 @@ class TestHiddenapiListGeneration(unittest.TestCase): # Test empty CSV entry. self.assertEqual(flags.generate_csv(), []) - # Test new additions. + # Test new additions. CSV generator produces values with old flags + # to be backwards compatible. flags.parse_and_merge_csv([ - 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O, - 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, - 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, - 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + 'A,' + FLAG_UNSUPPORTED, + 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O, + 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API, + 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, + 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, ]) self.assertEqual(flags.generate_csv(), [ - 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O, - 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, - 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, - 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + 'A,' + OLD_FLAG_UNSUPPORTED, + 'B,' + OLD_FLAG_BLOCKED + "," + OLD_FLAG_MAX_TARGET_O, + 'C,' + FLAG_SYSTEM_API + ',' + OLD_FLAG_SDK, + 'D,' + OLD_FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, + 'E,' + OLD_FLAG_BLOCKED + ',' + FLAG_TEST_API, ]) # Test unknown flag. @@ -72,16 +73,16 @@ class TestHiddenapiListGeneration(unittest.TestCase): def test_assign_flag(self): flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B']) + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B']) # Test new additions. - flags.assign_flag(FLAG_GREYLIST, set([ 'A', 'B' ])) + flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ])) self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST, 'B,' + FLAG_GREYLIST ]) + [ 'A,' + OLD_FLAG_UNSUPPORTED + "," + OLD_FLAG_SDK, 'B,' + OLD_FLAG_UNSUPPORTED ]) # Test invalid API signature. with self.assertRaises(AssertionError): - flags.assign_flag(FLAG_WHITELIST, set([ 'C' ])) + flags.assign_flag(FLAG_SDK, set([ 'C' ])) # Test invalid flag. with self.assertRaises(AssertionError): diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java index 971aa8e05df2..79e95e81396a 100644 --- a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java +++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java @@ -267,42 +267,42 @@ public class TlvBufferUtilsTest { @Test(expected = IllegalArgumentException.class) public void testTlvItInvalidSizeT1L0() { - final byte[] dummy = { + final byte[] testTlv = { 0, 1, 2 }; - final int dummyLength = 3; - TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, dummy); + final int testLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, testTlv); } @Test(expected = IllegalArgumentException.class) public void testTlvItInvalidSizeTm3L2() { - final byte[] dummy = { + final byte[] testTlv = { 0, 1, 2 }; - final int dummyLength = 3; - TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, dummy); + final int testLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, testTlv); } @Test(expected = IllegalArgumentException.class) public void testTlvItInvalidSizeT1Lm2() { - final byte[] dummy = { + final byte[] testTlv = { 0, 1, 2 }; - final int dummyLength = 3; - TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, dummy); + final int testLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, testTlv); } @Test(expected = IllegalArgumentException.class) public void testTlvItInvalidSizeT1L3() { - final byte[] dummy = { + final byte[] testTlv = { 0, 1, 2 }; - final int dummyLength = 3; - TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, dummy); + final int testLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, testTlv); } @Test(expected = IllegalArgumentException.class) public void testTlvItInvalidSizeT3L1() { - final byte[] dummy = { + final byte[] testTlv = { 0, 1, 2 }; - final int dummyLength = 3; - TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, dummy); + final int testLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, testTlv); } /** diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java index 3f385431e833..1b48a67e9f55 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java @@ -45,7 +45,7 @@ public class WifiAwareAgentNetworkSpecifierTest { Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); for (int i = 0; i < numNs; ++i) { - nsSet.add(getDummyNetworkSpecifier(10 + i)); + nsSet.add(getMockNetworkSpecifier(10 + i)); } WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[numNs])); @@ -78,7 +78,7 @@ public class WifiAwareAgentNetworkSpecifierTest { @Test public void testEmptyDoesntMatchAnything() { WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(); - WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6); + WifiAwareNetworkSpecifier ns = getMockNetworkSpecifier(6); collector.checkThat("No match expected", ns.canBeSatisfiedBy(dut), equalTo(false)); } @@ -88,9 +88,9 @@ public class WifiAwareAgentNetworkSpecifierTest { */ @Test public void testSingleMatch() { - WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6); + WifiAwareNetworkSpecifier nsThis = getMockNetworkSpecifier(6); WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis); - WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8); + WifiAwareNetworkSpecifier nsOther = getMockNetworkSpecifier(8); collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true)); collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false)); } @@ -105,12 +105,12 @@ public class WifiAwareAgentNetworkSpecifierTest { Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); for (int i = 0; i < numNs; ++i) { - nsSet.add(getDummyNetworkSpecifier(10 + i)); + nsSet.add(getMockNetworkSpecifier(10 + i)); } WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[numNs])); - WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000); + WifiAwareNetworkSpecifier nsOther = getMockNetworkSpecifier(10000); for (WifiAwareNetworkSpecifier nsThis: nsSet) { collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true)); @@ -127,13 +127,13 @@ public class WifiAwareAgentNetworkSpecifierTest { Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); for (int i = 0; i < numNs; ++i) { - nsSet.add(getDummyNetworkSpecifier(10 + i)); + nsSet.add(getMockNetworkSpecifier(10 + i)); } WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); - nsSet.add(getDummyNetworkSpecifier(100 + numNs)); + nsSet.add(getMockNetworkSpecifier(100 + numNs)); WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); @@ -149,13 +149,13 @@ public class WifiAwareAgentNetworkSpecifierTest { Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); for (int i = 0; i < numNs; ++i) { - nsSet.add(getDummyNetworkSpecifier(10 + i)); + nsSet.add(getMockNetworkSpecifier(10 + i)); } WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); - nsSet.add(getDummyNetworkSpecifier(100 + numNs)); + nsSet.add(getMockNetworkSpecifier(100 + numNs)); WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier( nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); @@ -165,10 +165,10 @@ public class WifiAwareAgentNetworkSpecifierTest { // utilities /** - * Returns a WifiAwareNetworkSpecifier with dummy (but valid) entries. Each can be + * Returns a WifiAwareNetworkSpecifier with mock (but valid) entries. Each can be * differentiated (made unique) by specifying a different client ID. */ - WifiAwareNetworkSpecifier getDummyNetworkSpecifier(int clientId) { + WifiAwareNetworkSpecifier getMockNetworkSpecifier(int clientId) { return new WifiAwareNetworkSpecifier(WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB, WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, clientId, 0, 0, new byte[6], null, null, 10, 5, 0); diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index db8220b41910..7bc5f6260816 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -1570,7 +1570,7 @@ public class WifiAwareManagerTest { public void testWifiAwareNetworkCapabilitiesParcel() throws UnknownHostException { final Inet6Address inet6 = MacAddress.fromString( "11:22:33:44:55:66").getLinkLocalIpv6FromEui48Mac(); - // note: dummy scope = 5 + // note: placeholder scope = 5 final Inet6Address inet6Scoped = Inet6Address.getByAddress(null, inet6.getAddress(), 5); final int port = 5; final int transportProtocol = 6; |