diff options
109 files changed, 2348 insertions, 699 deletions
diff --git a/Android.bp b/Android.bp index 891ee91f7ed9..670860bb2c51 100644 --- a/Android.bp +++ b/Android.bp @@ -520,24 +520,22 @@ gensrcs { name: "framework-javastream-protos", depfile: true, - tool_files: ["tools/genprotos.sh"], tools: [ "aprotoc", "protoc-gen-javastream", "soong_zip", ], - // TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can - // end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to - // the way sbox rewrites the command. See b/70221552. - cmd: "$(location tools/genprotos.sh) " + - " $(location aprotoc) " + - " $(location protoc-gen-javastream) " + - " $(location soong_zip) " + - " $(genDir) " + - " $(depfile) " + - " $(in) " + - " $(out)", + cmd: "mkdir -p $(genDir)/$(in) " + + "&& $(location aprotoc) " + + " --plugin=$(location protoc-gen-javastream) " + + " --dependency_out=$(depfile) " + + " --javastream_out=$(genDir)/$(in) " + + " -Iexternal/protobuf/src " + + " -I . " + + " $(in) " + + "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)", + srcs: [ "core/proto/**/*.proto", "libs/incident/**/*.proto", @@ -865,28 +863,6 @@ python_binary_host { ], } -// TODO: Don't rely on this list by switching package.html into package-info.java -frameworks_base_subdirs = [ - "core/java", - "graphics/java", - "location/java", - "media/java", - "media/mca/effect/java", - "media/mca/filterfw/java", - "media/mca/filterpacks/java", - "drm/java", - "mms/java", - "opengl/java", - "sax/java", - "telecomm/java", - "telephony/common", - "telephony/java", - "wifi/java", - "lowpan/java", - "keystore/java", - "rs/java", -] - // Make the api/current.txt file available for use by modules in other // directories. filegroup { @@ -998,7 +974,6 @@ stubs_defaults { "test-runner/src/**/*.java", ], libs: framework_docs_only_libs, - local_sourcepaths: frameworks_base_subdirs, create_doc_stubs: true, annotations_enabled: true, api_levels_annotations_enabled: true, @@ -1059,7 +1034,6 @@ stubs_defaults { ":updatable-media-srcs", ], libs: ["framework-internal-utils"], - local_sourcepaths: frameworks_base_subdirs, installable: false, annotations_enabled: true, previous_api: ":last-released-public-api", diff --git a/api/current.txt b/api/current.txt index 19fd711f1f44..4ba4fbee7b15 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2023,7 +2023,7 @@ package android { field public static final int fingerprint_icon_content_description = 17039384; // 0x1040018 field public static final int httpErrorBadUrl = 17039367; // 0x1040007 field public static final int httpErrorUnsupportedScheme = 17039368; // 0x1040008 - field public static final int no = 17039369; // 0x1040009 + field @Deprecated public static final int no = 17039369; // 0x1040009 field public static final int ok = 17039370; // 0x104000a field public static final int paste = 17039371; // 0x104000b field public static final int paste_as_plain_text = 17039385; // 0x1040019 @@ -2033,7 +2033,7 @@ package android { field public static final int status_bar_notification_info_overflow = 17039383; // 0x1040017 field public static final int unknownName = 17039374; // 0x104000e field public static final int untitled = 17039375; // 0x104000f - field public static final int yes = 17039379; // 0x1040013 + field @Deprecated public static final int yes = 17039379; // 0x1040013 } public static final class R.style { @@ -3021,9 +3021,9 @@ package android.accounts { field public final String type; } - public class AccountAuthenticatorActivity extends android.app.Activity { - ctor public AccountAuthenticatorActivity(); - method public final void setAccountAuthenticatorResult(android.os.Bundle); + @Deprecated public class AccountAuthenticatorActivity extends android.app.Activity { + ctor @Deprecated public AccountAuthenticatorActivity(); + method @Deprecated public final void setAccountAuthenticatorResult(android.os.Bundle); } public class AccountAuthenticatorResponse implements android.os.Parcelable { @@ -34548,8 +34548,8 @@ package android.os { } public class Handler { - ctor public Handler(); - ctor public Handler(@Nullable android.os.Handler.Callback); + ctor @Deprecated public Handler(); + ctor @Deprecated public Handler(@Nullable android.os.Handler.Callback); ctor public Handler(@NonNull android.os.Looper); ctor public Handler(@NonNull android.os.Looper, @Nullable android.os.Handler.Callback); method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper); @@ -43520,6 +43520,7 @@ package android.telecom { field public static final int LOCAL = 2; // 0x2 field public static final int MISSED = 5; // 0x5 field public static final int OTHER = 9; // 0x9 + field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; field public static final int REJECTED = 6; // 0x6 field public static final int REMOTE = 3; // 0x3 field public static final int RESTRICTED = 8; // 0x8 @@ -44048,6 +44049,7 @@ package android.telephony { field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; field public static final String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool"; + field public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = "allow_hold_call_during_emergency_bool"; field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool"; field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool"; field public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; @@ -44064,7 +44066,7 @@ package android.telephony { field public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings"; field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT = "carrier_default_wfc_ims_mode_int"; field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT = "carrier_default_wfc_ims_roaming_mode_int"; - field public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; + field @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; field public static final String KEY_CARRIER_IMS_GBA_REQUIRED_BOOL = "carrier_ims_gba_required_bool"; field public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL = "carrier_instant_lettering_available_bool"; field public static final String KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING = "carrier_instant_lettering_encoding_string"; diff --git a/api/removed.txt b/api/removed.txt index b947918dc757..a4ccfb6db128 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -595,10 +595,6 @@ package android.provider { field public static final String VOLUME_VOICE = "volume_voice"; } - public static final class Telephony.Sms.Intents { - field public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; - } - } package android.speech.tts { diff --git a/api/system-current.txt b/api/system-current.txt index 2a8fb6341da3..341dd6faeb6f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -66,6 +66,7 @@ package android { field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER"; field public static final String DEVICE_POWER = "android.permission.DEVICE_POWER"; field public static final String DISPATCH_PROVISIONING_MESSAGE = "android.permission.DISPATCH_PROVISIONING_MESSAGE"; + field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED"; field public static final String FORCE_BACK = "android.permission.FORCE_BACK"; field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS"; @@ -74,6 +75,7 @@ package android { field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO"; field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"; field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS"; + field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES"; field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST"; field public static final String HDMI_CEC = "android.permission.HDMI_CEC"; field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"; @@ -602,6 +604,15 @@ package android.app { method public boolean isStatusBarExpansionDisabled(); } + public class UiModeManager { + method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int); + field public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = "android.app.action.ENTER_CAR_MODE_PRIORITIZED"; + field public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = "android.app.action.EXIT_CAR_MODE_PRIORITIZED"; + field public static final int DEFAULT_PRIORITY = 0; // 0x0 + field public static final String EXTRA_CALLING_PACKAGE = "android.app.extra.CALLING_PACKAGE"; + field public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY"; + } + public final class Vr2dDisplayProperties implements android.os.Parcelable { ctor public Vr2dDisplayProperties(int, int, int); method public int describeContents(); @@ -1239,7 +1250,9 @@ package android.bluetooth { public final class BluetoothAdapter { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean disableBLE(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean enableBLE(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean enableNoAutoConnect(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean factoryReset(); @@ -1746,6 +1759,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 + field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; field @StringRes public int requestRes; @@ -5668,14 +5682,6 @@ package android.os.storage { } -package android.os.telephony { - - public class TelephonyRegistryManager { - method public void notifyCarrierNetworkChange(boolean); - } - -} - package android.permission { public final class PermissionControllerManager { @@ -6144,6 +6150,10 @@ package android.provider { field public static final String SLOT_INDEX = "slot_index"; } + public static final class Telephony.Sms.Intents { + field public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = "android.provider.action.SMS_EMERGENCY_CB_RECEIVED"; + } + public final class TimeZoneRulesDataContract { field public static final String AUTHORITY = "com.android.timezone"; } @@ -7315,6 +7325,21 @@ package android.telephony { method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int); } + public class CbGeoUtils { + } + + public static interface CbGeoUtils.Geometry { + method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); + } + + public static class CbGeoUtils.LatLng { + ctor public CbGeoUtils.LatLng(double, double); + method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng); + method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng); + field public final double lat; + field public final double lng; + } + public abstract class CellBroadcastService extends android.app.Service { ctor public CellBroadcastService(); method @CallSuper @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent); @@ -7738,6 +7763,7 @@ package android.telephony { field public static final int NUMBER_UNREACHABLE = 8; // 0x8 field public static final int OTASP_PROVISIONING_IN_PROCESS = 76; // 0x4c field public static final int OUTGOING_CANCELED = 44; // 0x2c + field public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; // 0x50 field public static final int OUTGOING_FAILURE = 43; // 0x2b field public static final int OUT_OF_NETWORK = 11; // 0xb field public static final int OUT_OF_SERVICE = 18; // 0x12 @@ -8127,6 +8153,7 @@ package android.telephony { method public int getGeographicalScope(); method @Nullable public String getLanguageCode(); method @NonNull public android.telephony.SmsCbLocation getLocation(); + method public int getMaximumWaitingDuration(); method @Nullable public String getMessageBody(); method public int getMessageFormat(); method public int getMessagePriority(); @@ -8278,7 +8305,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetherApnRequired(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetheringApnRequired(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); method public boolean needsOtaServiceProvisioning(); @@ -8362,6 +8389,15 @@ package android.telephony { field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 } + public class TelephonyRegistryManager { + method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor); + method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyCallStateChangedForAllSubscriptions(int, @Nullable String); + method public void notifyCarrierNetworkChange(boolean); + method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); + method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + } + public final class UiccAccessRule implements android.os.Parcelable { ctor public UiccAccessRule(byte[], @Nullable String, long); method public int describeContents(); @@ -8894,7 +8930,7 @@ package android.telephony.ims { public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting(); diff --git a/api/test-current.txt b/api/test-current.txt index 1f310c33383c..eaf1fd793750 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -376,6 +376,7 @@ package android.app { } public class UiModeManager { + method @RequiresPermission("android.permission.ENTER_CAR_MODE_PRIORITIZED") public void enableCarMode(@IntRange(from=0) int, int); method public boolean isNightModeLocked(); method public boolean isUiModeLocked(); } @@ -707,6 +708,7 @@ package android.content.pm { method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS", "android.permission.GET_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @NonNull public abstract String getServicesSystemSharedLibraryPackageName(); method @NonNull public abstract String getSharedSystemSharedLibraryPackageName(); + method @Nullable public String[] getTelephonyPackageNames(); method @Nullable public String getWellbeingPackageName(); method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); @@ -739,6 +741,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 + field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000 field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; @@ -3228,7 +3231,7 @@ package android.telephony.ims { public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting(); diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index 25cd342cb5e9..6470a04aefd6 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -103,8 +103,6 @@ import java.util.Arrays; * When writing an activity to satisfy these requests one must pass in the AccountManagerResponse * and return the result via that response when the activity finishes (or whenever else the * activity author deems it is the correct time to respond). - * The {@link AccountAuthenticatorActivity} handles this, so one may wish to extend that when - * writing activities to handle these requests. */ public abstract class AbstractAccountAuthenticator { private static final String TAG = "AccountAuthenticator"; diff --git a/core/java/android/accounts/AccountAuthenticatorActivity.java b/core/java/android/accounts/AccountAuthenticatorActivity.java index 967aa0424b1d..65ba35ff9e8d 100644 --- a/core/java/android/accounts/AccountAuthenticatorActivity.java +++ b/core/java/android/accounts/AccountAuthenticatorActivity.java @@ -32,7 +32,11 @@ import android.os.Bundle; * This result will be sent as the result of the request when the activity finishes. If this * is never set or if it is set to null then error {@link AccountManager#ERROR_CODE_CANCELED} * will be called on the response. + * + * @deprecated Applications should extend Activity themselves. This class is not compatible with + * AppCompat, and the functionality it provides is not complex. */ +@Deprecated public class AccountAuthenticatorActivity extends Activity { private AccountAuthenticatorResponse mAccountAuthenticatorResponse = null; private Bundle mResultBundle = null; diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 360be350601d..835769f69951 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -3121,6 +3121,15 @@ public class ApplicationPackageManager extends PackageManager { } @Override + public String[] getTelephonyPackageNames() { + try { + return mPM.getTelephonyPackageNames(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + @Override public String getSystemCaptionsServicePackageName() { try { return mPM.getSystemCaptionsServicePackageName(); diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl index f2c9f615c03f..a3e0845af0ce 100644 --- a/core/java/android/app/IUiModeManager.aidl +++ b/core/java/android/app/IUiModeManager.aidl @@ -25,7 +25,7 @@ interface IUiModeManager { * Enables the car mode. Only the system can do this. * @hide */ - void enableCarMode(int flags); + void enableCarMode(int flags, int priority, String callingPackage); /** * Disables the car mode. @@ -34,6 +34,12 @@ interface IUiModeManager { void disableCarMode(int flags); /** + * Disables car mode (the original version is marked unsupported app usage so cannot be changed + * for the time being). + */ + void disableCarModeByCallingPackage(int flags, String callingPackage); + + /** * Return the current running mode. */ int getCurrentModeType(); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index dd39376f80ca..903dd493d187 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1638,7 +1638,7 @@ public class NotificationManager { @Override public int hashCode() { return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders, - suppressedVisualEffects); + suppressedVisualEffects, state); } @Override @@ -1650,10 +1650,10 @@ public class NotificationManager { && other.priorityCallSenders == priorityCallSenders && other.priorityMessageSenders == priorityMessageSenders && suppressedVisualEffectsEqual(suppressedVisualEffects, - other.suppressedVisualEffects); + other.suppressedVisualEffects) + && other.state == this.state; } - private boolean suppressedVisualEffectsEqual(int suppressedEffects, int otherSuppressedVisualEffects) { if (suppressedEffects == otherSuppressedVisualEffects) { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 46a128a2cd01..29cb3c1f131b 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -157,7 +157,7 @@ import android.os.health.SystemHealthManager; import android.os.image.DynamicSystemManager; import android.os.image.IDynamicSystemService; import android.os.storage.StorageManager; -import android.os.telephony.TelephonyRegistryManager; +import android.telephony.TelephonyRegistryManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; @@ -611,7 +611,7 @@ final class SystemServiceRegistry { new CachedServiceFetcher<TelephonyRegistryManager>() { @Override public TelephonyRegistryManager createService(ContextImpl ctx) { - return new TelephonyRegistryManager(); + return new TelephonyRegistryManager(ctx); }}); registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class, @@ -653,7 +653,7 @@ final class SystemServiceRegistry { new CachedServiceFetcher<UiModeManager>() { @Override public UiModeManager createService(ContextImpl ctx) throws ServiceNotFoundException { - return new UiModeManager(); + return new UiModeManager(ctx.getOuterContext()); }}); registerService(Context.USB_SERVICE, UsbManager.class, diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 46316e1a254b..83247875c8a5 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -17,6 +17,10 @@ package android.app; import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -68,6 +72,25 @@ public class UiModeManager { * of the broadcast to {@link Activity#RESULT_CANCELED}. */ public static String ACTION_ENTER_CAR_MODE = "android.app.action.ENTER_CAR_MODE"; + + /** + * Broadcast sent when the device's UI has switched to car mode, either by being placed in a car + * dock or explicit action of the user. + * <p> + * In addition to the behavior for {@link #ACTION_ENTER_CAR_MODE}, this broadcast includes the + * package name of the app which requested to enter car mode in the + * {@link #EXTRA_CALLING_PACKAGE}. If an app requested to enter car mode using + * {@link #enableCarMode(int, int)} and specified a priority this will be specified in the + * {@link #EXTRA_PRIORITY}. + * + * This is primarily intended to be received by other components of the Android OS. + * <p> + * Receiver requires permission: {@link android.Manifest.permission.HANDLE_CAR_MODE_CHANGES} + * @hide + */ + @SystemApi + public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = + "android.app.action.ENTER_CAR_MODE_PRIORITIZED"; /** * Broadcast sent when the device's UI has switch away from car mode back @@ -75,6 +98,28 @@ public class UiModeManager { * when the user exits car mode. */ public static String ACTION_EXIT_CAR_MODE = "android.app.action.EXIT_CAR_MODE"; + + /** + * Broadcast sent when the device's UI has switched away from car mode back to normal mode. + * Typically used by a car mode app, to dismiss itself when the user exits car mode. + * <p> + * In addition to the behavior for {@link #ACTION_EXIT_CAR_MODE}, this broadcast includes the + * package name of the app which requested to exit car mode in {@link #EXTRA_CALLING_PACKAGE}. + * If an app requested to enter car mode using {@link #enableCarMode(int, int)} and specified a + * priority this will be specified in the {@link #EXTRA_PRIORITY} when exiting car mode. + * <p> + * If {@link #DISABLE_CAR_MODE_ALL_PRIORITIES} is used when disabling car mode (i.e. this is + * initiated by the user via the persistent car mode notification), this broadcast is sent once + * for each priority level for which car mode is being disabled. + * <p> + * This is primarily intended to be received by other components of the Android OS. + * <p> + * Receiver requires permission: {@link android.Manifest.permission.HANDLE_CAR_MODE_CHANGES} + * @hide + */ + @SystemApi + public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = + "android.app.action.EXIT_CAR_MODE_PRIORITIZED"; /** * Broadcast sent when the device's UI has switched to desk mode, @@ -97,6 +142,24 @@ public class UiModeManager { */ public static String ACTION_EXIT_DESK_MODE = "android.app.action.EXIT_DESK_MODE"; + /** + * String extra used with {@link #ACTION_ENTER_CAR_MODE_PRIORITIZED} and + * {@link #ACTION_EXIT_CAR_MODE_PRIORITIZED} to indicate the package name of the app which + * requested to enter or exit car mode. + * @hide + */ + @SystemApi + public static final String EXTRA_CALLING_PACKAGE = "android.app.extra.CALLING_PACKAGE"; + + /** + * Integer extra used with {@link #ACTION_ENTER_CAR_MODE_PRIORITIZED} and + * {@link #ACTION_EXIT_CAR_MODE_PRIORITIZED} to indicate the priority level at which car mode + * is being disabled. + * @hide + */ + @SystemApi + public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY"; + /** @hide */ @IntDef(prefix = { "MODE_" }, value = { MODE_NIGHT_AUTO, @@ -126,10 +189,21 @@ public class UiModeManager { private IUiModeManager mService; + /** + * Context required for getting the opPackageName of API caller; maybe be {@code null} if the + * old constructor marked with UnSupportedAppUsage is used. + */ + private @Nullable Context mContext; + @UnsupportedAppUsage /*package*/ UiModeManager() throws ServiceNotFoundException { + this(null /* context */); + } + + /*package*/ UiModeManager(Context context) throws ServiceNotFoundException { mService = IUiModeManager.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE)); + mContext = context; } /** @@ -152,6 +226,14 @@ public class UiModeManager { */ public static final int ENABLE_CAR_MODE_ALLOW_SLEEP = 0x0002; + /** @hide */ + @IntDef(prefix = { "ENABLE_CAR_MODE_" }, value = { + ENABLE_CAR_MODE_GO_CAR_HOME, + ENABLE_CAR_MODE_ALLOW_SLEEP + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EnableCarMode {} + /** * Force device into car mode, like it had been placed in the car dock. * This will cause the device to switch to the car home UI as part of @@ -159,9 +241,54 @@ public class UiModeManager { * @param flags Must be 0. */ public void enableCarMode(int flags) { + enableCarMode(DEFAULT_PRIORITY, flags); + } + + /** + * Force device into car mode, like it had been placed in the car dock. This will cause the + * device to switch to the car home UI as part of the mode switch. + * <p> + * An app may request to enter car mode when the system is already in car mode. The app may + * specify a "priority" when entering car mode. The device will remain in car mode + * (i.e. {@link #getCurrentModeType()} is {@link Configuration#UI_MODE_TYPE_CAR}) as long as + * there is a priority level at which car mode have been enabled. For example assume app A + * enters car mode at priority level 100, and then app B enters car mode at the default priority + * (0). If app A exits car mode, the device will remain in car mode until app B exits car mode. + * <p> + * Specifying a priority level when entering car mode is important in cases where multiple apps + * on a device implement a car-mode {@link android.telecom.InCallService} (see + * {@link android.telecom.TelecomManager#METADATA_IN_CALL_SERVICE_CAR_MODE_UI}). The + * {@link android.telecom.InCallService} associated with the highest priority app which entered + * car mode will be bound to by Telecom and provided with information about ongoing calls on + * the device. + * <p> + * System apps holding the required permission can enable car mode when the app determines the + * correct conditions exist for that app to be in car mode. The device maker should ensure that + * where multiple apps exist on the device which can potentially enter car mode, appropriate + * priorities are used to ensure that calls delivered by the + * {@link android.telecom.InCallService} API are delivered to the highest priority app. + * If app A and app B can both potentially enable car mode, and it is desired that app B is the + * one which should receive call information, the priority for app B should be higher than the + * one for app A. + * <p> + * When an app uses a priority to enable car mode, they can disable car mode at the specified + * priority level using {@link #disableCarMode(int)}. An app may only enable car mode at a + * single priority. + * <p> + * Public apps are assumed to enter/exit car mode at {@link #DEFAULT_PRIORITY}. + * + * @param priority The declared priority for the caller. + * @param flags Car mode flags. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) + public void enableCarMode(@IntRange(from = 0) int priority, @EnableCarMode int flags) { if (mService != null) { try { - mService.enableCarMode(flags); + mService.enableCarMode(flags, priority, + mContext == null ? null : mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -176,15 +303,44 @@ public class UiModeManager { * being in car mode). */ public static final int DISABLE_CAR_MODE_GO_HOME = 0x0001; + + /** + * Flag for use with {@link #disableCarMode(int)}: Disables car mode at ALL priority levels. + * Primarily intended for use from {@link com.android.internal.app.DisableCarModeActivity} to + * provide the user with a means to exit car mode at all priority levels. + * @hide + */ + public static final int DISABLE_CAR_MODE_ALL_PRIORITIES = 0x0002; + + /** @hide */ + @IntDef(prefix = { "DISABLE_CAR_MODE_" }, value = { + DISABLE_CAR_MODE_GO_HOME + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DisableCarMode {} + + /** + * The default priority used for entering car mode. + * <p> + * Callers of the {@link UiModeManager#enableCarMode(int)} priority will be assigned the + * default priority. + * <p> + * System apps can specify a priority other than the default priority when using + * {@link UiModeManager#enableCarMode(int, int)} to enable car mode. + * @hide + */ + @SystemApi + public static final int DEFAULT_PRIORITY = 0; /** * Turn off special mode if currently in car mode. - * @param flags May be 0 or {@link #DISABLE_CAR_MODE_GO_HOME}. + * @param flags One of the disable car mode flags. */ - public void disableCarMode(int flags) { + public void disableCarMode(@DisableCarMode int flags) { if (mService != null) { try { - mService.disableCarMode(flags); + mService.disableCarModeByCallingPackage(flags, + mContext == null ? null : mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 566b38738dc1..9d152a7faf44 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1734,6 +1734,56 @@ public final class BluetoothAdapter { } /** + * Connects all enabled and supported bluetooth profiles between the local and remote device + * + * @param device is the remote device with which to connect these profiles + * @return true if all profiles successfully connected, false if an error occurred + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.connectAllEnabledProfiles(device); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + return false; + } + + /** + * Disconnects all enabled and supported bluetooth profiles between the local and remote device + * + * @param device is the remote device with which to disconnect these profiles + * @return true if all profiles successfully disconnected, false if an error occurred + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.disconnectAllEnabledProfiles(device); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + return false; + } + + /** * Return true if the multi advertisement is supported by the chipset * * @return true if Multiple Advertisement feature is supported diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index dabe0fdac39a..f5aa01458481 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -324,4 +324,54 @@ public interface BluetoothProfile { return "STATE_UNKNOWN"; } } + + /** + * Convert an integer value of profile ID into human readable string + * + * @param profile profile ID + * @return profile name as String, UNKOWN_PROFILE if the profile ID is not defined. + * @hide + */ + static String getProfileName(int profile) { + switch(profile) { + case HEADSET: + return "HEADSET"; + case A2DP: + return "A2DP"; + case HID_HOST: + return "HID_HOST"; + case PAN: + return "PAN"; + case PBAP: + return "PBAP"; + case GATT: + return "GATT"; + case GATT_SERVER: + return "GATT_SERVER"; + case MAP: + return "MAP"; + case SAP: + return "SAP"; + case A2DP_SINK: + return "A2DP_SINK"; + case AVRCP_CONTROLLER: + return "AVRCP_CONTROLLER"; + case AVRCP: + return "AVRCP"; + case HEADSET_CLIENT: + return "HEADSET_CLIENT"; + case PBAP_CLIENT: + return "PBAP_CLIENT"; + case MAP_CLIENT: + return "MAP_CLIENT"; + case HID_DEVICE: + return "HID_DEVICE"; + case OPP: + return "OPP"; + case HEARING_AID: + return "HEARING_AID"; + default: + return "UNKNOWN_PROFILE"; + } + } } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a3b918d095e0..a12e4da6e23e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -63,6 +63,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.MediaStore; +import android.telephony.TelephonyRegistryManager; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayAdjustments; @@ -4747,7 +4748,7 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve an - * {@link android.os.telephony.TelephonyRegistryManager}. + * {@link TelephonyRegistryManager}. * @hide */ @SystemApi diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a7eecd7f4306..7538dca76d18 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -753,6 +753,8 @@ interface IPackageManager { String getWellbeingPackageName(); + String[] getTelephonyPackageNames(); + String getAppPredictionServicePackageName(); String getSystemCaptionsServicePackageName(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a93297e9d51b..81670cd0d2b8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -7368,6 +7368,18 @@ public abstract class PackageManager { } /** + * @return the system defined telephony package names, or null if there's none. + * + * @hide + */ + @Nullable + @TestApi + public String[] getTelephonyPackageNames() { + throw new UnsupportedOperationException( + "getTelephonyPackageNames not implemented in subclass"); + } + + /** * @return the system defined content capture service package name, or null if there's none. * * @hide diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 672994e79134..30a3bd4d0738 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -59,6 +59,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_CONFIGURATOR = 9; public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10; public static final int PACKAGE_APP_PREDICTOR = 11; + public static final int PACKAGE_TELEPHONY = 12; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, @@ -72,6 +73,7 @@ public abstract class PackageManagerInternal { PACKAGE_CONFIGURATOR, PACKAGE_INCIDENT_REPORT_APPROVER, PACKAGE_APP_PREDICTOR, + PACKAGE_TELEPHONY, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} @@ -413,6 +415,17 @@ public abstract class PackageManagerInternal { @ResolveInfoFlags int flags, int filterCallingUid, int userId); /** + * Retrieve all activities that can be performed for the given intent. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#queryIntentActivities(Intent, int) + */ + public abstract List<ResolveInfo> queryIntentActivities( + Intent intent, @Nullable String resolvedType, @ResolveInfoFlags int flags, + int filterCallingUid, int userId); + + + /** * Retrieve all services that can be performed for the given intent. * @see PackageManager#queryIntentServices(Intent, int) */ @@ -715,10 +728,11 @@ public abstract class PackageManagerInternal { */ public abstract boolean isResolveActivityComponent(@NonNull ComponentInfo component); + /** - * Returns the package name for a known package. + * Returns a list of package names for a known package */ - public abstract @Nullable String getKnownPackageName( + public abstract @NonNull String[] getKnownPackageNames( @KnownPackage int knownPackage, int userId); /** diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index dd5c6a53cc20..c77c53f387e2 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -237,6 +237,17 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @TestApi public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000; + /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the <code>telephony</code> value of + * {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + @TestApi + public static final int PROTECTION_FLAG_TELEPHONY = 0x400000; + /** @hide */ @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { PROTECTION_FLAG_PRIVILEGED, @@ -258,6 +269,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_CONFIGURATOR, PROTECTION_FLAG_INCIDENT_REPORT_APPROVER, PROTECTION_FLAG_APP_PREDICTOR, + PROTECTION_FLAG_TELEPHONY, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionFlags {} @@ -501,6 +513,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) { protLevel += "|appPredictor"; } + if ((level & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0) { + protLevel += "|telephony"; + } return protLevel; } diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 5bc9953e0d05..990c1142284c 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -25,6 +25,8 @@ import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + import java.net.InetAddress; import java.util.ArrayList; import java.util.List; @@ -152,6 +154,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) { + Preconditions.checkNotNull(dnsServers); mDnsServers = dnsServers; return this; } @@ -175,8 +178,10 @@ public final class StaticIpConfiguration implements Parcelable { final StaticIpConfiguration config = new StaticIpConfiguration(); config.ipAddress = mIpAddress; config.gateway = mGateway; - for (InetAddress server : mDnsServers) { - config.dnsServers.add(server); + if (mDnsServers != null) { + for (InetAddress server : mDnsServers) { + config.dnsServers.add(server); + } } config.domains = mDomains; return config; diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java index 4e88149b8095..aa0f6220036c 100644 --- a/core/java/android/net/util/MultinetworkPolicyTracker.java +++ b/core/java/android/net/util/MultinetworkPolicyTracker.java @@ -94,7 +94,8 @@ public class MultinetworkPolicyTracker { } }; - TelephonyManager.from(ctx).listen(new PhoneStateListener(handler.getLooper()) { + ctx.getSystemService(TelephonyManager.class).listen( + new PhoneStateListener(handler.getLooper()) { @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveSubId = subId; diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index 9af9edae9a3f..a99bdabee137 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -28,15 +28,14 @@ import java.lang.reflect.Modifier; * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}. Each Handler * instance is associated with a single thread and that thread's message - * queue. When you create a new Handler, it is bound to the thread / - * message queue of the thread that is creating it -- from that point on, - * it will deliver messages and runnables to that message queue and execute - * them as they come out of the message queue. - * + * queue. When you create a new Handler it is bound to a {@link Looper}. + * It will deliver messages and runnables to that Looper's message + * queue and execute them on that Looper's thread. + * * <p>There are two main uses for a Handler: (1) to schedule messages and * runnables to be executed at some point in the future; and (2) to enqueue * an action to be performed on a different thread than your own. - * + * * <p>Scheduling messages is accomplished with the * {@link #post}, {@link #postAtTime(Runnable, long)}, * {@link #postDelayed}, {@link #sendEmptyMessage}, @@ -114,7 +113,18 @@ public class Handler { * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. + * + * @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs + * where operations are silently lost (if the Handler is not expecting new tasks and quits), + * crashes (if a handler is sometimes created on a thread without a Looper active), or race + * conditions, where the thread a handler is associated with is not what the author + * anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper + * explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or + * similar. If the implicit thread local behavior is required for compatibility, use + * {@code new Handler(Looper.myLooper())} to make it clear to readers. + * */ + @Deprecated public Handler() { this(null, false); } @@ -128,7 +138,17 @@ public class Handler { * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. - */ + * + * @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs + * where operations are silently lost (if the Handler is not expecting new tasks and quits), + * crashes (if a handler is sometimes created on a thread without a Looper active), or race + * conditions, where the thread a handler is associated with is not what the author + * anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper + * explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or + * similar. If the implicit thread local behavior is required for compatibility, use + * {@code new Handler(Looper.myLooper(), callback)} to make it clear to readers. + */ + @Deprecated public Handler(@Nullable Callback callback) { this(callback, false); } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 82a3c4015f70..391f3a2fd135 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -43,8 +43,6 @@ import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.Log; -import com.android.internal.telephony.PhoneConstants; - import java.util.List; /** @@ -610,7 +608,7 @@ public class CallLog { * if the contact is unknown. * @param context the context used to get the ContentResolver * @param number the phone number to be added to the calls db - * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which + * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which * is set by the network and denotes the number presenting rules for * "allowed", "payphone", "restricted" or "unknown" * @param callType enumerated values for "incoming", "outgoing", or "missed" @@ -645,7 +643,7 @@ public class CallLog { * @param number the phone number to be added to the calls db * @param viaNumber the secondary number that the incoming call received with. If the * call was received with the SIM assigned number, then this field must be ''. - * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which + * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which * is set by the network and denotes the number presenting rules for * "allowed", "payphone", "restricted" or "unknown" * @param callType enumerated values for "incoming", "outgoing", or "missed" @@ -686,7 +684,7 @@ public class CallLog { * if it was outgoing. Otherwise it is ''. * @param viaNumber the secondary number that the incoming call received with. If the * call was received with the SIM assigned number, then this field must be ''. - * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which + * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which * is set by the network and denotes the number presenting rules for * "allowed", "payphone", "restricted" or "unknown" * @param callType enumerated values for "incoming", "outgoing", or "missed" @@ -1048,22 +1046,22 @@ public class CallLog { /** * Remap network specified number presentation types - * PhoneConstants.PRESENTATION_xxx to calllog number presentation types + * TelecomManager.PRESENTATION_xxx to calllog number presentation types * Calls.PRESENTATION_xxx, in order to insulate the persistent calllog * from any future radio changes. * If the number field is empty set the presentation type to Unknown. */ private static int getLogNumberPresentation(String number, int presentation) { - if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) { + if (presentation == TelecomManager.PRESENTATION_RESTRICTED) { return presentation; } - if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) { + if (presentation == TelecomManager.PRESENTATION_PAYPHONE) { return presentation; } if (TextUtils.isEmpty(number) - || presentation == PhoneConstants.PRESENTATION_UNKNOWN) { + || presentation == TelecomManager.PRESENTATION_UNKNOWN) { return PRESENTATION_UNKNOWN; } diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java index 9184d6d51f44..eefc1b70bac9 100644 --- a/core/java/android/service/carrier/CarrierService.java +++ b/core/java/android/service/carrier/CarrierService.java @@ -22,7 +22,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; import android.os.ResultReceiver; -import android.os.telephony.TelephonyRegistryManager; +import android.telephony.TelephonyRegistryManager; import android.util.Log; /** diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index e5bfb4dfb7b4..2af827e36696 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -35,8 +35,8 @@ import android.telephony.Annotation.SrvccState; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.IPhoneStateListener; +import com.android.internal.annotations.VisibleForTesting; import dalvik.system.VMRuntime; diff --git a/telephony/java/android/telephony/Rlog.java b/core/java/android/telephony/Rlog.java index cdab2dc54dd2..cdab2dc54dd2 100644 --- a/telephony/java/android/telephony/Rlog.java +++ b/core/java/android/telephony/Rlog.java diff --git a/core/java/android/os/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index b67409988da0..456789fb77bc 100644 --- a/core/java/android/os/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -13,12 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.os.telephony; +package android.telephony; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.content.Context; import android.net.LinkProperties; import android.net.NetworkCapabilities; +import android.os.Binder; import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerExecutor; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.Annotation; @@ -41,8 +49,15 @@ import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; +import android.util.Log; + +import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.ITelephonyRegistry; + +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; /** * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update @@ -59,9 +74,26 @@ public class TelephonyRegistryManager { private static final String TAG = "TelephonyRegistryManager"; private static ITelephonyRegistry sRegistry; + private final Context mContext; + + /** + * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>(); + /** + * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap + = new HashMap<>(); + /** @hide **/ - public TelephonyRegistryManager() { + public TelephonyRegistryManager(@NonNull Context context) { + mContext = context; if (sRegistry == null) { sRegistry = ITelephonyRegistry.Stub.asInterface( ServiceManager.getService("telephony.registry")); @@ -69,6 +101,113 @@ public class TelephonyRegistryManager { } /** + * Register for changes to the list of active {@link SubscriptionInfo} records or to the + * individual records themselves. When a change occurs the onSubscriptionsChanged method of + * the listener will be invoked immediately if there has been a notification. The + * onSubscriptionChanged method will also be triggered once initially when calling this + * function. + * + * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener} + * with onSubscriptionsChanged overridden. + * @param executor the executor that will execute callbacks. + */ + public void addOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener, + @NonNull Executor executor) { + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged () { + Log.d(TAG, "onSubscriptionsChangedListener callback received."); + executor.execute(() -> listener.onSubscriptionsChanged()); + } + }; + mSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. This is not + * strictly necessary as the listener will automatically be unregistered if an attempt to + * invoke the listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) { + if (mSubscriptionChangedListenerMap.get(listener) == null) { + return; + } + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mSubscriptionChangedListenerMap.get(listener)); + mSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Register for changes to the list of opportunistic subscription records or to the + * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged + * method of the listener will be invoked immediately if there has been a notification. + * + * @param listener an instance of + * {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with + * onOpportunisticSubscriptionsChanged overridden. + * @param executor an Executor that will execute callbacks. + */ + public void addOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener, + @NonNull Executor executor) { + /** + * The callback methods need to be called on the executor thread where + * this object was created. If the binder did that for us it'd be nice. + */ + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged() { + final long identity = Binder.clearCallingIdentity(); + try { + Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received."); + executor.execute(() -> listener.onOpportunisticSubscriptionsChanged()); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }; + mOpportunisticSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(), + callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} + * that is currently listening opportunistic subscriptions change. This is not strictly + * necessary as the listener will automatically be unregistered if an attempt to invoke the + * listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) { + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mOpportunisticSubscriptionChangedListenerMap.get(listener)); + mOpportunisticSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** * Informs the system of an intentional upcoming carrier network change by a carrier app. * This call only used to allow the system to provide alternative UI while telephony is * performing an action that may result in intentional, temporary network lack of connectivity. @@ -98,14 +237,33 @@ public class TelephonyRegistryManager { * @param slotIndex for which call state changed. Can be derived from subId except when subId is * invalid. * @param state latest call state. e.g, offhook, ringing - * @param incomingNumer incoming phone number. + * @param incomingNumber incoming phone number. * * @hide */ public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state, - String incomingNumer) { + String incomingNumber) { try { - sRegistry.notifyCallState(slotIndex, subId, state, incomingNumer); + sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify call state changed on all subscriptions. + * + * @param state latest call state. e.g, offhook, ringing + * @param incomingNumber incoming phone number. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void notifyCallStateChangedForAllSubscriptions(@CallState int state, + @Nullable String incomingNumber) { + try { + sRegistry.notifyCallStateForAllSubs(state, incomingNumber); } catch (RemoteException ex) { // system server crash } @@ -545,4 +703,15 @@ public class TelephonyRegistryManager { } } + /** + * @param activeDataSubId + * @hide + */ + public void notifyActiveDataSubIdChanged(int activeDataSubId) { + try { + sRegistry.notifyActiveDataSubIdChanged(activeDataSubId); + } catch (RemoteException ex) { + + } + } } diff --git a/core/java/com/android/internal/app/DisableCarModeActivity.java b/core/java/com/android/internal/app/DisableCarModeActivity.java index 7943c613b357..d44312b716ba 100644 --- a/core/java/com/android/internal/app/DisableCarModeActivity.java +++ b/core/java/com/android/internal/app/DisableCarModeActivity.java @@ -33,7 +33,9 @@ public class DisableCarModeActivity extends Activity { try { IUiModeManager uiModeManager = IUiModeManager.Stub.asInterface( ServiceManager.getService("uimode")); - uiModeManager.disableCarMode(UiModeManager.DISABLE_CAR_MODE_GO_HOME); + uiModeManager.disableCarModeByCallingPackage(UiModeManager.DISABLE_CAR_MODE_GO_HOME + | UiModeManager.DISABLE_CAR_MODE_ALL_PRIORITIES, + getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Failed to disable car mode", e); } diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 5857642cbd4e..7dcb12c9e72b 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -133,7 +133,7 @@ interface IPlatformCompat boolean isChangeEnabledByUid(long changeId, int uid); /** - * Add overrides to compatibility changes. + * Add overrides to compatibility changes. Kills the app to allow the changes to take effect. * * @param overrides Parcelable containing the compat change overrides to be applied. * @param packageName The package name of the app whose changes will be overridden. @@ -142,7 +142,28 @@ interface IPlatformCompat void setOverrides(in CompatibilityChangeConfig overrides, in String packageName); /** - * Revert overrides to compatibility changes. + * Add overrides to compatibility changes. Doesn't kill the app, to be only used in tests. + * + * @param overrides Parcelable containing the compat change overrides to be applied. + * @param packageName The package name of the app whose changes will be overridden. + * + */ + void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName); + + /** + * Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig, + * String)}. This restores the default behaviour for the given change and app, once any app + * processes have been restarted. + * Kills the app to allow the changes to take effect. + * + * @param changeId The ID of the change that was overridden. + * @param packageName The app package name that was overridden. + * @return {@code true} if an override existed; + */ + boolean clearOverride(long changeId, String packageName); + + /** + * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect. * * @param packageName The package name of the app whose overrides will be cleared. * @@ -150,6 +171,15 @@ interface IPlatformCompat void clearOverrides(in String packageName); /** + * Revert overrides to compatibility changes. Doesn't kill the app, to be only used in tests. + * + * @param packageName The package name of the app whose overrides will be cleared. + * + */ + void clearOverridesForTest(in String packageName); + + + /** * Get configs for an application. * * @param appInfo The application whose config will be returned. diff --git a/core/java/com/android/internal/package-info.java b/core/java/com/android/internal/package-info.java new file mode 100644 index 000000000000..8a226dbdc9fe --- /dev/null +++ b/core/java/com/android/internal/package-info.java @@ -0,0 +1,4 @@ +/** + * @hide + */ +package com.android.internal; diff --git a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl index 493b1ff6aba7..493b1ff6aba7 100644 --- a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl +++ b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index 90019eef62fd..084a3cc64a35 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -29,6 +29,9 @@ import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; +/** + * {@hide} + */ oneway interface IPhoneStateListener { void onServiceStateChanged(in ServiceState serviceState); void onSignalStrengthChanged(int asu); diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index d7a7af1d530f..d7a7af1d530f 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9a90555041d7..9e4c2220576c 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -667,6 +667,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX]; + char dex2oatCpuSetBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX]; + char dex2oatCpuSetImageBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX]; char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; @@ -956,6 +958,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option"); parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j", "-Ximage-compiler-option"); + parseCompilerOption("dalvik.vm.dex2oat-cpu-set", dex2oatCpuSetBuf, "--cpu-set=", + "-Xcompiler-option"); + parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=", + "-Ximage-compiler-option"); // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to // pass the instruction-set-features/variant as an image-compiler-option. diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h index 16ef753c0cd0..f03f42737134 100644 --- a/core/jni/core_jni_helpers.h +++ b/core/jni/core_jni_helpers.h @@ -22,6 +22,18 @@ #include <nativehelper/scoped_utf_chars.h> #include <android_runtime/AndroidRuntime.h> +// Host targets (layoutlib) do not differentiate between regular and critical native methods, +// and they need all the JNI methods to have JNIEnv* and jclass/jobject as their first two arguments. +// The following macro allows to have those arguments when compiling for host while omitting them when +// compiling for Android. +#ifdef __ANDROID__ +#define CRITICAL_JNI_PARAMS +#define CRITICAL_JNI_PARAMS_COMMA +#else +#define CRITICAL_JNI_PARAMS JNIEnv*, jclass +#define CRITICAL_JNI_PARAMS_COMMA JNIEnv*, jclass, +#endif + namespace android { // Defines some helpful functions. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index b8c6cf64f9db..216b87f89b90 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -108,6 +108,8 @@ <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" /> + <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE_PRIVILEGED" /> + <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE_PRIVILEGED" /> <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" /> <protected-broadcast android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" /> @@ -1626,7 +1628,7 @@ @hide This should only be used by Settings and SystemUI. --> <permission android:name="android.permission.NETWORK_SETTINGS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows SetupWizard to call methods in Networking services <p>Not for use by any other third-party or privileged applications. @@ -2146,12 +2148,12 @@ <!-- Must be required by a telephony data service to ensure that only the system can bind to it. - <p>Protection level: signature + <p>Protection level: signature|telephony @SystemApi @hide --> <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Must be required by a NetworkService to ensure that only the system can bind to it. @@ -2172,11 +2174,11 @@ <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to it. - <p>Protection level: signature + <p>Protection level: signature|telephony @hide --> <permission android:name="android.permission.BIND_EUICC_SERVICE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- ================================== --> <!-- Permissions for sdcard interaction --> @@ -2956,7 +2958,7 @@ @hide --> <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- @SystemApi Allows an application to use {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} @@ -3736,7 +3738,7 @@ @hide --> <permission android:name="android.permission.DEVICE_POWER" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows toggling battery saver on the system. Superseded by DEVICE_POWER permission. @hide @SystemApi @@ -3771,13 +3773,13 @@ <p>Not for use by third-party applications. --> <permission android:name="android.permission.BROADCAST_SMS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows an application to broadcast a WAP PUSH receipt notification. <p>Not for use by third-party applications. --> <permission android:name="android.permission.BROADCAST_WAP_PUSH" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- @SystemApi Allows an application to broadcast privileged networking requests. <p>Not for use by third-party applications. @@ -4339,6 +4341,21 @@ it will be ignored. @hide --> <permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE" + android:protectionLevel="signature|privileged" /> + + <!-- @SystemApi Allows entering or exiting car mode using a specified priority. + This permission is required to use UiModeManager while specifying a priority for the calling + app. A device manufacturer uses this permission to prioritize the apps which can + potentially request to enter car-mode on a device to help establish the correct behavior + where multiple such apps are active at the same time. + @hide --> + <permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED" + android:protectionLevel="signature|privileged" /> + + <!-- @SystemApi Required to receive ACTION_ENTER_CAR_MODE_PRIVILEGED or + ACTION_EXIT_CAR_MODE_PRIVILEGED. + @hide --> + <permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES" android:protectionLevel="signature|privileged" /> <!-- The system process is explicitly the only one allowed to launch the @@ -4392,13 +4409,13 @@ {@link android.provider.BlockedNumberContract}. @hide --> <permission android:name="android.permission.READ_BLOCKED_NUMBERS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Allows the holder to write blocked numbers. See {@link android.provider.BlockedNumberContract}. @hide --> <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|telephony" /> <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only the system can bind to it. diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 77fca8fe4d8e..17045d812f4b 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -295,6 +295,9 @@ <!-- Additional flag from base permission type: this permission can be automatically granted to the system app predictor --> <flag name="appPredictor" value="0x200000" /> + <!-- Additional flag from base permission type: this permission can be automatically + granted to the system telephony apps --> + <flag name="telephony" value="0x400000" /> </attr> <!-- Flags indicating more context for a permission group. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 6c0fe46563c4..4b4baa9c1584 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -529,7 +529,7 @@ - TYPE_ETHERNET (9) is prepended to this list, and - - the return value of TelephonyManager.isTetherApnRequired() + - the return value of TelephonyManager.isTetheringApnRequired() determines how the array is further modified: * TRUE (DUN REQUIRED). @@ -3677,6 +3677,15 @@ --> <string name="config_defaultWellbeingPackage" translatable="false"></string> + + <!-- The package name for the system telephony apps. + This package must be trusted, as it will be granted with permissions with special telephony + protection level. Note, framework by default support multiple telephony apps, each package + name is separated by comma. + Example: "com.android.phone,com.android.stk,com.android.providers.telephony" + --> + <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string> + <!-- The component name for the default system attention service. This service must be trusted, as it can be activated without explicit consent of the user. See android.attention.AttentionManagerService. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6efa2d653b4c..e729b03c1b82 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3056,9 +3056,9 @@ <string name="ok">OK</string> <!-- Preference framework strings. --> <string name="cancel">Cancel</string> - <!-- Preference framework strings. --> + <!-- Preference framework strings. {@deprecated Do not use. Incorrectly matches android.R.string.ok rather than "yes".} --> <string name="yes">OK</string> - <!-- Preference framework strings. --> + <!-- Preference framework strings. {@deprecated Do not use. Incorrectly matches android.R.string.cancel rather than "no".} --> <string name="no">Cancel</string> <!-- This is the generic "attention" string to be used in attention dialogs. Typically combined with setIconAttribute(android.R.attr.alertDialogIcon) diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0804703a585b..e8cd271118dc 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3464,6 +3464,7 @@ <java-symbol type="string" name="config_defaultAutofillService" /> <java-symbol type="string" name="config_defaultTextClassifierPackage" /> <java-symbol type="string" name="config_defaultWellbeingPackage" /> + <java-symbol type="string" name="config_telephonyPackages" /> <java-symbol type="string" name="config_defaultContentCaptureService" /> <java-symbol type="string" name="config_defaultAugmentedAutofillService" /> <java-symbol type="string" name="config_defaultAppPredictionService" /> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 80f3cc68221f..9064abf6ba36 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -238,6 +238,7 @@ applications that come with the platform <permission name="android.permission.BIND_CONNECTION_SERVICE"/> <permission name="android.permission.BIND_INCALL_SERVICE"/> <permission name="android.permission.CALL_PRIVILEGED"/> + <permission name="android.permission.HANDLE_CAR_MODE_CHANGES"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.MANAGE_ROLE_HOLDERS"/> @@ -328,6 +329,8 @@ applications that come with the platform <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" /> <!-- Permission required to test ExplicitHealthCheckServiceImpl. --> <permission name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"/> + <!-- Permission required for UiModeManager cts test. --> + <permission name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 646aa13664c4..c0a04220cfe7 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -348,16 +348,6 @@ public class KeyStore { return list(prefix, UID_SELF); } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public boolean reset() { - try { - return mBinder.reset() == NO_ERROR; - } catch (RemoteException e) { - Log.w(TAG, "Cannot connect to keystore", e); - return false; - } - } - /** * Attempt to lock the keystore for {@code user}. * @@ -922,15 +912,26 @@ public class KeyStore { } } - public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature, - byte[] entropy) { + /** + * Android KeyStore finish operation. + * + * @param token Authentication token. + * @param arguments Keymaster arguments + * @param input Optional additional input data. + * @param signature Optional signature to be verified. + * @param entropy Optional additional entropy + * @return OperationResult that will indicate success or error of the operation. + */ + public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] input, + byte[] signature, byte[] entropy) { OperationPromise promise = new OperationPromise(); try { mBinder.asBinder().linkToDeath(promise, 0); arguments = arguments != null ? arguments : new KeymasterArguments(); entropy = entropy != null ? entropy : new byte[0]; + input = input != null ? input : new byte[0]; signature = signature != null ? signature : new byte[0]; - int errorCode = mBinder.finish(promise, token, arguments, signature, entropy); + int errorCode = mBinder.finish(promise, token, arguments, input, signature, entropy); if (errorCode == NO_ERROR) { return promise.getFuture().get(); } else { @@ -948,7 +949,7 @@ public class KeyStore { } public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { - return finish(token, arguments, signature, null); + return finish(token, arguments, null, signature, null); } private class KeystoreResultPromise diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java index 441ee660b53a..c6515efd2c61 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java @@ -432,7 +432,7 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC } @Override - public OperationResult finish(byte[] signature, byte[] additionalEntropy) { + public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) { if ((additionalEntropy != null) && (additionalEntropy.length > 0)) { throw new ProviderException("AAD stream does not support additional entropy"); } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index 3dc884eb38ad..17aacb9756aa 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -210,13 +210,9 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { } } if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { - if (mKeySizeBits < 64) { + if (mKeySizeBits < 64 || mKeySizeBits > 512) { throw new InvalidAlgorithmParameterException( - "HMAC key size must be at least 64 bits."); - } - if (mKeySizeBits > 512 && spec.isStrongBoxBacked()) { - throw new InvalidAlgorithmParameterException( - "StrongBox HMAC key size must be smaller than 512 bits."); + "HMAC key sizes must be within 64-512 bits, inclusive."); } // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java index e0304787142d..75bea26aecef 100644 --- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java @@ -62,7 +62,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS * Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't * be reached. */ - OperationResult finish(byte[] siganture, byte[] additionalEntropy); + OperationResult finish(byte[] input, byte[] siganture, byte[] additionalEntropy); } // Binder buffer is about 1MB, but it's shared between all active transactions of the process. @@ -217,7 +217,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS byte[] output = update(input, inputOffset, inputLength); output = ArrayUtils.concat(output, flush()); - OperationResult opResult = mKeyStoreStream.finish(signature, additionalEntropy); + OperationResult opResult = mKeyStoreStream.finish(EmptyArray.BYTE, signature, + additionalEntropy); if (opResult == null) { throw new KeyStoreConnectException(); } else if (opResult.resultCode != KeyStore.NO_ERROR) { @@ -334,8 +335,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS } @Override - public OperationResult finish(byte[] signature, byte[] additionalEntropy) { - return mKeyStore.finish(mOperationToken, null, signature, additionalEntropy); + public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) { + return mKeyStore.finish(mOperationToken, null, input, signature, additionalEntropy); } } } diff --git a/media/java/android/media/tv/OWNER b/media/java/android/media/tv/OWNERS index 64c0bb53e894..64c0bb53e894 100644 --- a/media/java/android/media/tv/OWNER +++ b/media/java/android/media/tv/OWNERS diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp index 8c38d887f82b..84a0e0d032d9 100644 --- a/media/jni/android_media_MediaDataSource.cpp +++ b/media/jni/android_media_MediaDataSource.cpp @@ -26,7 +26,6 @@ #include <nativehelper/JNIHelp.h> #include <binder/MemoryDealer.h> -#include <drm/drm_framework_common.h> #include <media/stagefright/foundation/ADebug.h> #include <nativehelper/ScopedLocalRef.h> @@ -160,8 +159,4 @@ String8 JMediaDataSource::toString() { return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid()); } -sp<DecryptHandle> JMediaDataSource::DrmInitialization(const char * /* mime */) { - return NULL; -} - } // namespace android diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h index 39405d2db579..378baf433fed 100644 --- a/media/jni/android_media_MediaDataSource.h +++ b/media/jni/android_media_MediaDataSource.h @@ -47,7 +47,6 @@ public: virtual void close(); virtual uint32_t getFlags(); virtual String8 toString(); - virtual sp<DecryptHandle> DrmInitialization(const char *mime); private: // Protect all member variables with mLock because this object will be diff --git a/packages/CtsShim/Android.bp b/packages/CtsShim/Android.bp new file mode 100644 index 000000000000..7728464f8652 --- /dev/null +++ b/packages/CtsShim/Android.bp @@ -0,0 +1,74 @@ +// +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//########################################################## +// Variant: Privileged app + +android_app_import { + name: "CtsShimPrivPrebuilt", + + // this needs to be a privileged application + privileged: true, + + // Make sure the build system doesn't try to resign the APK + dex_preopt: { + enabled: false, + }, + + arch: { + arm: { + apk: "apk/arm/CtsShimPriv.apk", + }, + arm64: { + apk: "apk/arm/CtsShimPriv.apk", + }, + x86: { + apk: "apk/x86/CtsShimPriv.apk", + }, + x86_64: { + apk: "apk/x86/CtsShimPriv.apk", + }, + }, + presigned: true, +} + +//########################################################## +// Variant: System app + +android_app_import { + name: "CtsShimPrebuilt", + + // Make sure the build system doesn't try to resign the APK + dex_preopt: { + enabled: false, + }, + + arch: { + arm: { + apk: "apk/arm/CtsShim.apk", + }, + arm64: { + apk: "apk/arm/CtsShim.apk", + }, + x86: { + apk: "apk/x86/CtsShim.apk", + }, + x86_64: { + apk: "apk/x86/CtsShim.apk", + }, + }, + presigned: true, +} diff --git a/packages/CtsShim/Android.mk b/packages/CtsShim/Android.mk deleted file mode 100644 index 12972f14514b..000000000000 --- a/packages/CtsShim/Android.mk +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -########################################################### -# Variant: Privileged app - -include $(CLEAR_VARS) - -LOCAL_MODULE := CtsShimPrivPrebuilt -LOCAL_MODULE_TAGS := optional -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MODULE_CLASS := APPS -LOCAL_BUILT_MODULE_STEM := package.apk -# Make sure the build system doesn't try to resign the APK -LOCAL_CERTIFICATE := PRESIGNED -LOCAL_DEX_PREOPT := false -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 - -LOCAL_SRC_FILES_arm := apk/arm/CtsShimPriv.apk -LOCAL_SRC_FILES_arm64 := apk/arm/CtsShimPriv.apk -LOCAL_SRC_FILES_x86 := apk/x86/CtsShimPriv.apk -LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShimPriv.apk - -include $(BUILD_PREBUILT) - - -########################################################### -# Variant: System app - -include $(CLEAR_VARS) - -LOCAL_MODULE := CtsShimPrebuilt -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := APPS -LOCAL_BUILT_MODULE_STEM := package.apk -# Make sure the build system doesn't try to resign the APK -LOCAL_CERTIFICATE := PRESIGNED -LOCAL_DEX_PREOPT := false -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 - -LOCAL_SRC_FILES_arm := apk/arm/CtsShim.apk -LOCAL_SRC_FILES_arm64 := apk/arm/CtsShim.apk -LOCAL_SRC_FILES_x86 := apk/x86/CtsShim.apk -LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShim.apk - -include $(BUILD_PREBUILT) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp new file mode 100644 index 000000000000..ede1fab64973 --- /dev/null +++ b/packages/CtsShim/build/Android.bp @@ -0,0 +1,117 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Build rules to build shim apks. + +//########################################################## +// Variant: Privileged app upgrade + +android_app { + name: "CtsShimPrivUpgrade", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: "shim_priv_upgrade/AndroidManifest.xml", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], +} + +genrule { + name: "generate_priv_manifest", + srcs: [ + "shim_priv/AndroidManifest.xml", + ":CtsShimPrivUpgrade" + ], + out: ["AndroidManifest.xml"], + cmd: "sed -e s/__HASH__/`sha512sum -b $(location :CtsShimPrivUpgrade) | cut -d' ' -f1`/ $(location shim_priv/AndroidManifest.xml) > $(out)", +} + +//########################################################## +// Variant: Privileged app + +android_app { + name: "CtsShimPriv", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: ":generate_priv_manifest", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], + // Explicitly uncompress native libs rather than letting the build system doing it and destroy the + // v2/v3 signature. + use_embedded_native_libs: true, +} + +//########################################################## +// Variant: Privileged app upgrade w/ the wrong SHA + +android_app { + name: "CtsShimPrivUpgradeWrongSHA", + // this needs to be a privileged application + privileged: true, + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + // anything to make this package's SHA different from CtsShimPrivUpgrade + aaptflags: [ + "--version-name", + "WrongSHA", + ], + + manifest: "shim_priv_upgrade/AndroidManifest.xml", + + compile_multilib: "both", + jni_libs: ["libshim_jni"], + +} + +//########################################################## +// Variant: System app + +android_app { + name: "CtsShim", + + sdk_version: "current", + optimize: { + enabled: false, + }, + dex_preopt: { + enabled: false, + }, + + manifest: "shim/AndroidManifest.xml", +} diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk deleted file mode 100644 index 03eb0d9aad5a..000000000000 --- a/packages/CtsShim/build/Android.mk +++ /dev/null @@ -1,116 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(my-dir) - -########################################################### -# Variant: Privileged app upgrade - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShimPrivUpgrade - -LOCAL_MANIFEST_FILE := shim_priv_upgrade/AndroidManifest.xml - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -include $(BUILD_PACKAGE) -my_shim_priv_upgrade_apk := $(LOCAL_BUILT_MODULE) - -########################################################### -# Variant: Privileged app - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShimPriv - -# Generate the upgrade key by taking the hash of the built CtsShimPrivUpgrade apk -gen := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,true)/AndroidManifest.xml -$(gen): PRIVATE_CUSTOM_TOOL = sed -e "s/__HASH__/`sha512sum $(PRIVATE_INPUT_APK) | cut -d' ' -f1`/" $< >$@ -$(gen): PRIVATE_INPUT_APK := $(my_shim_priv_upgrade_apk) -$(gen): $(LOCAL_PATH)/shim_priv/AndroidManifest.xml $(my_shim_priv_upgrade_apk) - $(transform-generated-source) - -my_shim_priv_upgrade_apk := - -LOCAL_FULL_MANIFEST_FILE := $(gen) - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -LOCAL_USE_AAPT2 := true - -include $(BUILD_PACKAGE) - -########################################################### -# Variant: Privileged app upgrade w/ the wrong SHA - -include $(CLEAR_VARS) -# this needs to be a privileged application -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false -# anything to make this package's SHA different from CtsShimPrivUpgrade -LOCAL_AAPT_FLAGS := --version-name WrongSHA - -LOCAL_PACKAGE_NAME := CtsShimPrivUpgradeWrongSHA - -LOCAL_MANIFEST_FILE := shim_priv_upgrade/AndroidManifest.xml - -LOCAL_MULTILIB := both -LOCAL_JNI_SHARED_LIBRARIES := libshim_jni - -include $(BUILD_PACKAGE) - - -########################################################### -# Variant: System app - -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := current -LOCAL_PROGUARD_ENABLED := disabled -LOCAL_DEX_PREOPT := false - -LOCAL_PACKAGE_NAME := CtsShim - -LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml - -LOCAL_USE_AAPT2 := true - -include $(BUILD_PACKAGE) - -########################################################### -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index ea3c1d95925c..092cbf3c7c12 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -222,7 +222,8 @@ public class DataUsageController { } } - return TelephonyManager.from(mContext).createForSubscriptionId(subscriptionId); + return mContext.getSystemService( + TelephonyManager.class).createForSubscriptionId(subscriptionId); } public void setMobileDataEnabled(boolean enabled) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java index 3da5e766c389..f7bee30a087f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java @@ -75,7 +75,7 @@ public class DataUsageControllerTest { public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) .thenReturn(mSubscriptionManager); when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 047ac5984fe3..13fc881624ec 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -207,6 +207,9 @@ <!-- Permission required for CTS test - CrossProfileAppsHostSideTest --> <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/> + <!-- Permission requried for CTS test - UiModeManagerTest --> + <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java index cf0e3b2ddda7..ca9b1681bacc 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -251,7 +251,7 @@ public class TetheringConfiguration { /** Check whether dun is required. */ public static boolean checkDunRequired(Context ctx, int id) { final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); - return (tm != null) ? tm.isTetherApnRequired(id) : false; + return (tm != null) ? tm.isTetheringApnRequired(id) : false; } private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java index 9c65c0deed07..30bff3560955 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java @@ -145,7 +145,7 @@ public class TetheringConfigurationTest { @Test public void testDunFromTelephonyManagerMeansDun() { - when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(true); + when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(true); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -169,7 +169,7 @@ public class TetheringConfigurationTest { @Test public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { - when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -212,7 +212,7 @@ public class TetheringConfigurationTest { @Test public void testNoDefinedUpstreamTypesAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{}); - when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -235,7 +235,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn( new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -253,7 +253,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { when(mResources.getIntArray(config_tether_upstream_types)) .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetherApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 30a356325ada..d1e4231f88b0 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -16,6 +16,7 @@ package com.android.server; +import android.annotation.IntRange; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; @@ -41,6 +42,7 @@ import android.os.Handler; import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.PowerManagerInternal; +import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -53,6 +55,7 @@ import android.provider.Settings.Secure; import android.service.dreams.Sandman; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; +import android.util.ArraySet; import android.util.Slog; import com.android.internal.R; @@ -66,6 +69,9 @@ import com.android.server.twilight.TwilightState; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; final class UiModeManagerService extends SystemService { private static final String TAG = UiModeManager.class.getSimpleName(); @@ -81,6 +87,7 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mNightMode = UiModeManager.MODE_NIGHT_NO; + private Map<Integer, String> mCarModePackagePriority = new HashMap<>(); private boolean mCarModeEnabled = false; private boolean mCharging = false; private boolean mPowerSave = false; @@ -338,15 +345,25 @@ final class UiModeManagerService extends SystemService { private final IUiModeManager.Stub mService = new IUiModeManager.Stub() { @Override - public void enableCarMode(int flags) { + public void enableCarMode(@UiModeManager.EnableCarMode int flags, + @IntRange(from = 0) int priority, String callingPackage) { if (isUiModeLocked()) { Slog.e(TAG, "enableCarMode while UI mode is locked"); return; } + + if (priority != UiModeManager.DEFAULT_PRIORITY + && getContext().checkCallingOrSelfPermission( + android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Enabling car mode with a priority requires " + + "permission ENTER_CAR_MODE_PRIORITIZED"); + } + final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - setCarModeLocked(true, flags); + setCarModeLocked(true, flags, priority, callingPackage); if (mSystemReady) { updateLocked(flags, 0); } @@ -356,16 +373,49 @@ final class UiModeManagerService extends SystemService { } } + /** + * This method is only kept around for the time being; the AIDL has an UnsupportedAppUsage + * tag which means this method is technically considered part of the greylist "API". + * @param flags + */ + @Override + public void disableCarMode(@UiModeManager.DisableCarMode int flags) { + disableCarModeByCallingPackage(flags, null /* callingPackage */); + } + + /** + * Handles requests to disable car mode. + * @param flags Disable car mode flags + * @param callingPackage + */ @Override - public void disableCarMode(int flags) { + public void disableCarModeByCallingPackage(@UiModeManager.DisableCarMode int flags, + String callingPackage) { if (isUiModeLocked()) { Slog.e(TAG, "disableCarMode while UI mode is locked"); return; } + + // If the caller is the system, we will allow the DISABLE_CAR_MODE_ALL_PRIORITIES car + // mode flag to be specified; this is so that the user can disable car mode at all + // priorities using the persistent notification. + boolean isSystemCaller = Binder.getCallingUid() == Process.SYSTEM_UID; + final int carModeFlags = + isSystemCaller ? flags : flags & ~UiModeManager.DISABLE_CAR_MODE_ALL_PRIORITIES; + final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - setCarModeLocked(false, 0); + // Determine if the caller has enabled car mode at a priority other than the + // default one. If they have, then attempt to disable at that priority. + int priority = mCarModePackagePriority.entrySet() + .stream() + .filter(e -> e.getValue().equals(callingPackage)) + .findFirst() + .map(Map.Entry::getKey) + .orElse(UiModeManager.DEFAULT_PRIORITY); + + setCarModeLocked(false, carModeFlags, priority, callingPackage); if (mSystemReady) { updateLocked(0, flags); } @@ -471,19 +521,32 @@ final class UiModeManagerService extends SystemService { synchronized (mLock) { pw.println("Current UI Mode Service state:"); pw.print(" mDockState="); pw.print(mDockState); - pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); + pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); + pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" ("); - pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") "); - pw.print(" mNightModeLocked="); pw.print(mNightModeLocked); - pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); - pw.print(" mComputedNightMode="); pw.print(mComputedNightMode); - pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags); - pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch); + pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") "); + pw.print(" mNightModeLocked="); pw.println(mNightModeLocked); + + pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); + pw.print(" (carModeApps="); + for (Map.Entry<Integer, String> entry : mCarModePackagePriority.entrySet()) { + pw.print(entry.getKey()); + pw.print(":"); + pw.print(entry.getValue()); + pw.print(" "); + } + pw.println(""); + pw.print(" mComputedNightMode="); pw.print(mComputedNightMode); + pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags); + pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch); + pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode)); - pw.print(" mUiModeLocked="); pw.print(mUiModeLocked); - pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); + pw.print(" mUiModeLocked="); pw.print(mUiModeLocked); + pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); + pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration); - pw.print(" mSystemReady="); pw.println(mSystemReady); + pw.print(" mSystemReady="); pw.println(mSystemReady); + if (mTwilightManager != null) { // We may not have a TwilightManager. pw.print(" mTwilightService.getLastTwilightState()="); @@ -506,12 +569,32 @@ final class UiModeManagerService extends SystemService { } } - void setCarModeLocked(boolean enabled, int flags) { - if (mCarModeEnabled != enabled) { - mCarModeEnabled = enabled; + /** + * Updates the global car mode state. + * The device is considered to be in car mode if there exists an app at any priority level which + * has entered car mode. + * + * @param enabled {@code true} if the caller wishes to enable car mode, {@code false} otherwise. + * @param flags Flags used when enabling/disabling car mode. + * @param priority The priority level for entering or exiting car mode; defaults to + * {@link UiModeManager#DEFAULT_PRIORITY} for callers using + * {@link UiModeManager#enableCarMode(int)}. Callers using + * {@link UiModeManager#enableCarMode(int, int)} may specify a priority. + * @param packageName The package name of the app which initiated the request to enable or + * disable car mode. + */ + void setCarModeLocked(boolean enabled, int flags, int priority, String packageName) { + if (enabled) { + enableCarMode(priority, packageName); + } else { + disableCarMode(flags, priority, packageName); + } + boolean isCarModeNowEnabled = isCarModeEnabled(); + if (mCarModeEnabled != isCarModeNowEnabled) { + mCarModeEnabled = isCarModeNowEnabled; // When exiting car mode, restore night mode from settings - if (!mCarModeEnabled) { + if (!isCarModeNowEnabled) { Context context = getContext(); updateNightModeFromSettings(context, context.getResources(), @@ -521,11 +604,102 @@ final class UiModeManagerService extends SystemService { mCarModeEnableFlags = flags; } + /** + * Handles disabling car mode. + * <p> + * Car mode can be disabled at a priority level if any of the following is true: + * 1. The priority being disabled is the {@link UiModeManager#DEFAULT_PRIORITY}. + * 2. The priority level is enabled and the caller is the app who originally enabled it. + * 3. The {@link UiModeManager#DISABLE_CAR_MODE_ALL_PRIORITIES} flag was specified, meaning all + * car mode priorities are disabled. + * + * @param flags Car mode flags. + * @param priority The priority level at which to disable car mode. + * @param packageName The calling package which initiated the request. + */ + private void disableCarMode(int flags, int priority, String packageName) { + boolean isDisableAll = (flags & UiModeManager.DISABLE_CAR_MODE_ALL_PRIORITIES) != 0; + boolean isPriorityTracked = mCarModePackagePriority.keySet().contains(priority); + boolean isDefaultPriority = priority == UiModeManager.DEFAULT_PRIORITY; + boolean isChangeAllowed = + // Anyone can disable the default priority. + isDefaultPriority + // If priority was enabled, only enabling package can disable it. + || isPriorityTracked && mCarModePackagePriority.get(priority).equals(packageName) + // Disable all priorities flag can disable all regardless. + || isDisableAll; + if (isChangeAllowed) { + Slog.d(TAG, "disableCarMode: disabling, priority=" + priority + + ", packageName=" + packageName); + if (isDisableAll) { + Set<Map.Entry<Integer, String>> entries = + new ArraySet<>(mCarModePackagePriority.entrySet()); + mCarModePackagePriority.clear(); + + for (Map.Entry<Integer, String> entry : entries) { + notifyCarModeDisabled(entry.getKey(), entry.getValue()); + } + } else { + mCarModePackagePriority.remove(priority); + notifyCarModeDisabled(priority, packageName); + } + } + } + + /** + * Handles enabling car mode. + * <p> + * Car mode can be enabled at any priority if it has not already been enabled at that priority. + * The calling package is tracked for the first app which enters priority at the + * {@link UiModeManager#DEFAULT_PRIORITY}, though any app can disable it at that priority. + * + * @param priority The priority for enabling car mode. + * @param packageName The calling package which initiated the request. + */ + private void enableCarMode(int priority, String packageName) { + boolean isPriorityTracked = mCarModePackagePriority.containsKey(priority); + boolean isPackagePresent = mCarModePackagePriority.containsValue(packageName); + if (!isPriorityTracked && !isPackagePresent) { + Slog.d(TAG, "enableCarMode: enabled at priority=" + priority + ", packageName=" + + packageName); + mCarModePackagePriority.put(priority, packageName); + notifyCarModeEnabled(priority, packageName); + } else { + Slog.d(TAG, "enableCarMode: car mode at priority " + priority + " already enabled."); + } + + } + + private void notifyCarModeEnabled(int priority, String packageName) { + Intent intent = new Intent(UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED); + intent.putExtra(UiModeManager.EXTRA_CALLING_PACKAGE, packageName); + intent.putExtra(UiModeManager.EXTRA_PRIORITY, priority); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.HANDLE_CAR_MODE_CHANGES); + } + + private void notifyCarModeDisabled(int priority, String packageName) { + Intent intent = new Intent(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED); + intent.putExtra(UiModeManager.EXTRA_CALLING_PACKAGE, packageName); + intent.putExtra(UiModeManager.EXTRA_PRIORITY, priority); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.HANDLE_CAR_MODE_CHANGES); + } + + /** + * Determines if car mode is enabled at any priority level. + * @return {@code true} if car mode is enabled, {@code false} otherwise. + */ + private boolean isCarModeEnabled() { + return mCarModePackagePriority.size() > 0; + } + private void updateDockState(int newState) { synchronized (mLock) { if (newState != mDockState) { mDockState = newState; - setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR, 0); + setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR, 0, + UiModeManager.DEFAULT_PRIORITY, "" /* packageName */); if (mSystemReady) { updateLocked(UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME, 0); } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 83ad4e7e7100..454941ccdb03 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -89,6 +89,7 @@ public class Watchdog extends Thread { "/system/bin/drmserver", "/system/bin/mediadrmserver", "/system/bin/mediaserver", + "/system/bin/netd", "/system/bin/sdcard", "/system/bin/surfaceflinger", "/system/bin/vold", diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e5c8ba515446..5af1480af94b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -349,7 +349,6 @@ import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; import com.android.server.appop.AppOpsService; -import com.android.server.compat.CompatConfig; import com.android.server.compat.PlatformCompat; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.firewall.IntentFirewall; @@ -5049,8 +5048,9 @@ public class ActivityManagerService extends IActivityManager.Stub bindApplicationTimeMillis = SystemClock.elapsedRealtime(); mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); - long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info); + long[] disabledCompatChanges = {}; if (mPlatformCompat != null) { + disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info); mPlatformCompat.resetReporting(app.info); } if (app.isolatedEntryPoint != null) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 6e92e80424fa..d9e4844209d0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -41,6 +41,7 @@ import android.app.usage.AppStandbyInfo; import android.app.usage.ConfigurationStats; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageStatsManager; +import android.compat.Compatibility; import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.Context; @@ -80,15 +81,17 @@ import android.os.UserManager; import android.text.TextUtils; import android.text.format.Time; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.DebugUtils; import android.util.DisplayMetrics; import android.util.proto.ProtoOutputStream; import android.view.Display; +import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.util.HexDump; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; -import com.android.server.compat.CompatConfig; +import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; import java.io.File; @@ -2868,56 +2871,49 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - private void killPackage(String packageName, PrintWriter pw) throws RemoteException { - int uid = mPm.getPackageUid(packageName, 0, mUserId); - if (uid < 0) { - // uid is negative if the package wasn't found. - pw.println("Didn't find package " + packageName + " on device."); - } else { - pw.println("Killing package " + packageName + " (UID " + uid + ")."); - final long origId = Binder.clearCallingIdentity(); - mInterface.killUid(UserHandle.getAppId(uid), - UserHandle.USER_ALL, "killPackage"); - Binder.restoreCallingIdentity(origId); - } - } - private int runCompat(PrintWriter pw) throws RemoteException { - final CompatConfig config = CompatConfig.get(); + final PlatformCompat platformCompat = (PlatformCompat) + ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); String toggleValue = getNextArgRequired(); long changeId; String changeIdString = getNextArgRequired(); try { changeId = Long.parseLong(changeIdString); } catch (NumberFormatException e) { - changeId = config.lookupChangeId(changeIdString); + changeId = platformCompat.lookupChangeId(changeIdString); } if (changeId == -1) { pw.println("Unknown or invalid change: '" + changeIdString + "'."); + return -1; } String packageName = getNextArgRequired(); + if (!platformCompat.isKnownChangeId(changeId)) { + pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it" + + " could have no effect."); + } + ArraySet<Long> enabled = new ArraySet<>(); + ArraySet<Long> disabled = new ArraySet<>(); switch (toggleValue) { case "enable": - if (!config.addOverride(changeId, packageName, true)) { - pw.println("Warning! Change " + changeId + " is not known yet. Enabling it" - + " could have no effect."); - } + enabled.add(changeId); pw.println("Enabled change " + changeId + " for " + packageName + "."); - killPackage(packageName, pw); + CompatibilityChangeConfig overrides = + new CompatibilityChangeConfig( + new Compatibility.ChangeConfig(enabled, disabled)); + platformCompat.setOverrides(overrides, packageName); return 0; case "disable": - if (!config.addOverride(changeId, packageName, false)) { - pw.println("Warning! Change " + changeId + " is not known yet. Disabling it" - + " could have no effect."); - } + disabled.add(changeId); pw.println("Disabled change " + changeId + " for " + packageName + "."); - killPackage(packageName, pw); + overrides = + new CompatibilityChangeConfig( + new Compatibility.ChangeConfig(enabled, disabled)); + platformCompat.setOverrides(overrides, packageName); return 0; case "reset": - if (config.removeOverride(changeId, packageName)) { + if (platformCompat.clearOverride(changeId, packageName)) { pw.println("Reset change " + changeId + " for " + packageName + " to default value."); - killPackage(packageName, pw); } else { pw.println("No override exists for changeId " + changeId + "."); } diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 525531635df6..0524f91a01fb 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -445,7 +445,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) { // We were asked to fetch Telephony data. if (mTelephony == null) { - mTelephony = TelephonyManager.from(mContext); + mTelephony = mContext.getSystemService(TelephonyManager.class); } if (mTelephony != null) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c2f452932775..567404697395 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -731,7 +731,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void notePhoneState(int state) { enforceCallingPermission(); - int simState = TelephonyManager.getDefault().getSimState(); + int simState = mContext.getSystemService(TelephonyManager.class).getSimState(); synchronized (mStats) { mStats.notePhoneStateLocked(state, simState); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 1f1e8a5b3868..48f08e3226e3 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3911,8 +3911,7 @@ public class AudioService extends IAudioService.Stub final boolean muteSystem = (zenPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0; final boolean muteNotificationAndRing = ZenModeConfig - .areAllPriorityOnlyNotificationZenSoundsMuted( - mNm.getConsolidatedNotificationPolicy()); + .areAllPriorityOnlyNotificationZenSoundsMuted(zenPolicy); return muteAlarms && isAlarm(streamType) || muteMedia && isMedia(streamType) || muteSystem && isSystem(streamType) @@ -3924,11 +3923,13 @@ public class AudioService extends IAudioService.Stub } /** - * DND total silence: media and alarms streams are tied to the muted ringer - * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)} - * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode) - * DND priority only: alarms, media, system streams can be muted separate from ringer based on - * zenPolicy (this method determines which streams) + * Notifications, ringer and system sounds are controlled by the ringer: + * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)} but can + * also be muted by DND based on the DND mode: + * DND total silence: media and alarms streams can be muted by DND + * DND alarms only: no streams additionally controlled by DND + * DND priority only: alarms, media, system, ringer and notification streams can be muted by + * DND. The current applied zenPolicy determines which streams will be muted by DND. * @return true if changed, else false */ private boolean updateZenModeAffectedStreams() { @@ -3949,6 +3950,11 @@ public class AudioService extends IAudioService.Stub & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) { zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM; } + + if (ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(zenPolicy)) { + zenModeAffectedStreams |= 1 << AudioManager.STREAM_NOTIFICATION; + zenModeAffectedStreams |= 1 << AudioManager.STREAM_RING; + } } if (mZenModeAffectedStreams != zenModeAffectedStreams) { diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index d6ec22b078ea..490cce347188 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -43,13 +43,14 @@ import java.util.HashSet; import java.util.Set; import javax.xml.datatype.DatatypeConfigurationException; + /** * This class maintains state relating to platform compatibility changes. * * <p>It stores the default configuration for each change, and any per-package overrides that have * been configured. */ -public final class CompatConfig { +final class CompatConfig { private static final String TAG = "CompatConfig"; @@ -61,13 +62,13 @@ public final class CompatConfig { private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); @VisibleForTesting - public CompatConfig() { + CompatConfig() { } /** * @return The static instance of this class to be used within the system server. */ - public static CompatConfig get() { + static CompatConfig get() { return sInstance; } @@ -77,7 +78,7 @@ public final class CompatConfig { * * @param change The change to add. Any change with the same ID will be overwritten. */ - public void addChange(CompatChange change) { + void addChange(CompatChange change) { synchronized (mChanges) { mChanges.put(change.getId(), change); } @@ -89,10 +90,10 @@ public final class CompatConfig { * * @param app The app in question * @return A sorted long array of change IDs. We use a primitive array to minimize memory - * footprint: Every app process will store this array statically so we aim to reduce - * overhead as much as possible. + * footprint: Every app process will store this array statically so we aim to reduce + * overhead as much as possible. */ - public long[] getDisabledChanges(ApplicationInfo app) { + long[] getDisabledChanges(ApplicationInfo app) { LongArray disabled = new LongArray(); synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { @@ -113,7 +114,7 @@ public final class CompatConfig { * @param name Name of the change to look up * @return The change ID, or {@code -1} if no change with that name exists. */ - public long lookupChangeId(String name) { + long lookupChangeId(String name) { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { if (TextUtils.equals(mChanges.valueAt(i).getName(), name)) { @@ -128,11 +129,11 @@ public final class CompatConfig { * Find if a given change is enabled for a given application. * * @param changeId The ID of the change in question - * @param app App to check for + * @param app App to check for * @return {@code true} if the change is enabled for this app. Also returns {@code true} if the - * change ID is not known, as unknown changes are enabled by default. + * change ID is not known, as unknown changes are enabled by default. */ - public boolean isChangeEnabled(long changeId, ApplicationInfo app) { + boolean isChangeEnabled(long changeId, ApplicationInfo app) { synchronized (mChanges) { CompatChange c = mChanges.get(changeId); if (c == null) { @@ -150,14 +151,15 @@ public final class CompatConfig { * * <p>Note, package overrides are not persistent and will be lost on system or runtime restart. * - * @param changeId The ID of the change to be overridden. Note, this call will succeed even if - * this change is not known; it will only have any effect if any code in the - * platform is gated on the ID given. + * @param changeId The ID of the change to be overridden. Note, this call will succeed even + * if + * this change is not known; it will only have any effect if any code in the + * platform is gated on the ID given. * @param packageName The app package name to override the change for. - * @param enabled If the change should be enabled or disabled. + * @param enabled If the change should be enabled or disabled. * @return {@code true} if the change existed before adding the override. */ - public boolean addOverride(long changeId, String packageName, boolean enabled) { + boolean addOverride(long changeId, String packageName, boolean enabled) { boolean alreadyKnown = true; synchronized (mChanges) { CompatChange c = mChanges.get(changeId); @@ -172,15 +174,27 @@ public final class CompatConfig { } /** + * Check whether the change is known to the compat config. + * + * @return {@code true} if the change is known. + */ + boolean isKnownChangeId(long changeId) { + synchronized (mChanges) { + CompatChange c = mChanges.get(changeId); + return c != null; + } + } + + /** * Removes an override previously added via {@link #addOverride(long, String, boolean)}. This * restores the default behaviour for the given change and app, once any app processes have been * restarted. * - * @param changeId The ID of the change that was overridden. + * @param changeId The ID of the change that was overridden. * @param packageName The app package name that was overridden. * @return {@code true} if an override existed; */ - public boolean removeOverride(long changeId, String packageName) { + boolean removeOverride(long changeId, String packageName) { boolean overrideExists = false; synchronized (mChanges) { CompatChange c = mChanges.get(changeId); @@ -191,22 +205,22 @@ public final class CompatConfig { } return overrideExists; } + /** * Overrides the enabled state for a given change and app. This method is intended to be used * *only* for debugging purposes. * * <p>Note, package overrides are not persistent and will be lost on system or runtime restart. * - * @param overrides list of overrides to default changes config. + * @param overrides list of overrides to default changes config. * @param packageName app for which the overrides will be applied. */ - public void addOverrides( - CompatibilityChangeConfig overrides, String packageName) { + void addOverrides(CompatibilityChangeConfig overrides, String packageName) { synchronized (mChanges) { - for (Long changeId: overrides.enabledChanges()) { + for (Long changeId : overrides.enabledChanges()) { addOverride(changeId, packageName, true); } - for (Long changeId: overrides.disabledChanges()) { + for (Long changeId : overrides.disabledChanges()) { addOverride(changeId, packageName, false); } } @@ -221,7 +235,7 @@ public final class CompatConfig { * * @param packageName The package for which the overrides should be purged. */ - public void removePackageOverrides(String packageName) { + void removePackageOverrides(String packageName) { synchronized (mChanges) { for (int i = 0; i < mChanges.size(); ++i) { mChanges.valueAt(i).removePackageOverride(packageName); @@ -230,11 +244,11 @@ public final class CompatConfig { } /** - * Dumps the current list of compatibility config information. - * - * @param pw The {@link PrintWriter} instance to which the information will be dumped. - */ - public void dumpConfig(PrintWriter pw) { + * Dumps the current list of compatibility config information. + * + * @param pw The {@link PrintWriter} instance to which the information will be dumped. + */ + void dumpConfig(PrintWriter pw) { synchronized (mChanges) { if (mChanges.size() == 0) { pw.println("No compat overrides."); @@ -252,10 +266,10 @@ public final class CompatConfig { * * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped. * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the - * given app. + * given app. */ - public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) { + CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) { Set<Long> enabled = new HashSet<>(); Set<Long> disabled = new HashSet<>(); synchronized (mChanges) { @@ -276,15 +290,15 @@ public final class CompatConfig { * * @return An array of {@link CompatibilityChangeInfo} with the current changes. */ - public CompatibilityChangeInfo[] dumpChanges() { + CompatibilityChangeInfo[] dumpChanges() { synchronized (mChanges) { CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()]; for (int i = 0; i < mChanges.size(); ++i) { CompatChange change = mChanges.valueAt(i); changeInfos[i] = new CompatibilityChangeInfo(change.getId(), - change.getName(), - change.getEnableAfterTargetSdk(), - change.getDisabled()); + change.getName(), + change.getEnableAfterTargetSdk(), + change.getDisabled()); } return changeInfos; } diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 75e2d220898d..ae5ad7ea1261 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,9 +16,13 @@ package com.android.server.compat; +import android.app.ActivityManager; +import android.app.IActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; import android.util.StatsLog; @@ -106,12 +110,32 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) { CompatConfig.get().addOverrides(overrides, packageName); + killPackage(packageName); + } + + @Override + public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) { + CompatConfig.get().addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) { CompatConfig config = CompatConfig.get(); config.removePackageOverrides(packageName); + killPackage(packageName); + } + + @Override + public void clearOverridesForTest(String packageName) { + CompatConfig config = CompatConfig.get(); + config.removePackageOverrides(packageName); + } + + @Override + public boolean clearOverride(long changeId, String packageName) { + boolean existed = CompatConfig.get().removeOverride(changeId, packageName); + killPackage(packageName); + return existed; } @Override @@ -124,6 +148,39 @@ public class PlatformCompat extends IPlatformCompat.Stub { return CompatConfig.get().dumpChanges(); } + /** + * Check whether the change is known to the compat config. + * @param changeId + * @return {@code true} if the change is known. + */ + public boolean isKnownChangeId(long changeId) { + return CompatConfig.get().isKnownChangeId(changeId); + + } + + /** + * Retrieves the set of disabled changes for a given app. Any change ID not in the returned + * array is by default enabled for the app. + * + * @param appInfo The app in question + * @return A sorted long array of change IDs. We use a primitive array to minimize memory + * footprint: Every app process will store this array statically so we aim to reduce + * overhead as much as possible. + */ + public long[] getDisabledChanges(ApplicationInfo appInfo) { + return CompatConfig.get().getDisabledChanges(appInfo); + } + + /** + * Look up a change ID by name. + * + * @param name Name of the change to look up + * @return The change ID, or {@code -1} if no change with that name exists. + */ + public long lookupChangeId(String name) { + return CompatConfig.get().lookupChangeId(name); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; @@ -151,4 +208,34 @@ public class PlatformCompat extends IPlatformCompat.Stub { private void reportChange(long changeId, int uid, int state) { mChangeReporter.reportChange(uid, changeId, state); } + + private void killPackage(String packageName) { + int uid = -1; + try { + uid = mContext.getPackageManager().getPackageUid(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Didn't find package " + packageName + " on device.", e); + return; + } + + Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ")."); + killUid(UserHandle.getAppId(uid), + UserHandle.USER_ALL, "PlatformCompat overrides"); + } + + private void killUid(int appId, int userId, String reason) { + final long identity = Binder.clearCallingIdentity(); + try { + IActivityManager am = ActivityManager.getService(); + if (am != null) { + try { + am.killUid(appId, userId, reason); + } catch (RemoteException e) { + /* ignore - same process */ + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } } diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index b3804c4d7ec5..acedc3635730 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -286,8 +286,8 @@ public class Tethering extends BaseNetworkObserver { private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); - TelephonyManager.from(mContext).listen(mPhoneStateListener, - PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + mContext.getSystemService(TelephonyManager.class).listen( + mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_STATE); diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java index 2e72fbd95931..93227bd78a81 100644 --- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java @@ -321,7 +321,11 @@ class GnssNetworkConnectivityHandler { private void handleUpdateNetworkState(Network network, boolean isConnected, NetworkCapabilities capabilities) { - boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled(); + boolean networkAvailable = false; + TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); + if (telephonyManager != null) { + networkAvailable = isConnected && telephonyManager.getDataEnabled(); + } NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network, capabilities); String apn = networkAttributes.mApn; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 41806cabef3f..08c94267e969 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -337,7 +337,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), TelephonyManager.getDefault(), + wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); service.registerLocalService(); diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index 8facce112b52..dbe83670d3a0 100644 --- a/services/core/java/com/android/server/pm/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/ComponentResolver.java @@ -49,6 +49,7 @@ import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ArrayUtils; import com.android.server.IntentResolver; import java.io.PrintWriter; @@ -375,8 +376,11 @@ public class ComponentResolver { addProvidersLocked(pkg, chatty); addServicesLocked(pkg, chatty); } - final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName( - PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM); + // expect single setupwizard package + final String setupWizardPackage = ArrayUtils.firstOrNull( + sPackageManagerInternal.getKnownPackageNames( + PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); + for (int i = newIntents.size() - 1; i >= 0; --i) { final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i); final PackageParser.Package disabledPkg = sPackageManagerInternal @@ -410,8 +414,11 @@ public class ComponentResolver { final List<ActivityIntentInfo> protectedFilters = mProtectedFilters; mProtectedFilters = null; - final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName( - PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM); + // expect single setupwizard package + final String setupWizardPackage = ArrayUtils.firstOrNull( + sPackageManagerInternal.getKnownPackageNames( + PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); + if (DEBUG_FILTERS && setupWizardPackage == null) { Slog.i(TAG, "No setup wizard;" + " All protected intents capped to priority 0"); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 56d2258b8c91..a77b72871155 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1430,6 +1430,7 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mConfiguratorPackage; final @Nullable String mAppPredictionServicePackage; final @Nullable String mIncidentReportApproverPackage; + final @Nullable String[] mTelephonyPackages; final @NonNull String mServicesSystemSharedLibraryPackageName; final @NonNull String mSharedSystemSharedLibraryPackageName; @@ -3146,6 +3147,7 @@ public class PackageManagerService extends IPackageManager.Stub mContext.getString(R.string.config_deviceConfiguratorPackageName); mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); + mTelephonyPackages = getTelephonyPackageNames(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -20786,6 +20788,16 @@ public class PackageManagerService extends IPackageManager.Stub } @Override + public String[] getTelephonyPackageNames() { + String names = mContext.getString(R.string.config_telephonyPackages); + String[] telephonyPackageNames = null; + if (!TextUtils.isEmpty(names)) { + telephonyPackageNames = names.trim().split(","); + } + return telephonyPackageNames; + } + + @Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return; @@ -23934,34 +23946,36 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public String getKnownPackageName(int knownPackage, int userId) { + public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) { switch(knownPackage) { case PackageManagerInternal.PACKAGE_BROWSER: - return getDefaultBrowserPackageName(userId); + return new String[]{getDefaultBrowserPackageName(userId)}; case PackageManagerInternal.PACKAGE_INSTALLER: - return mRequiredInstallerPackage; + return new String[]{mRequiredInstallerPackage}; case PackageManagerInternal.PACKAGE_SETUP_WIZARD: - return mSetupWizardPackage; + return new String[]{mSetupWizardPackage}; case PackageManagerInternal.PACKAGE_SYSTEM: - return "android"; + return new String[]{"android"}; case PackageManagerInternal.PACKAGE_VERIFIER: - return mRequiredVerifierPackage; + return new String[]{mRequiredVerifierPackage}; case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER: - return mSystemTextClassifierPackage; + return new String[]{mSystemTextClassifierPackage}; case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER: - return mRequiredPermissionControllerPackage; + return new String[]{mRequiredPermissionControllerPackage}; case PackageManagerInternal.PACKAGE_WELLBEING: - return mWellbeingPackage; + return new String[]{mWellbeingPackage}; case PackageManagerInternal.PACKAGE_DOCUMENTER: - return mDocumenterPackage; + return new String[]{mDocumenterPackage}; case PackageManagerInternal.PACKAGE_CONFIGURATOR: - return mConfiguratorPackage; + return new String[]{mConfiguratorPackage}; case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER: - return mIncidentReportApproverPackage; + return new String[]{mIncidentReportApproverPackage}; case PackageManagerInternal.PACKAGE_APP_PREDICTOR: - return mAppPredictionServicePackage; + return new String[]{mAppPredictionServicePackage}; + case PackageManagerInternal.PACKAGE_TELEPHONY: + return mTelephonyPackages; } - return null; + return ArrayUtils.emptyArray(String.class); } @Override @@ -24117,6 +24131,12 @@ public class PackageManagerService extends IPackageManager.Stub public List<ResolveInfo> queryIntentActivities( Intent intent, int flags, int filterCallingUid, int userId) { final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver()); + return queryIntentActivities(intent, resolvedType, flags, filterCallingUid, userId); + } + + @Override + public List<ResolveInfo> queryIntentActivities( + Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) { return PackageManagerService.this .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid, userId, false /*resolveForStart*/, true /*allowDynamicSplits*/); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 3bc2236a8221..4ecfbfee6e65 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3337,7 +3337,8 @@ public final class Settings { int flags, ComponentName cn, String scheme, PatternMatcher ssp, IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) { final List<ResolveInfo> ri = - pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0); + pmInternal.queryIntentActivities( + intent, intent.getType(), flags, Binder.getCallingUid(), 0); if (PackageManagerService.DEBUG_PREFERRED) { Log.d(TAG, "Queried " + intent + " results: " + ri); } diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 6d22faa7032e..c39dcfefb2e8 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -276,6 +276,9 @@ public final class BasePermission { public boolean isAppPredictor() { return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0; } + public boolean isTelephony() { + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0; + } public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { if (!origPackageName.equals(sourcePackageName)) { diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index f76298592c2b..5870986a264f 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -436,17 +436,20 @@ public final class DefaultPermissionGrantPolicy { // Installer grantSystemFixedPermissionsToSystemPackage( - getKnownPackage(PackageManagerInternal.PACKAGE_INSTALLER, userId), + ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_INSTALLER, userId)), userId, STORAGE_PERMISSIONS); // Verifier - final String verifier = getKnownPackage(PackageManagerInternal.PACKAGE_VERIFIER, userId); + final String verifier = ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_VERIFIER, userId)); grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS); grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS); // SetupWizard grantPermissionsToSystemPackage( - getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId, + ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId, PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CAMERA_PERMISSIONS); @@ -595,7 +598,8 @@ public final class DefaultPermissionGrantPolicy { userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS); // Browser - String browserPackage = getKnownPackage(PackageManagerInternal.PACKAGE_BROWSER, userId); + String browserPackage = ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_BROWSER, userId)); if (browserPackage == null) { browserPackage = getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_BROWSER, userId); @@ -760,8 +764,8 @@ public final class DefaultPermissionGrantPolicy { } } - private String getKnownPackage(int knownPkgId, int userId) { - return mServiceInternal.getKnownPackageName(knownPkgId, userId); + private @NonNull String[] getKnownPackages(int knownPkgId, int userId) { + return mServiceInternal.getKnownPackageNames(knownPkgId, userId); } private void grantDefaultPermissionsToDefaultSystemDialerApp( diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 6d1f2d3e1e57..6a7c622b7e33 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1706,8 +1706,9 @@ public class PermissionManagerService { } } } - final String systemPackageName = mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM); + // expect single system package + String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM)); final PackageParser.Package systemPackage = mPackageManagerInt.getPackage(systemPackageName); @@ -1823,18 +1824,19 @@ public class PermissionManagerService { // need a separate flag anymore. Hence we need to check which // permissions are needed by the permission controller if (!allowed && bp.isInstaller() - && (pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM)) - || pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM), + pkg.packageName) || ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER, - UserHandle.USER_SYSTEM)))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // If this permission is to be granted to the system installer and // this app is an installer, then it gets the permission. allowed = true; } if (!allowed && bp.isVerifier() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the system verifier and // this app is a verifier, then it gets the permission. allowed = true; @@ -1850,53 +1852,64 @@ public class PermissionManagerService { allowed = origPermissions.hasInstallPermission(perm); } if (!allowed && bp.isSetup() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the system setup wizard and // this app is a setup wizard, then it gets the permission. allowed = true; } if (!allowed && bp.isSystemTextClassifier() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER, - UserHandle.USER_SYSTEM))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // Special permissions for the system default text classifier. allowed = true; } if (!allowed && bp.isConfigurator() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_CONFIGURATOR, - UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_CONFIGURATOR, + UserHandle.USER_SYSTEM), pkg.packageName)) { // Special permissions for the device configurator. allowed = true; } if (!allowed && bp.isWellbeing() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM), + pkg.packageName)) { // Special permission granted only to the OEM specified wellbeing app allowed = true; } if (!allowed && bp.isDocumenter() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM), + pkg.packageName)) { // If this permission is to be granted to the documenter and // this app is the documenter, then it gets the permission. allowed = true; } if (!allowed && bp.isIncidentReportApprover() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER, - UserHandle.USER_SYSTEM))) { + UserHandle.USER_SYSTEM), pkg.packageName)) { // If this permission is to be granted to the incident report approver and // this app is the incident report approver, then it gets the permission. allowed = true; } if (!allowed && bp.isAppPredictor() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM))) { + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM), + pkg.packageName)) { // Special permissions for the system app predictor. allowed = true; } + if (!allowed && bp.isTelephony() + && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + PackageManagerInternal.PACKAGE_TELEPHONY, UserHandle.USER_SYSTEM), + pkg.packageName)) { + // Special permissions for the system telephony apps. + allowed = true; + } } return allowed; } diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java index 69e24063210d..865e3b8cc109 100644 --- a/services/net/java/android/net/NetworkStackClient.java +++ b/services/net/java/android/net/NetworkStackClient.java @@ -103,7 +103,7 @@ public class NetworkStackClient { // checks here should be kept in sync with PermissionUtil. if (caller != Process.SYSTEM_UID && caller != Process.NETWORK_STACK_UID - && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) { + && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) { throw new SecurityException( "Only the system server should try to bind to the network stack."); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index dcab78ede287..8cd6ef9c132f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -98,7 +98,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT; Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders, - priorityMessageSenders, suppressedVisualEffects); + priorityMessageSenders, suppressedVisualEffects, 0); assertEquals(expectedPolicy, config.toNotificationPolicy(zenPolicy)); } diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index ae924645d3da..bebbbd01fd88 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -97,6 +97,14 @@ public final class DisconnectCause implements Parcelable { */ public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL"; + /** + * This reason is set when a call is ended in order to place an emergency call when a + * {@link PhoneAccount} doesn't support holding an ongoing call to place an emergency call. This + * reason string should only be associated with the {@link #LOCAL} disconnect code returned from + * {@link #getCode()}. + */ + public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED"; + private int mDisconnectCode; private CharSequence mDisconnectLabel; private CharSequence mDisconnectDescription; diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java index 79d366037f08..79d366037f08 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index f27b944d2cff..087937d5ade2 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -1127,8 +1127,9 @@ public final class Telephony { * values:</p> * * <ul> - * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message - * data, including ETWS or CMAS warning notification info if present.</li> + * <li><em>"message"</em> - An {@link android.telephony.SmsCbMessage} object + * containing the broadcast message data, including ETWS or CMAS warning notification + * info if present.</li> * </ul> * * <p>The extra values can be extracted using @@ -1139,11 +1140,12 @@ public final class Telephony { * * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST} to * receive.</p> - * @removed + * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION = - "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; + @SystemApi + public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = + "android.provider.action.SMS_EMERGENCY_CB_RECEIVED"; /** * Broadcast Action: A new CDMA SMS has been received containing Service Category diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 4dad01f9d5c0..a0aa8928dae8 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -809,7 +809,9 @@ public class CarrierConfigManager { /** * The default flag specifying whether ETWS/CMAS test setting is forcibly disabled in * Settings->More->Emergency broadcasts menu even though developer options is turned on. + * @deprecated moved to cellbroadcastreceiver resource show_test_settings */ + @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool"; @@ -1743,6 +1745,15 @@ public class CarrierConfigManager { "allow_emergency_video_calls_bool"; /** + * Flag indicating whether or not an ongoing call will be held when an outgoing emergency call + * is placed. If true, ongoing calls will be put on hold when an emergency call is placed. If + * false, placing an emergency call will trigger the disconnect of all ongoing calls before + * the emergency call is placed. + */ + public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = + "allow_hold_call_during_emergency_bool"; + + /** * Flag indicating whether the carrier supports RCS presence indication for * User Capability Exchange (UCE). When presence is supported, the device should use the * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the @@ -3499,6 +3510,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_MMS_USER_AGENT_STRING, ""); sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true); sDefaults.putInt(KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 0); + sDefaults.putBoolean(KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL, true); sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false); sDefaults.putBoolean(KEY_USE_RCS_SIP_OPTIONS_BOOL, false); sDefaults.putBoolean(KEY_FORCE_IMEI_BOOL, false); diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java index 0b73252a1e1b..f4ce6e75769c 100644 --- a/telephony/java/com/android/internal/telephony/CbGeoUtils.java +++ b/telephony/java/android/telephony/CbGeoUtils.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.internal.telephony; +package android.telephony; import android.annotation.NonNull; -import android.telephony.Rlog; +import android.annotation.SystemApi; import android.text.TextUtils; import java.util.ArrayList; @@ -30,8 +30,17 @@ import java.util.stream.Collectors; * The coordinates used by this utils class are latitude and longitude, but some algorithms in this * class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use * this class for anything other then geo-targeting of cellbroadcast messages. + * @hide */ +@SystemApi public class CbGeoUtils { + + /** + * This class is never instantiated + * @hide + */ + private CbGeoUtils() {} + /** Geometric interface. */ public interface Geometry { /** @@ -39,27 +48,36 @@ public class CbGeoUtils { * @param p point in latitude, longitude format. * @return {@code True} if the given point is inside the geometry. */ - boolean contains(LatLng p); + boolean contains(@NonNull LatLng p); } /** * Tolerance for determining if the value is 0. If the absolute value of a value is less than * this tolerance, it will be treated as 0. + * @hide */ public static final double EPS = 1e-7; - /** The radius of earth. */ + /** + * The radius of earth. + * @hide + */ public static final int EARTH_RADIUS_METER = 6371 * 1000; private static final String TAG = "CbGeoUtils"; - /** The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. */ + // The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. + /** @hide */ public static final int GEO_FENCING_MAXIMUM_WAIT_TIME = 0x01; + /** @hide */ public static final int GEOMETRY_TYPE_POLYGON = 0x02; + /** @hide */ public static final int GEOMETRY_TYPE_CIRCLE = 0x03; - /** The identifier of geometry in the encoded string. */ + // The identifier of geometry in the encoded string. + /** @hide */ private static final String CIRCLE_SYMBOL = "circle"; + /** @hide */ private static final String POLYGON_SYMBOL = "polygon"; /** Point represent by (latitude, longitude). */ @@ -81,7 +99,8 @@ public class CbGeoUtils { * @param p the point use to calculate the subtraction result. * @return the result of this point subtract the given point {@code p}. */ - public LatLng subtract(LatLng p) { + @NonNull + public LatLng subtract(@NonNull LatLng p) { return new LatLng(lat - p.lat, lng - p.lng); } @@ -90,7 +109,7 @@ public class CbGeoUtils { * @param p the point use to calculate the distance. * @return the distance in meter. */ - public double distance(LatLng p) { + public double distance(@NonNull LatLng p) { double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat)); double dlng = Math.sin(0.5 * Math.toRadians(lng - p.lng)); double x = dlat * dlat @@ -106,6 +125,7 @@ public class CbGeoUtils { /** * The class represents a simple polygon with at least 3 points. + * @hide */ public static class Polygon implements Geometry { /** @@ -239,7 +259,10 @@ public class CbGeoUtils { } } - /** The class represents a circle. */ + /** + * The class represents a circle. + * @hide + */ public static class Circle implements Geometry { private final LatLng mCenter; private final double mRadiusMeter; @@ -266,6 +289,7 @@ public class CbGeoUtils { /** * Parse the geometries from the encoded string {@code str}. The string must follow the * geometry encoding specified by {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. + * @hide */ @NonNull public static List<Geometry> parseGeometriesFromString(@NonNull String str) { @@ -297,6 +321,7 @@ public class CbGeoUtils { * * @param geometries the list of geometry objects need to be encoded. * @return the encoded string. + * @hide */ @NonNull public static String encodeGeometriesToString(List<Geometry> geometries) { @@ -313,6 +338,7 @@ public class CbGeoUtils { * {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. * @param geometry the geometry object need to be encoded. * @return the encoded string. + * @hide */ @NonNull private static String encodeGeometryToString(@NonNull Geometry geometry) { @@ -351,6 +377,7 @@ public class CbGeoUtils { * * @param str encoded lat/lng string. * @Return {@link LatLng} object. + * @hide */ @NonNull public static LatLng parseLatLngFromString(@NonNull String str) { @@ -361,6 +388,7 @@ public class CbGeoUtils { /** * @Return the sign of the given value {@code value} with the specified tolerance. Return 1 * means the sign is positive, -1 means negative, 0 means the value will be treated as 0. + * @hide */ public static int sign(double value) { if (value > EPS) return 1; diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index 85110c22aa18..04ec4b6949af 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -354,6 +354,12 @@ public final class DisconnectCause { */ public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79; + /** + * Indicates that an emergency call was placed, which caused the existing connection to be + * hung up. + */ + public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; + //********************************************************************************************* // When adding a disconnect type: // 1) Update toString() with the newly added disconnect type. @@ -528,6 +534,8 @@ public final class DisconnectCause { return "EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE"; case WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION: return "WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION"; + case OUTGOING_EMERGENCY_CALL_PLACED: + return "OUTGOING_EMERGENCY_CALL_PLACED"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index dc991b9a3ea7..3e044e52d28b 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -25,9 +25,7 @@ import android.database.Cursor; import android.os.Parcel; import android.os.Parcelable; import android.provider.Telephony.CellBroadcasts; - -import com.android.internal.telephony.CbGeoUtils; -import com.android.internal.telephony.CbGeoUtils.Geometry; +import android.telephony.CbGeoUtils.Geometry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -414,9 +412,8 @@ public final class SmsCbMessage implements Parcelable { /** * Get the Geo-Fencing Maximum Wait Time. * @return the time in second. - * @hide */ - public int getMaximumWaitingTime() { + public int getMaximumWaitingDuration() { return mMaximumWaitTimeSec; } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 54e87afb2da9..daeacf8206b4 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -520,7 +520,6 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message body"); } - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -629,7 +628,6 @@ public final class SmsManager { final int finalPriority = priority; final int finalValidity = validityPeriod; - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -933,7 +931,6 @@ public final class SmsManager { } if (parts.size() > 1) { - final Context context = ActivityThread.currentApplication().getApplicationContext(); // We will only show the SMS disambiguation dialog in the case that the message is being // persisted. This is for two reasons: // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific @@ -1174,7 +1171,6 @@ public final class SmsManager { if (parts.size() > 1) { final int finalPriority = priority; final int finalValidity = validityPeriod; - final Context context = ActivityThread.currentApplication().getApplicationContext(); if (persistMessage) { resolveSubscriptionForOperation(new SubscriptionResolverResult() { @Override @@ -1331,7 +1327,6 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message data"); } - final Context context = ActivityThread.currentApplication().getApplicationContext(); resolveSubscriptionForOperation(new SubscriptionResolverResult() { @Override public void onSuccess(int subId) { diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 0e1dda7a9cce..9d1b7a918327 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -49,6 +49,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; @@ -61,10 +62,8 @@ import android.telephony.ims.ImsMmTelManager; import android.util.DisplayMetrics; import android.util.Log; -import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISub; -import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Preconditions; @@ -931,20 +930,24 @@ public class SubscriptionManager { OnSubscriptionsChangedListenerHandler(Looper looper) { super(looper); } - - @Override - public void handleMessage(Message msg) { - if (DBG) { - log("handleMessage: invoke the overriden onSubscriptionsChanged()"); - } - OnSubscriptionsChangedListener.this.onSubscriptionsChanged(); - } } - private final Handler mHandler; + /** + * Posted executor callback on the handler associated with a given looper. + * The looper can be the calling thread's looper or the looper passed from the + * constructor {@link #OnSubscriptionsChangedListener(Looper)}. + */ + private final HandlerExecutor mExecutor; + + /** + * @hide + */ + public HandlerExecutor getHandlerExecutor() { + return mExecutor; + } public OnSubscriptionsChangedListener() { - mHandler = new OnSubscriptionsChangedListenerHandler(); + mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler()); } /** @@ -953,7 +956,7 @@ public class SubscriptionManager { * @hide */ public OnSubscriptionsChangedListener(Looper looper) { - mHandler = new OnSubscriptionsChangedListenerHandler(looper); + mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper)); } /** @@ -965,18 +968,6 @@ public class SubscriptionManager { if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); } - /** - * The callback methods need to be called on the handler thread where - * this object was created. If the binder did that for us it'd be nice. - */ - IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { - @Override - public void onSubscriptionsChanged() { - if (DBG) log("callback: received, sendEmptyMessage(0) to handler"); - mHandler.sendEmptyMessage(0); - } - }; - private void log(String s) { Rlog.d(LOG_TAG, s); } @@ -1018,21 +1009,19 @@ public class SubscriptionManager { * onSubscriptionsChanged overridden. */ public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + if (listener == null) return; String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { logd("register OnSubscriptionsChangedListener pkgName=" + pkgName + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available. Where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.addOnSubscriptionsChangedListener(pkgName, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available. Where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.addOnSubscriptionsChangedListener(listener, + listener.mExecutor); } } @@ -1044,21 +1033,18 @@ public class SubscriptionManager { * @param listener that is to be unregistered. */ public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + if (listener == null) return; String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener); } } @@ -1077,7 +1063,6 @@ public class SubscriptionManager { * for #onOpportunisticSubscriptionsChanged to be invoked. */ public static class OnOpportunisticSubscriptionsChangedListener { - private Executor mExecutor; /** * Callback invoked when there is any change to any SubscriptionInfo. Typically * this method would invoke {@link #getActiveSubscriptionInfoList} @@ -1086,27 +1071,6 @@ public class SubscriptionManager { if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN"); } - private void setExecutor(Executor executor) { - mExecutor = executor; - } - - /** - * The callback methods need to be called on the handler thread where - * this object was created. If the binder did that for us it'd be nice. - */ - IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { - @Override - public void onSubscriptionsChanged() { - final long identity = Binder.clearCallingIdentity(); - try { - if (DBG) log("onOpportunisticSubscriptionsChanged callback received."); - mExecutor.execute(() -> onOpportunisticSubscriptionsChanged()); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - }; - private void log(String s) { Rlog.d(LOG_TAG, s); } @@ -1133,18 +1097,13 @@ public class SubscriptionManager { + " listener=" + listener); } - listener.setExecutor(executor); - - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available. Where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + // We use the TelephonyRegistry as it runs in the system and thus is always + // available where as SubscriptionController could crash and not be available + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener( + listener, executor); } } @@ -1164,16 +1123,10 @@ public class SubscriptionManager { logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" + pkgForDebug + " listener=" + listener); } - try { - // We use the TelephonyRegistry as it runs in the system and thus is always - // available where as SubscriptionController could crash and not be available - ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - if (tr != null) { - tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); - } - } catch (RemoteException ex) { - Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex); + TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistryManager != null) { + telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener); } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 55212cd969f0..46f5ebb79723 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -7673,8 +7673,8 @@ public class TelephonyManager { */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @SystemApi - public boolean isTetherApnRequired() { - return isTetherApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId())); + public boolean isTetheringApnRequired() { + return isTetheringApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId())); } /** @@ -7684,11 +7684,11 @@ public class TelephonyManager { * @return {@code true} if DUN APN is required for tethering. * @hide */ - public boolean isTetherApnRequired(int subId) { + public boolean isTetheringApnRequired(int subId) { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.isTetherApnRequiredForSubscriber(subId); + return telephony.isTetheringApnRequiredForSubscriber(subId); } catch (RemoteException ex) { Rlog.e(TAG, "hasMatchedTetherApnSetting RemoteException", ex); } catch (NullPointerException ex) { diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index eb0e2f7b8786..5fd0af564d34 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -979,25 +979,25 @@ public class ImsMmTelManager implements RegistrationManager { /** * Get the status of the MmTel Feature registered on this subscription. + * @param executor The executor that will be used to call the callback. * @param callback A callback containing an Integer describing the current state of the * MmTel feature, Which will be one of the following: * {@link ImsFeature#STATE_UNAVAILABLE}, * {@link ImsFeature#STATE_INITIALIZING}, * {@link ImsFeature#STATE_READY}. Will be called using the executor * specified when the service state has been retrieved from the IMS service. - * @param executor The executor that will be used to call the callback. * @throws ImsException if the IMS service associated with this subscription is not available or * the IMS service is not available. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void getFeatureState(@NonNull @ImsFeature.ImsState Consumer<Integer> callback, - @NonNull @CallbackExecutor Executor executor) throws ImsException { - if (callback == null) { - throw new IllegalArgumentException("Must include a non-null Consumer."); - } + public void getFeatureState(@NonNull @CallbackExecutor Executor executor, + @NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } + if (callback == null) { + throw new IllegalArgumentException("Must include a non-null Consumer."); + } try { getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() { @Override diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 119f890bcb7b..e96d082ca953 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -199,12 +199,19 @@ public class RcsFeature extends ImsFeature { /** @hide*/ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CAPABILITY_TYPE_", flag = true, value = { + CAPABILITY_TYPE_NONE, CAPABILITY_TYPE_OPTIONS_UCE, CAPABILITY_TYPE_PRESENCE_UCE }) public @interface RcsImsCapabilityFlag {} /** + * Undefined capability type for initialization + * @hide + */ + public static final int CAPABILITY_TYPE_NONE = 0; + + /** * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS. * If not set, this RcsFeature should not service capability requests. diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index b502ee711107..2f18049e7e71 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -819,7 +819,7 @@ interface ITelephony { * @return {@code true} if DUN APN is required for tethering. * @hide */ - boolean isTetherApnRequiredForSubscriber(int subId); + boolean isTetheringApnRequiredForSubscriber(int subId); /** * Enables framework IMS and triggers IMS Registration. diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java index c3d490a6d5cf..5766287d6691 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java @@ -25,17 +25,17 @@ import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; +import android.telephony.CbGeoUtils; +import android.telephony.CbGeoUtils.Circle; +import android.telephony.CbGeoUtils.Geometry; +import android.telephony.CbGeoUtils.LatLng; +import android.telephony.CbGeoUtils.Polygon; import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; import android.util.Pair; import android.util.Slog; import com.android.internal.R; -import com.android.internal.telephony.CbGeoUtils; -import com.android.internal.telephony.CbGeoUtils.Circle; -import com.android.internal.telephony.CbGeoUtils.Geometry; -import com.android.internal.telephony.CbGeoUtils.LatLng; -import com.android.internal.telephony.CbGeoUtils.Polygon; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsConstants; import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java index d85cf151b9eb..11bc5de08c66 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java @@ -33,7 +33,7 @@ import java.util.Locale; * All relevant header information is now sent as a Parcelable * {@link android.telephony.SmsCbMessage} object in the "message" extra of the * {@link android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION} or - * {@link android.provider.Telephony.Sms.Intents#SMS_EMERGENCY_CB_RECEIVED_ACTION} intent. + * {@link android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED} intent. * The raw PDU is no longer sent to SMS CB applications. */ public class SmsCbHeader { diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp new file mode 100644 index 000000000000..5e9ef8efc402 --- /dev/null +++ b/tests/PlatformCompatGating/Android.bp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "PlatformCompatGating", + // Only compile source java files in this apk. + srcs: ["src/**/*.java"], + certificate: "platform", + libs: [ + "android.test.runner", + "android.test.base", + ], + static_libs: [ + "junit", + "android-support-test", + "mockito-target-minus-junit4", + "truth-prebuilt", + "platform-compat-test-rules" + ], +} diff --git a/tests/PlatformCompatGating/AndroidManifest.xml b/tests/PlatformCompatGating/AndroidManifest.xml new file mode 100644 index 000000000000..7f14b83fbc75 --- /dev/null +++ b/tests/PlatformCompatGating/AndroidManifest.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tests.gating"> + <application android:label="GatingTest"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.tests.gating"/> +</manifest> diff --git a/tests/PlatformCompatGating/AndroidTest.xml b/tests/PlatformCompatGating/AndroidTest.xml new file mode 100644 index 000000000000..c62684837332 --- /dev/null +++ b/tests/PlatformCompatGating/AndroidTest.xml @@ -0,0 +1,30 @@ +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Test compatibility change gating."> + <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="PlatformCompatGating.apk"/> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/> + <option name="test-suite-tag" value="apct"/> + <option name="test-tag" value="Gating"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.tests.gating"/> + <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java b/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java new file mode 100644 index 000000000000..731be8e3d9f0 --- /dev/null +++ b/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.compat.testing; + +import android.compat.Compatibility; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.compat.IPlatformCompat; + +/** + * This is a dummy API to test gating + * + * @hide + */ +public class DummyApi { + + public static final long CHANGE_ID = 666013; + public static final long CHANGE_ID_1 = 666014; + public static final long CHANGE_ID_2 = 666015; + public static final long CHANGE_SYSTEM_SERVER = 666016; + + /** + * Dummy method + * @return "A" if change is enabled, "B" otherwise. + */ + public static String dummyFunc() { + if (Compatibility.isChangeEnabled(CHANGE_ID)) { + return "A"; + } + return "B"; + } + + /** + * Dummy combined method + * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled, + "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled, + "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled, + "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled. + */ + public static String dummyCombinedFunc() { + if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "0"; + } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1) + && Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "1"; + } else if (Compatibility.isChangeEnabled(CHANGE_ID_1) + && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { + return "2"; + } + return "3"; + } + + /** + * Dummy api using system server API. + */ + public static boolean dummySystemServer(Context context) { + IPlatformCompat platformCompat = IPlatformCompat.Stub + .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + if (platformCompat == null) { + throw new RuntimeException("Could not obtain IPlatformCompat instance!"); + } + String packageName = context.getPackageName(); + try { + return platformCompat.isChangeEnabledByPackageName(CHANGE_SYSTEM_SERVER, packageName, + context.getUserId()); + } catch (RemoteException e) { + throw new RuntimeException("Could not get change value!", e); + } + } +} diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java new file mode 100644 index 000000000000..dc317f1941c7 --- /dev/null +++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tests.gating; + +import static com.google.common.truth.Truth.assertThat; + +import android.compat.testing.PlatformCompatChangeRule; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import com.android.compat.testing.DummyApi; + +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; + +/** + * Tests for platform compatibility change gating. + */ +@RunWith(AndroidJUnit4.class) +public class PlatformCompatGatingTest { + + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingPositive() { + assertThat(DummyApi.dummyFunc()).isEqualTo("A"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID}) + public void testDummyGatingNegative() { + assertThat(DummyApi.dummyFunc()).isEqualTo("B"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined0() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0"); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_ID_1}) + @EnableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined1() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1}) + @DisableCompatChanges({DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined2() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) + public void testDummyGatingCombined3() { + assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3"); + } + + @Test + @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) + public void testDummyGatingPositiveSystemServer() { + assertThat( + DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue(); + } + + @Test + @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) + public void testDummyGatingNegativeSystemServer() { + assertThat( + DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse(); + } +} diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp new file mode 100644 index 000000000000..8211ef523ee7 --- /dev/null +++ b/tests/PlatformCompatGating/test-rules/Android.bp @@ -0,0 +1,26 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +java_library { + name: "platform-compat-test-rules", + srcs: ["src/**/*.java"], + static_libs: [ + "junit", + "android-support-test", + "truth-prebuilt", + "core-compat-test-rules" + ], +}
\ No newline at end of file diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java new file mode 100644 index 000000000000..932ec643d478 --- /dev/null +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.compat.testing; + +import android.app.Instrumentation; +import android.compat.Compatibility; +import android.compat.Compatibility.ChangeConfig; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.support.test.InstrumentationRegistry; + +import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.IPlatformCompat; + +import libcore.junit.util.compat.CoreCompatChangeRule; + +import org.junit.runners.model.Statement; + +/** + * Allows tests to specify the which change to disable. + * + * <p>To use add the following to the test class. It will only change the behavior of a test method + * if it is annotated with + * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or + * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges}. + * </p> + * <pre> + * @Rule + * public TestRule compatChangeRule = new PlatformCompatChangeRule(); + * </pre> + * + * <p>Each test method that needs to disable a specific change needs to be annotated + * with {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or + * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} specifying the change + * id. e.g.: + * </p> + * <pre> + * @Test + * @DisableCompatChanges({42}) + * public void testAsIfChange42Disabled() { + * // check behavior + * } + * + * @Test + * @EnableCompatChanges({42}) + * public void testAsIfChange42Enabled() { + * // check behavior + * + * </pre> + */ +public class PlatformCompatChangeRule extends CoreCompatChangeRule { + + @Override + protected Statement createStatementForConfig(final Statement statement, ChangeConfig config) { + return new CompatChangeStatement(statement, config); + } + + + private static class CompatChangeStatement extends Statement { + private final Statement mTestStatement; + private final ChangeConfig mConfig; + + private CompatChangeStatement(Statement testStatement, ChangeConfig config) { + this.mTestStatement = testStatement; + this.mConfig = config; + } + + @Override + public void evaluate() throws Throwable { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + String packageName = instrumentation.getTargetContext().getPackageName(); + IPlatformCompat platformCompat = IPlatformCompat.Stub + .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + if (platformCompat == null) { + throw new IllegalStateException("Could not get IPlatformCompat service!"); + } + Compatibility.setOverrides(mConfig); + try { + platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), + packageName); + try { + mTestStatement.evaluate(); + } finally { + platformCompat.clearOverridesForTest(packageName); + } + } catch (RemoteException e) { + throw new RuntimeException("Could not call IPlatformCompat binder method!", e); + } finally { + Compatibility.clearOverrides(); + } + } + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 61f37fd6c7e2..aad2f3da40f2 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -20,6 +20,9 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; +import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; +import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; +import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; @@ -28,6 +31,7 @@ import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; @@ -145,6 +149,7 @@ import android.net.MatchAllNetworkSpecifier; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkFactory; +import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; @@ -244,6 +249,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; import kotlin.reflect.KClass; @@ -330,6 +336,9 @@ public class ConnectivityServiceTest { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; + // Contains all registered receivers since this object was created. Useful to clear + // them when needed, as BroadcastInterceptingContext does not provide this facility. + private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>(); @Spy private Resources mResources; private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); @@ -343,6 +352,7 @@ public class ConnectivityServiceTest { "wifi,1,1,1,-1,true", "mobile,0,0,0,-1,true", "mobile_mms,2,0,2,60000,true", + "mobile_supl,3,0,2,60000,true", }); when(mResources.getStringArray( @@ -410,6 +420,19 @@ public class ConnectivityServiceTest { // make sure the code does not rely on unexpected permissions. super.enforceCallingOrSelfPermission(permission, message); } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + mRegisteredReceivers.add(receiver); + return super.registerReceiver(receiver, filter); + } + + public void clearRegisteredReceivers() { + // super.unregisterReceiver is a no-op for receivers that are not registered (because + // they haven't been registered or because they have already been unregistered). + // For the same reason, don't bother clearing mRegisteredReceivers. + for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv); + } } private void waitForIdle() { @@ -438,7 +461,7 @@ public class ConnectivityServiceTest { } // Bring up a network that we can use to send messages to ConnectivityService. - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); waitFor(cv); @@ -458,7 +481,7 @@ public class ConnectivityServiceTest { @Ignore public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception { // Bring up a network that we can use to send messages to ConnectivityService. - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); waitFor(cv); @@ -1227,17 +1250,26 @@ public class ConnectivityServiceTest { * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION * broadcasts are received. */ - private ConditionVariable waitForConnectivityBroadcasts(final int count) { + private ConditionVariable registerConnectivityBroadcast(final int count) { + return registerConnectivityBroadcastThat(count, intent -> true); + } + + private ConditionVariable registerConnectivityBroadcastThat(final int count, + @NonNull final Predicate<Intent> filter) { final ConditionVariable cv = new ConditionVariable(); - mServiceContext.registerReceiver(new BroadcastReceiver() { + final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION); + intentFilter.addAction(CONNECTIVITY_ACTION_SUPL); + final BroadcastReceiver receiver = new BroadcastReceiver() { private int remaining = count; public void onReceive(Context context, Intent intent) { + if (!filter.test(intent)) return; if (--remaining == 0) { cv.open(); mServiceContext.unregisterReceiver(this); } } - }, new IntentFilter(CONNECTIVITY_ACTION)); + }; + mServiceContext.registerReceiver(receiver, intentFilter); return cv; } @@ -1258,6 +1290,75 @@ public class ConnectivityServiceTest { } @Test + public void testNetworkFeature() throws Exception { + // Connect the cell agent and wait for the connected broadcast. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL); + final ConditionVariable cv1 = registerConnectivityBroadcastThat(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE); + mCellNetworkAgent.connect(true); + waitFor(cv1); + + // Build legacy request for SUPL. + final NetworkCapabilities legacyCaps = new NetworkCapabilities(); + legacyCaps.addTransportType(TRANSPORT_CELLULAR); + legacyCaps.addCapability(NET_CAPABILITY_SUPL); + final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL, + ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST); + + // Send request and check that the legacy broadcast for SUPL is sent correctly. + final TestNetworkCallback callback = new TestNetworkCallback(); + final ConditionVariable cv2 = registerConnectivityBroadcastThat(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + mCm.requestNetwork(legacyRequest, callback); + callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + waitFor(cv2); + + // File another request, withdraw it and make sure no broadcast is sent + final ConditionVariable cv3 = registerConnectivityBroadcast(1); + final TestNetworkCallback callback2 = new TestNetworkCallback(); + mCm.requestNetwork(legacyRequest, callback2); + callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + mCm.unregisterNetworkCallback(callback2); + assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent + // As the broadcast did not fire, the receiver was not unregistered. Do this now. + mServiceContext.clearRegisteredReceivers(); + + // Withdraw the request and check that the broadcast for disconnection is sent. + final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent -> + !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected() + && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + mCm.unregisterNetworkCallback(callback); + waitFor(cv4); + + // Re-file the request and expect the connected broadcast again + final ConditionVariable cv5 = registerConnectivityBroadcastThat(1, + intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); + final TestNetworkCallback callback3 = new TestNetworkCallback(); + mCm.requestNetwork(legacyRequest, callback3); + callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); + waitFor(cv5); + + // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one + // for mobile. Use a small hack to check that both have been sent, but the order is + // not contractual. + final AtomicBoolean vanillaAction = new AtomicBoolean(false); + final AtomicBoolean suplAction = new AtomicBoolean(false); + final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> { + if (intent.getAction().equals(CONNECTIVITY_ACTION)) { + vanillaAction.set(true); + } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) { + suplAction.set(true); + } + return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected(); + }); + mCellNetworkAgent.disconnect(); + waitFor(cv6); + assertTrue(vanillaAction.get()); + assertTrue(suplAction.get()); + } + + @Test public void testLingering() throws Exception { verifyNoNetwork(); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); @@ -1265,7 +1366,7 @@ public class ConnectivityServiceTest { assertNull(mCm.getActiveNetworkInfo()); assertNull(mCm.getActiveNetwork()); // Test bringing up validated cellular. - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); @@ -1275,7 +1376,7 @@ public class ConnectivityServiceTest { assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); // Test bringing up validated WiFi. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1292,7 +1393,7 @@ public class ConnectivityServiceTest { assertLength(1, mCm.getAllNetworks()); assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(1); + cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.disconnect(); waitFor(cv); verifyNoNetwork(); @@ -1302,7 +1403,7 @@ public class ConnectivityServiceTest { public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { // Test bringing up unvalidated WiFi mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1317,17 +1418,17 @@ public class ConnectivityServiceTest { verifyActiveNetwork(TRANSPORT_WIFI); // Test bringing up validated cellular mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mCellNetworkAgent.disconnect(); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(1); + cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.disconnect(); waitFor(cv); verifyNoNetwork(); @@ -1337,23 +1438,23 @@ public class ConnectivityServiceTest { public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { // Test bringing up unvalidated cellular. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.disconnect(); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(1); + cv = registerConnectivityBroadcast(1); mCellNetworkAgent.disconnect(); waitFor(cv); verifyNoNetwork(); @@ -1363,7 +1464,7 @@ public class ConnectivityServiceTest { public void testUnlingeringDoesNotValidate() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1371,14 +1472,14 @@ public class ConnectivityServiceTest { NET_CAPABILITY_VALIDATED)); // Test bringing up validated cellular. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( NET_CAPABILITY_VALIDATED)); // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mCellNetworkAgent.disconnect(); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1391,23 +1492,23 @@ public class ConnectivityServiceTest { public void testCellularOutscoresWeakWifi() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test bringing up validated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test WiFi getting really weak. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.adjustScore(-11); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test WiFi restoring signal strength. - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.adjustScore(11); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1427,7 +1528,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.expectDisconnected(); // Test bringing up validated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final ConditionVariable cv = waitForConnectivityBroadcasts(1); + final ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -1446,18 +1547,18 @@ public class ConnectivityServiceTest { public void testCellularFallback() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test bringing up validated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Reevaluate WiFi (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( NET_CAPABILITY_VALIDATED)); mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); @@ -1467,7 +1568,7 @@ public class ConnectivityServiceTest { NET_CAPABILITY_VALIDATED)); verifyActiveNetwork(TRANSPORT_CELLULAR); // Reevaluate cellular (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( NET_CAPABILITY_VALIDATED)); mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); @@ -1484,18 +1585,18 @@ public class ConnectivityServiceTest { public void testWiFiFallback() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test bringing up validated cellular. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mCellNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Reevaluate cellular (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( NET_CAPABILITY_VALIDATED)); mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); @@ -1570,7 +1671,7 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); // Test unvalidated networks - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(false); genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); @@ -1585,7 +1686,7 @@ public class ConnectivityServiceTest { assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); @@ -1594,7 +1695,7 @@ public class ConnectivityServiceTest { waitFor(cv); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - cv = waitForConnectivityBroadcasts(2); + cv = registerConnectivityBroadcast(2); mWiFiNetworkAgent.disconnect(); genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); @@ -1602,7 +1703,7 @@ public class ConnectivityServiceTest { waitFor(cv); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - cv = waitForConnectivityBroadcasts(1); + cv = registerConnectivityBroadcast(1); mCellNetworkAgent.disconnect(); genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); @@ -2192,7 +2293,7 @@ public class ConnectivityServiceTest { // Test bringing up validated WiFi. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final ConditionVariable cv = waitForConnectivityBroadcasts(1); + final ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -2220,7 +2321,7 @@ public class ConnectivityServiceTest { public void testMMSonCell() throws Exception { // Test bringing up cellular without MMS mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.connect(false); waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); @@ -3679,7 +3780,7 @@ public class ConnectivityServiceTest { } mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); mWiFiNetworkAgent.connect(true); waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); @@ -4212,7 +4313,7 @@ public class ConnectivityServiceTest { assertNotPinnedToWifi(); // Disconnect cell and wifi. - ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down. + ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down. mCellNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect(); waitFor(cv); @@ -4225,7 +4326,7 @@ public class ConnectivityServiceTest { assertPinnedToWifiWithWifiDefault(); // ... and is maintained even when that network is no longer the default. - cv = waitForConnectivityBroadcasts(1); + cv = registerConnectivityBroadcast(1); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mCellNetworkAgent.connect(true); waitFor(cv); @@ -4326,7 +4427,7 @@ public class ConnectivityServiceTest { @Test public void testNetworkInfoOfTypeNone() throws Exception { - ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1); + ConditionVariable broadcastCV = registerConnectivityBroadcast(1); verifyNoNetwork(); TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE); @@ -5778,7 +5879,7 @@ public class ConnectivityServiceTest { .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); // Disconnect wifi - ConditionVariable cv = waitForConnectivityBroadcasts(1); + ConditionVariable cv = registerConnectivityBroadcast(1); reset(mNetworkManagementService); mWiFiNetworkAgent.disconnect(); waitFor(cv); diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt index f045369459c9..42d4cf3c382b 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -18,6 +18,7 @@ package com.android.server import android.net.ConnectivityManager.TYPE_ETHERNET import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_MOBILE_SUPL import android.net.ConnectivityManager.TYPE_WIFI import android.net.ConnectivityManager.TYPE_WIMAX import android.net.NetworkInfo.DetailedState.CONNECTED @@ -46,7 +47,7 @@ const val UNSUPPORTED_TYPE = TYPE_WIMAX @RunWith(AndroidJUnit4::class) @SmallTest class LegacyTypeTrackerTest { - private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET) + private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL) private val mMockService = mock(ConnectivityService::class.java).apply { doReturn(false).`when`(this).isDefaultNetwork(any()) @@ -70,6 +71,26 @@ class LegacyTypeTrackerTest { } @Test + fun testSupl() { + val mobileNai = mock(NetworkAgentInfo::class.java) + mTracker.add(TYPE_MOBILE, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE) + reset(mMockService) + mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) + reset(mMockService) + mTracker.remove(mobileNai, false) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE) + } + + @Test fun testAddNetwork() { val mobileNai = mock(NetworkAgentInfo::class.java) val wifiNai = mock(NetworkAgentInfo::class.java) diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index 5f62c08f55f3..9e5717b4bd64 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -208,6 +208,12 @@ public class TetheringTest { if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; return super.getSystemService(name); } + + @Override + public String getSystemServiceName(Class<?> serviceClass) { + if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE; + return super.getSystemServiceName(serviceClass); + } } public class MockIpServerDependencies extends IpServer.Dependencies { diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 1d29a824d10d..4d42a612030d 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -192,8 +192,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService = new NetworkStatsService( mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock, - TelephonyManager.getDefault(), mSettings, mStatsFactory, - new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); + mServiceContext.getSystemService(TelephonyManager.class), mSettings, + mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); mHandlerThread = new HandlerThread("HandlerThread"); mHandlerThread.start(); Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService); diff --git a/tools/genprotos.sh b/tools/genprotos.sh deleted file mode 100755 index f901c9f588b6..000000000000 --- a/tools/genprotos.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can -# end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to -# the way sbox rewrites the command. See b/70221552. - -set -e - -location_aprotoc=$1 -location_protoc=$2 -location_soong_zip=$3 -genDir=$4 -depfile=$5 -in=$6 -out=$7 - -mkdir -p ${genDir}/${in} && \ - ${location_aprotoc} --plugin=${location_protoc} \ - --dependency_out=${depfile} \ - --javastream_out=${genDir}/${in} \ - -Iexternal/protobuf/src \ - -I . \ - ${in} && \ - ${location_soong_zip} -jar -o ${out} -C ${genDir}/${in} -D ${genDir}/${in} diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp index 0e33fddcde07..1e96234543c8 100644 --- a/tools/processors/unsupportedappusage/Android.bp +++ b/tools/processors/unsupportedappusage/Android.bp @@ -1,11 +1,6 @@ -java_plugin { - name: "unsupportedappusage-annotation-processor", - processor_class: "android.processor.unsupportedappusage.UnsupportedAppUsageProcessor", - - java_resources: [ - "META-INF/**/*", - ], +java_library_host { + name: "unsupportedappusage-annotation-processor-lib", srcs: [ "src/**/*.java", ], @@ -22,6 +17,18 @@ java_plugin { "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", ], }, +} + +java_plugin { + name: "unsupportedappusage-annotation-processor", + processor_class: "android.processor.unsupportedappusage.UnsupportedAppUsageProcessor", + + java_resources: [ + "META-INF/**/*", + ], + static_libs: [ + "unsupportedappusage-annotation-processor-lib" + ], use_tools_jar: true, } diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java index 5a5703ed520c..65fc733fa364 100644 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java +++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java @@ -101,14 +101,20 @@ public class SignatureBuilder { private String getClassSignature(TypeElement clazz) { StringBuilder sb = new StringBuilder("L"); for (Element enclosing : getEnclosingElements(clazz)) { - if (enclosing.getKind() == PACKAGE) { - sb.append(((PackageElement) enclosing) - .getQualifiedName() - .toString() - .replace('.', '/')); - sb.append('/'); - } else { - sb.append(enclosing.getSimpleName()).append('$'); + switch (enclosing.getKind()) { + case MODULE: + // ignore this. + break; + case PACKAGE: + sb.append(((PackageElement) enclosing) + .getQualifiedName() + .toString() + .replace('.', '/')); + sb.append('/'); + break; + default: + sb.append(enclosing.getSimpleName()).append('$'); + break; } } diff --git a/tools/processors/unsupportedappusage/test/Android.bp b/tools/processors/unsupportedappusage/test/Android.bp new file mode 100644 index 000000000000..49ea3d4bbc96 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/Android.bp @@ -0,0 +1,28 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +java_test_host { + name: "unsupportedappusage-processor-test", + + srcs: ["src/**/*.java"], + + static_libs: [ + "libjavac", + "unsupportedappusage-annotation-processor-lib", + "truth-host-prebuilt", + "mockito-host", + "junit-host", + "objenesis", + ], +} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java new file mode 100644 index 000000000000..23db99e81194 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.processor.unsupportedappusage; + +import com.google.common.base.Splitter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CsvReader { + + private final Splitter mSplitter; + private final List<String> mColumns; + private final List<Map<String, String>> mContents; + + public CsvReader(InputStream in) throws IOException { + mSplitter = Splitter.on(","); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + mColumns = mSplitter.splitToList(br.readLine()); + mContents = new ArrayList<>(); + String line = br.readLine(); + while (line != null) { + List<String> contents = mSplitter.splitToList(line); + Map<String, String> contentMap = new HashMap<>(); + for (int i = 0; i < Math.min(contents.size(), mColumns.size()); ++i) { + contentMap.put(mColumns.get(i), contents.get(i)); + } + mContents.add(contentMap); + line = br.readLine(); + } + br.close(); + } + + public List<String> getColumns() { + return mColumns; + } + + public List<Map<String, String>> getContents() { + return mContents; + } +} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java new file mode 100644 index 000000000000..012e88f17924 --- /dev/null +++ b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.processor.unsupportedappusage; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.javac.Javac; + +import com.google.common.base.Joiner; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Map; + +public class UnsupportedAppUsageProcessorTest { + + private Javac mJavac; + + @Before + public void setup() throws IOException { + mJavac = new Javac(); + mJavac.addSource("dalvik.annotation.compat.UnsupportedAppUsage", Joiner.on('\n').join( + "package dalvik.annotation.compat;", + "public @interface UnsupportedAppUsage {", + " String expectedSignature() default \"\";\n", + " String someProperty() default \"\";", + "}")); + } + + private CsvReader compileAndReadCsv() throws IOException { + mJavac.compileWithAnnotationProcessor(new UnsupportedAppUsageProcessor()); + return new CsvReader( + mJavac.getOutputFile("unsupportedappusage/unsupportedappusage_index.csv")); + } + + @Test + public void testSignatureFormat() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", + "import dalvik.annotation.compat.UnsupportedAppUsage;", + "public class Class {", + " @UnsupportedAppUsage", + " public void method() {}", + "}")); + assertThat(compileAndReadCsv().getContents().get(0)).containsEntry( + "signature", "La/b/Class;->method()V" + ); + } + + @Test + public void testSourcePosition() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", // 1 + "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 + "public class Class {", // 3 + " @UnsupportedAppUsage", // 4 + " public void method() {}", // 5 + "}")); + Map<String, String> row = compileAndReadCsv().getContents().get(0); + assertThat(row).containsEntry("startline", "4"); + assertThat(row).containsEntry("startcol", "3"); + assertThat(row).containsEntry("endline", "4"); + assertThat(row).containsEntry("endcol", "23"); + } + + @Test + public void testAnnotationProperties() throws Exception { + mJavac.addSource("a.b.Class", Joiner.on('\n').join( + "package a.b;", // 1 + "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 + "public class Class {", // 3 + " @UnsupportedAppUsage(someProperty=\"value\")", // 4 + " public void method() {}", // 5 + "}")); + assertThat(compileAndReadCsv().getContents().get(0)).containsEntry( + "properties", "someProperty=%22value%22"); + } + + +} |