summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp29
-rw-r--r--api/current.txt15
-rw-r--r--api/system-current.txt30
-rw-r--r--api/test-current.txt13
-rw-r--r--cmds/idmap/create.cpp233
-rw-r--r--cmds/idmap/idmap.cpp283
-rw-r--r--cmds/idmap/idmap.h38
-rw-r--r--cmds/idmap/inspect.cpp313
-rw-r--r--cmds/idmap/scan.cpp281
-rw-r--r--cmds/statsd/Android.bp2
-rw-r--r--cmds/statsd/src/StatsService.cpp4
-rw-r--r--cmds/statsd/src/external/PullResultReceiver.cpp43
-rw-r--r--cmds/statsd/src/external/PullResultReceiver.h43
-rw-r--r--cmds/statsd/src/external/StatsCallbackPuller.cpp73
-rw-r--r--cmds/statsd/src/external/StatsCallbackPuller.h7
-rw-r--r--cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp63
-rw-r--r--cmds/statsd/src/external/StatsCallbackPullerDeprecated.h (renamed from services/tests/servicestests/src/com/android/server/pm/UserTests.java)38
-rw-r--r--cmds/statsd/src/external/StatsPuller.cpp10
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp159
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.h34
-rw-r--r--cmds/statsd/src/external/puller_util.cpp4
-rw-r--r--config/hiddenapi-greylist-max-q.txt703
-rw-r--r--config/hiddenapi-greylist.txt703
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java54
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java2
-rw-r--r--core/java/android/accounts/AccountAuthenticatorActivity.java4
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/IUiModeManager.aidl13
-rw-r--r--core/java/android/app/StatsManager.java2
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/UiModeManager.java178
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java50
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java18
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java50
-rw-r--r--core/java/android/content/ContextWrapper.java1
-rw-r--r--core/java/android/content/res/AssetManager.java58
-rw-r--r--core/java/android/os/Handler.java34
-rw-r--r--core/java/android/provider/AndroidDeviceConfig.java48
-rw-r--r--core/java/android/provider/BlockedNumberContract.java56
-rw-r--r--core/java/android/provider/CallLog.java16
-rw-r--r--core/java/android/provider/DeviceConfig.java57
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java34
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/widget/Editor.java3
-rw-r--r--core/java/android/widget/ProgressBar.java52
-rw-r--r--core/java/android/widget/Toast.java10
-rw-r--r--core/java/com/android/internal/app/DisableCarModeActivity.java4
-rw-r--r--core/java/com/android/internal/compat/IPlatformCompat.aidl9
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/OmniFunction.java21
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/PooledLambda.java63
-rw-r--r--core/jni/AndroidRuntime.cpp6
-rw-r--r--core/jni/android_util_AssetManager.cpp102
-rw-r--r--core/proto/android/server/windowmanagerservice.proto3
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--data/etc/privapp-permissions-platform.xml3
-rw-r--r--data/etc/services.core.protolog.json18
-rw-r--r--keystore/java/android/security/KeyStore.java29
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java2
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java8
-rw-r--r--keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java9
-rw-r--r--location/TEST_MAPPING10
-rw-r--r--media/java/android/media/MediaRoute2Info.java34
-rw-r--r--media/jni/soundpool/StreamManager.cpp3
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java43
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java174
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java98
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/AndroidManifest.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java103
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java272
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java97
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java5
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java2
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java10
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java7
-rw-r--r--services/core/Android.bp6
-rw-r--r--services/core/java/com/android/server/TEST_MAPPING9
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java330
-rw-r--r--services/core/java/com/android/server/VibratorService.java4
-rw-r--r--services/core/java/com/android/server/Watchdog.java1
-rw-r--r--services/core/java/com/android/server/compat/PlatformCompat.java6
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleXmlParser.java68
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java33
-rw-r--r--services/core/java/com/android/server/location/TEST_MAPPING10
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java82
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java49
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java25
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java202
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java74
-rw-r--r--services/core/java/com/android/server/pm/Installer.java22
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java24
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java42
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java27
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java23
-rw-r--r--services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java34
-rw-r--r--services/core/java/com/android/server/wm/Task.java30
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotCache.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerConstants.java171
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java74
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java7
-rw-r--r--services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java110
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp473
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp6
-rw-r--r--services/net/java/android/net/NetworkStackClient.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java366
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java159
-rw-r--r--services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java172
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java144
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java129
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java161
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java8
-rw-r--r--telephony/common/com/android/internal/telephony/GsmAlphabet.java (renamed from telephony/java/com/android/internal/telephony/GsmAlphabet.java)0
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java12
-rw-r--r--telephony/java/android/telephony/DisconnectCause.java8
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java8
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java7
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl2
-rw-r--r--tests/PlatformCompatGating/Android.bp33
-rw-r--r--tests/PlatformCompatGating/AndroidManifest.xml11
-rw-r--r--tests/PlatformCompatGating/AndroidTest.xml30
-rw-r--r--tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java87
-rw-r--r--tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java94
-rw-r--r--tests/PlatformCompatGating/test-rules/Android.bp26
-rw-r--r--tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java108
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java185
-rw-r--r--tests/net/java/com/android/server/LegacyTypeTrackerTest.kt23
-rwxr-xr-xtools/genprotos.sh24
-rw-r--r--tools/processors/unsupportedappusage/Android.bp21
-rw-r--r--tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java22
-rw-r--r--tools/processors/unsupportedappusage/test/Android.bp (renamed from cmds/idmap/Android.bp)32
-rw-r--r--tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java61
-rw-r--r--tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java96
152 files changed, 5658 insertions, 3557 deletions
diff --git a/Android.bp b/Android.bp
index 611d4ba18367..fd1239cea337 100644
--- a/Android.bp
+++ b/Android.bp
@@ -535,24 +535,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",
@@ -808,7 +806,6 @@ aidl_interface {
enabled: true,
},
},
- api_dir: "aidl/incremental",
}
gensrcs {
@@ -952,7 +949,10 @@ framework_docs_only_args = " -android -manifest $(location core/res/AndroidManif
"-overview $(location core/java/overview.html) " +
// Federate Support Library references against local API file.
"-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location :current-support-api) "
+ "-federationapi SupportLib $(location :current-support-api) " +
+ // Federate Support Library references against local API file.
+ "-federate AndroidX https://developer.android.com " +
+ "-federationapi AndroidX $(location :current-androidx-api) "
framework_docs_only_libs = [
"voip-common",
@@ -1063,6 +1063,7 @@ doc_defaults {
"core/res/AndroidManifest.xml",
"core/java/overview.html",
":current-support-api",
+ ":current-androidx-api",
],
create_stubs: false,
}
diff --git a/api/current.txt b/api/current.txt
index 010f383fb0ed..ee9363751a00 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3047,9 +3047,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 {
@@ -34834,8 +34834,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);
@@ -36846,7 +36846,6 @@ package android.provider {
method @WorkerThread public static boolean isBlocked(android.content.Context, String);
method @WorkerThread public static int unblock(android.content.Context, String);
field public static final String AUTHORITY = "com.android.blockednumber";
- field public static final android.net.Uri AUTHORITY_URI;
}
public static class BlockedNumberContract.BlockedNumbers {
@@ -43869,6 +43868,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
@@ -44397,6 +44397,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";
@@ -44413,7 +44414,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/system-current.txt b/api/system-current.txt
index 412e0959570c..c13afb6137b9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -68,6 +68,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";
@@ -77,6 +78,7 @@ package android {
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 GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS";
+ 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";
@@ -646,6 +648,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();
@@ -1284,7 +1295,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();
@@ -6117,6 +6130,19 @@ package android.printservice.recommendation {
package android.provider {
+ public class BlockedNumberContract {
+ field @NonNull public static final android.net.Uri AUTHORITY_URI;
+ field public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
+ field public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
+ field public static final String RES_BLOCK_STATUS = "block_status";
+ field public static final int STATUS_BLOCKED_IN_LIST = 1; // 0x1
+ field public static final int STATUS_BLOCKED_NOT_IN_CONTACTS = 5; // 0x5
+ field public static final int STATUS_BLOCKED_PAYPHONE = 4; // 0x4
+ field public static final int STATUS_BLOCKED_RESTRICTED = 2; // 0x2
+ field public static final int STATUS_BLOCKED_UNKNOWN_NUMBER = 3; // 0x3
+ field public static final int STATUS_NOT_BLOCKED = 0; // 0x0
+ }
+
public static final class ContactsContract.MetadataSync implements android.provider.BaseColumns android.provider.ContactsContract.MetadataSyncColumns {
field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
@@ -8119,6 +8145,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
@@ -8693,7 +8720,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();
@@ -8784,6 +8811,7 @@ package android.telephony {
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);
diff --git a/api/test-current.txt b/api/test-current.txt
index 19e12127c115..897e82558e2d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -420,6 +420,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();
}
@@ -2358,6 +2359,11 @@ package android.print {
package android.provider {
+ public interface AndroidDeviceConfig {
+ field public static final String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE = "system_gestures_excluded_by_pre_q_sticky_immersive";
+ field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+ }
+
public static final class CalendarContract.Calendars implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
field public static final String[] SYNC_WRITABLE_COLUMNS;
}
@@ -2393,13 +2399,13 @@ package android.provider {
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
+ field public static final String NAMESPACE_ANDROID = "android";
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
field public static final String NAMESPACE_ROLLBACK = "rollback";
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
- field public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
}
public static interface DeviceConfig.OnPropertiesChangedListener {
@@ -2416,11 +2422,6 @@ package android.provider {
method @Nullable public String getString(@NonNull String, @Nullable String);
}
- public static interface DeviceConfig.WindowManager {
- field public static final String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE = "system_gestures_excluded_by_pre_q_sticky_immersive";
- field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
- }
-
public final class MediaStore {
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
deleted file mode 100644
index f415f8f5dd75..000000000000
--- a/cmds/idmap/create.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "idmap.h"
-
-#include <memory>
-#include <androidfw/AssetManager.h>
-#include <androidfw/ResourceTypes.h>
-#include <androidfw/ZipFileRO.h>
-#include <utils/String8.h>
-
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-using namespace android;
-
-namespace {
- int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc)
- {
- std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(zip_path));
- if (zip.get() == NULL) {
- return -1;
- }
- ZipEntryRO entry = zip->findEntryByName(entry_name);
- if (entry == NULL) {
- return -1;
- }
- if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, crc)) {
- return -1;
- }
- zip->releaseEntry(entry);
- return 0;
- }
-
- int open_idmap(const char *path)
- {
- int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644));
- if (fd == -1) {
- ALOGD("error: open %s: %s\n", path, strerror(errno));
- goto fail;
- }
- if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
- ALOGD("error: fchmod %s: %s\n", path, strerror(errno));
- goto fail;
- }
- if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) {
- ALOGD("error: flock %s: %s\n", path, strerror(errno));
- goto fail;
- }
-
- return fd;
-fail:
- if (fd != -1) {
- close(fd);
- unlink(path);
- }
- return -1;
- }
-
- int write_idmap(int fd, const uint32_t *data, size_t size)
- {
- if (lseek(fd, 0, SEEK_SET) < 0) {
- return -1;
- }
- size_t bytesLeft = size;
- while (bytesLeft > 0) {
- ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft));
- if (w < 0) {
- fprintf(stderr, "error: write: %s\n", strerror(errno));
- return -1;
- }
- bytesLeft -= static_cast<size_t>(w);
- }
- return 0;
- }
-
- bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd)
- {
- static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES;
- struct stat st;
- if (fstat(idmap_fd, &st) == -1) {
- return true;
- }
- if (st.st_size < static_cast<off_t>(N)) {
- // file is empty or corrupt
- return true;
- }
-
- char buf[N];
- size_t bytesLeft = N;
- if (lseek(idmap_fd, 0, SEEK_SET) < 0) {
- return true;
- }
- for (;;) {
- ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft));
- if (r < 0) {
- return true;
- }
- bytesLeft -= static_cast<size_t>(r);
- if (bytesLeft == 0) {
- break;
- }
- if (r == 0) {
- // "shouldn't happen"
- return true;
- }
- }
-
- uint32_t version, cached_target_crc, cached_overlay_crc;
- String8 cached_target_path, cached_overlay_path;
- if (!ResTable::getIdmapInfo(buf, N, &version, &cached_target_crc, &cached_overlay_crc,
- &cached_target_path, &cached_overlay_path)) {
- return true;
- }
-
- if (version != ResTable::IDMAP_CURRENT_VERSION) {
- return true;
- }
-
- if (cached_target_path != target_apk_path) {
- return true;
- }
- if (cached_overlay_path != overlay_apk_path) {
- return true;
- }
-
- uint32_t actual_target_crc, actual_overlay_crc;
- if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
- &actual_target_crc) == -1) {
- return true;
- }
- if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
- &actual_overlay_crc) == -1) {
- return true;
- }
-
- return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc;
- }
-
- bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_path)
- {
- struct stat st;
- if (stat(idmap_path, &st) == -1) {
- // non-existing idmap is always stale; on other errors, abort idmap generation
- return errno == ENOENT;
- }
-
- int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY));
- if (idmap_fd == -1) {
- return false;
- }
- bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd);
- close(idmap_fd);
- return is_stale;
- }
-
- int create_idmap(const char *target_apk_path, const char *overlay_apk_path,
- uint32_t **data, size_t *size)
- {
- uint32_t target_crc, overlay_crc;
- if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
- &target_crc) == -1) {
- return -1;
- }
- if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
- &overlay_crc) == -1) {
- return -1;
- }
-
- AssetManager am;
- bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc,
- data, size);
- return b ? 0 : -1;
- }
-
- int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path,
- int fd, bool check_if_stale)
- {
- if (check_if_stale) {
- if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) {
- // already up to date -- nothing to do
- return 0;
- }
- }
-
- uint32_t *data = NULL;
- size_t size;
-
- if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) {
- return -1;
- }
-
- if (write_idmap(fd, data, size) == -1) {
- free(data);
- return -1;
- }
-
- free(data);
- return 0;
- }
-}
-
-int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_path)
-{
- if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) {
- // already up to date -- nothing to do
- return EXIT_SUCCESS;
- }
-
- int fd = open_idmap(idmap_path);
- if (fd == -1) {
- return EXIT_FAILURE;
- }
-
- int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false);
- close(fd);
- if (r != 0) {
- unlink(idmap_path);
- }
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
-{
- return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ?
- EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-int idmap_verify_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
-{
- return !is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd) ?
- EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
deleted file mode 100644
index 8f86ed8f7d32..000000000000
--- a/cmds/idmap/idmap.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-#include "idmap.h"
-
-#include <private/android_filesystem_config.h> // for AID_SYSTEM
-
-#include <stdlib.h>
-#include <string.h>
-
-namespace {
- const char *usage = "NAME\n\
- idmap - create or display idmap files\n\
-\n\
-SYNOPSIS \n\
- idmap --help \n\
- idmap --fd target overlay fd \n\
- idmap --path target overlay idmap \n\
- idmap --scan target-package-name-to-look-for path-to-target-apk dir-to-hold-idmaps \\\
- dir-to-scan [additional-dir-to-scan [additional-dir-to-scan [...]]]\n\
- idmap --inspect idmap \n\
- idmap --verify target overlay fd \n\
-\n\
-DESCRIPTION \n\
- Idmap files play an integral part in the runtime resource overlay framework. An idmap \n\
- file contains a mapping of resource identifiers between overlay package and its target \n\
- package; this mapping is used during resource lookup. Idmap files also act as control \n\
- files by their existence: if not present, the corresponding overlay package is ignored \n\
- when the resource context is created. \n\
-\n\
- Idmap files are stored in /data/resource-cache. For each pair (target package, overlay \n\
- package), there exists exactly one idmap file, or none if the overlay should not be used. \n\
-\n\
-NOMENCLATURE \n\
- target: the original, non-overlay, package. Each target package may be associated with \n\
- any number of overlay packages. \n\
-\n\
- overlay: an overlay package. Each overlay package is associated with exactly one target \n\
- package, specified in the overlay's manifest using the <overlay target=\"...\"/> \n\
- tag. \n\
-\n\
-OPTIONS \n\
- --help: display this help \n\
-\n\
- --fd: create idmap for target package 'target' (path to apk) and overlay package 'overlay' \n\
- (path to apk); write results to file descriptor 'fd' (integer). This invocation \n\
- version is intended to be used by a parent process with higher privileges to call \n\
- idmap in a controlled way: the parent will open a suitable file descriptor, fork, \n\
- drop its privileges and exec. This tool will continue execution without the extra \n\
- privileges, but still have write access to a file it could not have opened on its \n\
- own. \n\
-\n\
- --path: create idmap for target package 'target' (path to apk) and overlay package \n\
- 'overlay' (path to apk); write results to 'idmap' (path). \n\
-\n\
- --scan: non-recursively search directory 'dir-to-scan' (path) for static overlay packages \n\
- with target package 'target-package-name-to-look-for' (package name) present at\n\
- 'path-to-target-apk' (path to apk). For each overlay package found, create an\n\
- idmap file in 'dir-to-hold-idmaps' (path). \n\
-\n\
- --inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\
- debug-friendly format. \n\
-\n\
- --verify: verify if idmap corresponding to file descriptor 'fd' (integer) is made from \n\
- target package 'target' (path to apk) and overlay package 'overlay'. \n\
-\n\
-EXAMPLES \n\
- Create an idmap file: \n\
-\n\
- $ adb shell idmap --path /system/app/target.apk \\ \n\
- /vendor/overlay/overlay.apk \\ \n\
- /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\
-\n\
- Display an idmap file: \n\
-\n\
- $ adb shell idmap --inspect /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\
- SECTION ENTRY VALUE COMMENT \n\
- IDMAP HEADER magic 0x706d6469 \n\
- base crc 0xb65a383f \n\
- overlay crc 0x7b9675e8 \n\
- base path .......... /path/to/target.apk \n\
- overlay path .......... /path/to/overlay.apk \n\
- DATA HEADER target pkg 0x0000007f \n\
- types count 0x00000003 \n\
- DATA BLOCK target type 0x00000002 \n\
- overlay type 0x00000002 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 drawable/drawable \n\
- DATA BLOCK target type 0x00000003 \n\
- overlay type 0x00000003 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 xml/integer \n\
- DATA BLOCK target type 0x00000004 \n\
- overlay type 0x00000004 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 raw/lorem_ipsum \n\
-\n\
- In this example, the overlay package provides three alternative resource values:\n\
- drawable/drawable, xml/integer, and raw/lorem_ipsum \n\
-\n\
-NOTES \n\
- This tool and its expected invocation from installd is modelled on dexopt.";
-
- bool verify_directory_readable(const char *path)
- {
- return access(path, R_OK | X_OK) == 0;
- }
-
- bool verify_directory_writable(const char *path)
- {
- return access(path, W_OK) == 0;
- }
-
- bool verify_file_readable(const char *path)
- {
- return access(path, R_OK) == 0;
- }
-
- bool verify_root_or_system()
- {
- uid_t uid = getuid();
- gid_t gid = getgid();
-
- return (uid == 0 && gid == 0) || (uid == AID_SYSTEM && gid == AID_SYSTEM);
- }
-
- int maybe_create_fd(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_str)
- {
- // anyone (not just root or system) may do --fd -- the file has
- // already been opened by someone else on our behalf
-
- char *endptr;
- int idmap_fd = strtol(idmap_str, &endptr, 10);
- if (*endptr != '\0') {
- fprintf(stderr, "error: failed to parse file descriptor argument %s\n", idmap_str);
- return -1;
- }
-
- if (!verify_file_readable(target_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
- return -1;
- }
-
- if (!verify_file_readable(overlay_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
- return -1;
- }
-
- return idmap_create_fd(target_apk_path, overlay_apk_path, idmap_fd);
- }
-
- int maybe_create_path(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_path)
- {
- if (!verify_root_or_system()) {
- fprintf(stderr, "error: permission denied: not user root or user system\n");
- return -1;
- }
-
- if (!verify_file_readable(target_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
- return -1;
- }
-
- if (!verify_file_readable(overlay_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
- return -1;
- }
-
- return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
- }
-
- int maybe_verify_fd(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_str)
- {
- char *endptr;
- int idmap_fd = strtol(idmap_str, &endptr, 10);
- if (*endptr != '\0') {
- fprintf(stderr, "error: failed to parse file descriptor argument %s\n", idmap_str);
- return -1;
- }
-
- if (!verify_file_readable(target_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
- return -1;
- }
-
- if (!verify_file_readable(overlay_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
- return -1;
- }
-
- return idmap_verify_fd(target_apk_path, overlay_apk_path, idmap_fd);
- }
-
- int maybe_scan(const char *target_package_name, const char *target_apk_path,
- const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
- {
- if (!verify_root_or_system()) {
- fprintf(stderr, "error: permission denied: not user root or user system\n");
- return -1;
- }
-
- if (!verify_file_readable(target_apk_path)) {
- ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
- return -1;
- }
-
- if (!verify_directory_writable(idmap_dir)) {
- ALOGD("error: no write access to %s: %s\n", idmap_dir, strerror(errno));
- return -1;
- }
-
- const size_t N = overlay_dirs->size();
- for (size_t i = 0; i < N; i++) {
- const char *dir = overlay_dirs->itemAt(i);
- if (!verify_directory_readable(dir)) {
- ALOGD("error: no read access to %s: %s\n", dir, strerror(errno));
- return -1;
- }
- }
-
- return idmap_scan(target_package_name, target_apk_path, idmap_dir, overlay_dirs);
- }
-
- int maybe_inspect(const char *idmap_path)
- {
- // anyone (not just root or system) may do --inspect
- if (!verify_file_readable(idmap_path)) {
- ALOGD("error: failed to read idmap %s: %s\n", idmap_path, strerror(errno));
- return -1;
- }
- return idmap_inspect(idmap_path);
- }
-}
-
-int main(int argc, char **argv)
-{
-#if 0
- {
- char buf[1024];
- buf[0] = '\0';
- for (int i = 0; i < argc; ++i) {
- strncat(buf, argv[i], sizeof(buf) - 1);
- strncat(buf, " ", sizeof(buf) - 1);
- }
- ALOGD("%s:%d: uid=%d gid=%d argv=%s\n", __FILE__, __LINE__, getuid(), getgid(), buf);
- }
-#endif
-
- if (argc == 2 && !strcmp(argv[1], "--help")) {
- printf("%s\n", usage);
- return 0;
- }
-
- if (argc == 5 && !strcmp(argv[1], "--fd")) {
- return maybe_create_fd(argv[2], argv[3], argv[4]);
- }
-
- if (argc == 5 && !strcmp(argv[1], "--path")) {
- return maybe_create_path(argv[2], argv[3], argv[4]);
- }
-
- if (argc == 5 && !strcmp(argv[1], "--verify")) {
- return maybe_verify_fd(argv[2], argv[3], argv[4]);
- }
-
- if (argc >= 6 && !strcmp(argv[1], "--scan")) {
- android::Vector<const char *> v;
- for (int i = 5; i < argc; i++) {
- v.push(argv[i]);
- }
- return maybe_scan(argv[2], argv[3], argv[4], &v);
- }
-
- if (argc == 3 && !strcmp(argv[1], "--inspect")) {
- return maybe_inspect(argv[2]);
- }
-
- fprintf(stderr, "Usage: don't use this (cf dexopt usage).\n");
- return EXIT_FAILURE;
-}
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
deleted file mode 100644
index 5962108c9f7e..000000000000
--- a/cmds/idmap/idmap.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-#ifndef _IDMAP_H_
-#define _IDMAP_H_
-
-#define LOG_TAG "idmap"
-
-#include <utils/Log.h>
-#include <utils/Vector.h>
-
-#include <errno.h>
-#include <stdio.h>
-
-#ifndef TEMP_FAILURE_RETRY
-// Used to retry syscalls that can return EINTR.
-#define TEMP_FAILURE_RETRY(exp) ({ \
- typeof (exp) _rc; \
- do { \
- _rc = (exp); \
- } while (_rc == -1 && errno == EINTR); \
- _rc; })
-#endif
-
-int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_path);
-
-int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
-
-int idmap_verify_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
-
-// Regarding target_package_name: the idmap_scan implementation should
-// be able to extract this from the manifest in target_apk_path,
-// simplifying the external API.
-int idmap_scan(const char *target_package_name, const char *target_apk_path,
- const char *idmap_dir, const android::Vector<const char *> *overlay_dirs);
-
-int idmap_inspect(const char *idmap_path);
-
-#endif // _IDMAP_H_
diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
deleted file mode 100644
index 20005e2766d8..000000000000
--- a/cmds/idmap/inspect.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-#include "idmap.h"
-
-#include <androidfw/AssetManager.h>
-#include <androidfw/ResourceTypes.h>
-#include <utils/ByteOrder.h>
-#include <utils/String8.h>
-
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-using namespace android;
-
-namespace {
- static const uint32_t IDMAP_MAGIC = 0x504D4449;
- static const size_t PATH_LENGTH = 256;
-
- void printe(const char *fmt, ...);
-
- class IdmapBuffer {
- private:
- const char* buf_;
- size_t len_;
- size_t pos_;
- public:
- IdmapBuffer() : buf_((const char *)MAP_FAILED), len_(0), pos_(0) {}
-
- ~IdmapBuffer() {
- if (buf_ != MAP_FAILED) {
- munmap(const_cast<char*>(buf_), len_);
- }
- }
-
- status_t init(const char *idmap_path) {
- struct stat st;
- int fd;
-
- if (stat(idmap_path, &st) < 0) {
- printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno));
- return UNKNOWN_ERROR;
- }
- len_ = st.st_size;
- if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) {
- printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno));
- return UNKNOWN_ERROR;
- }
- if ((buf_ = (const char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
- close(fd);
- printe("failed to mmap idmap: %s\n", strerror(errno));
- return UNKNOWN_ERROR;
- }
- close(fd);
- return NO_ERROR;
- }
-
- status_t nextUint32(uint32_t* i) {
- if (!buf_) {
- printe("failed to read next uint32_t: buffer not initialized\n");
- return UNKNOWN_ERROR;
- }
-
- if (pos_ + sizeof(uint32_t) > len_) {
- printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n",
- pos_);
- return UNKNOWN_ERROR;
- }
-
- if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x3) != 0) {
- printe("failed to read next uint32_t: not aligned on 4-byte boundary\n");
- return UNKNOWN_ERROR;
- }
-
- *i = dtohl(*reinterpret_cast<const uint32_t*>(buf_ + pos_));
- pos_ += sizeof(uint32_t);
- return NO_ERROR;
- }
-
- status_t nextUint16(uint16_t* i) {
- if (!buf_) {
- printe("failed to read next uint16_t: buffer not initialized\n");
- return UNKNOWN_ERROR;
- }
-
- if (pos_ + sizeof(uint16_t) > len_) {
- printe("failed to read next uint16_t: end of buffer reached at pos=0x%08x\n",
- pos_);
- return UNKNOWN_ERROR;
- }
-
- if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x1) != 0) {
- printe("failed to read next uint32_t: not aligned on 2-byte boundary\n");
- return UNKNOWN_ERROR;
- }
-
- *i = dtohs(*reinterpret_cast<const uint16_t*>(buf_ + pos_));
- pos_ += sizeof(uint16_t);
- return NO_ERROR;
- }
-
- status_t nextPath(char *b) {
- if (!buf_) {
- printe("failed to read next path: buffer not initialized\n");
- return UNKNOWN_ERROR;
- }
- if (pos_ + PATH_LENGTH > len_) {
- printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_);
- return UNKNOWN_ERROR;
- }
- memcpy(b, buf_ + pos_, PATH_LENGTH);
- pos_ += PATH_LENGTH;
- return NO_ERROR;
- }
- };
-
- void printe(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- }
-
- void print_header() {
- printf("SECTION ENTRY VALUE COMMENT\n");
- }
-
- void print(const char *section, const char *subsection, uint32_t value, const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- printf("%-12s %-12s 0x%08x ", section, subsection, value);
- vprintf(fmt, ap);
- printf("\n");
- va_end(ap);
- }
-
- void print_path(const char *section, const char *subsection, const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- printf("%-12s %-12s .......... ", section, subsection);
- vprintf(fmt, ap);
- printf("\n");
- va_end(ap);
- }
-
- status_t resource_metadata(const AssetManager& am, uint32_t res_id,
- String8 *package, String8 *type, String8 *name) {
- const ResTable& rt = am.getResources();
- struct ResTable::resource_name data;
- if (!rt.getResourceName(res_id, false, &data)) {
- printe("failed to get resource name id=0x%08x\n", res_id);
- return UNKNOWN_ERROR;
- }
- if (package != NULL) {
- *package = String8(String16(data.package, data.packageLen));
- }
- if (type != NULL) {
- *type = String8(String16(data.type, data.typeLen));
- }
- if (name != NULL) {
- *name = String8(String16(data.name, data.nameLen));
- }
- return NO_ERROR;
- }
-
- status_t parse_idmap_header(IdmapBuffer& buf, AssetManager& am) {
- uint32_t i;
- char path[PATH_LENGTH];
-
- status_t err = buf.nextUint32(&i);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (i != IDMAP_MAGIC) {
- printe("not an idmap file: actual magic constant 0x%08x does not match expected magic "
- "constant 0x%08x\n", i, IDMAP_MAGIC);
- return UNKNOWN_ERROR;
- }
-
- print_header();
- print("IDMAP HEADER", "magic", i, "");
-
- err = buf.nextUint32(&i);
- if (err != NO_ERROR) {
- return err;
- }
- print("", "version", i, "");
-
- err = buf.nextUint32(&i);
- if (err != NO_ERROR) {
- return err;
- }
- print("", "base crc", i, "");
-
- err = buf.nextUint32(&i);
- if (err != NO_ERROR) {
- return err;
- }
- print("", "overlay crc", i, "");
-
- err = buf.nextPath(path);
- if (err != NO_ERROR) {
- // printe done from IdmapBuffer::nextPath
- return err;
- }
- print_path("", "base path", "%s", path);
-
- if (!am.addAssetPath(String8(path), NULL)) {
- printe("failed to add '%s' as asset path\n", path);
- return UNKNOWN_ERROR;
- }
-
- err = buf.nextPath(path);
- if (err != NO_ERROR) {
- // printe done from IdmapBuffer::nextPath
- return err;
- }
- print_path("", "overlay path", "%s", path);
-
- return NO_ERROR;
- }
-
- status_t parse_data(IdmapBuffer& buf, const AssetManager& am) {
- const uint32_t packageId = am.getResources().getBasePackageId(0);
-
- uint16_t data16;
- status_t err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- print("DATA HEADER", "target pkg", static_cast<uint32_t>(data16), "");
-
- err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- print("", "types count", static_cast<uint32_t>(data16), "");
-
- uint32_t typeCount = static_cast<uint32_t>(data16);
- while (typeCount > 0) {
- typeCount--;
-
- err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- const uint32_t targetTypeId = static_cast<uint32_t>(data16);
- print("DATA BLOCK", "target type", targetTypeId, "");
-
- err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- print("", "overlay type", static_cast<uint32_t>(data16), "");
-
- err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- const uint32_t entryCount = static_cast<uint32_t>(data16);
- print("", "entry count", entryCount, "");
-
- err = buf.nextUint16(&data16);
- if (err != NO_ERROR) {
- return err;
- }
- const uint32_t entryOffset = static_cast<uint32_t>(data16);
- print("", "entry offset", entryOffset, "");
-
- for (uint32_t i = 0; i < entryCount; i++) {
- uint32_t data32;
- err = buf.nextUint32(&data32);
- if (err != NO_ERROR) {
- return err;
- }
-
- uint32_t resID = (packageId << 24) | (targetTypeId << 16) | (entryOffset + i);
- String8 type;
- String8 name;
- err = resource_metadata(am, resID, NULL, &type, &name);
- if (err != NO_ERROR) {
- return err;
- }
- if (data32 != ResTable_type::NO_ENTRY) {
- print("", "entry", data32, "%s/%s", type.string(), name.string());
- }
- }
- }
-
- return NO_ERROR;
- }
-}
-
-int idmap_inspect(const char *idmap_path) {
- IdmapBuffer buf;
- if (buf.init(idmap_path) < 0) {
- // printe done from IdmapBuffer::init
- return EXIT_FAILURE;
- }
- AssetManager am;
- if (parse_idmap_header(buf, am) != NO_ERROR) {
- // printe done from parse_idmap_header
- return EXIT_FAILURE;
- }
- if (parse_data(buf, am) != NO_ERROR) {
- // printe done from parse_data_header
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
-}
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
deleted file mode 100644
index 847dda3df91f..000000000000
--- a/cmds/idmap/scan.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-#include <dirent.h>
-#include <inttypes.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include "idmap.h"
-
-#include <memory>
-#include <androidfw/ResourceTypes.h>
-#include <androidfw/StreamingZipInflater.h>
-#include <androidfw/ZipFileRO.h>
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h> // for AID_SYSTEM
-#include <utils/SortedVector.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-#define NO_OVERLAY_TAG (-1000)
-
-using namespace android;
-
-namespace {
- struct Overlay {
- Overlay() {}
- Overlay(const String8& a, const String8& i, int p) :
- apk_path(a), idmap_path(i), priority(p) {}
-
- bool operator<(Overlay const& rhs) const
- {
- return rhs.priority > priority;
- }
-
- String8 apk_path;
- String8 idmap_path;
- int priority;
- };
-
- bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
- {
- // the file is opened for appending so that it doesn't get truncated
- // before we can guarantee mutual exclusion via the flock
- FILE* fout = fopen(filename, "a");
- if (fout == NULL) {
- return false;
- }
-
- if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) {
- fclose(fout);
- return false;
- }
-
- if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) {
- TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
- fclose(fout);
- return false;
- }
-
- for (size_t i = 0; i < overlayVector.size(); ++i) {
- const Overlay& overlay = overlayVector[i];
- fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
- }
-
- TEMP_FAILURE_RETRY(fflush(fout));
- TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
- fclose(fout);
-
- // Make file world readable since Zygote (running as root) will read
- // it when creating the initial AssetManger object
- const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
- if (chmod(filename, mode) == -1) {
- unlink(filename);
- return false;
- }
-
- return true;
- }
-
- String8 flatten_path(const char *path)
- {
- String16 tmp(path);
- tmp.replaceAll('/', '@');
- return String8(tmp);
- }
-
- bool check_property(String16 property, String16 value) {
- char propBuf[PROPERTY_VALUE_MAX];
- property_get(String8(property).c_str(), propBuf, NULL);
- return String8(value) == propBuf;
- }
-
- int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name,
- bool* is_static_overlay)
- {
- const size_t N = parser.getAttributeCount();
- String16 target;
- int priority = -1;
- String16 propName = String16();
- String16 propValue = String16();
- for (size_t i = 0; i < N; ++i) {
- size_t len;
- String16 key(parser.getAttributeName(i, &len));
- if (key == String16("targetPackage")) {
- const char16_t *p = parser.getAttributeStringValue(i, &len);
- if (p != NULL) {
- target = String16(p, len);
- }
- } else if (key == String16("priority")) {
- Res_value v;
- if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
- priority = v.data;
- if (priority < 0 || priority > 9999) {
- return -1;
- }
- }
- } else if (key == String16("isStatic")) {
- Res_value v;
- if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
- *is_static_overlay = (v.data != 0);
- }
- } else if (key == String16("requiredSystemPropertyName")) {
- const char16_t *p = parser.getAttributeStringValue(i, &len);
- if (p != NULL) {
- propName = String16(p, len);
- }
- } else if (key == String16("requiredSystemPropertyValue")) {
- const char16_t *p = parser.getAttributeStringValue(i, &len);
- if (p != NULL) {
- propValue = String16(p, len);
- }
- }
- }
-
- // Note that conditional property enablement/exclusion only applies if
- // the attribute is present. In its absence, all overlays are presumed enabled.
- if (propName.size() > 0 && propValue.size() > 0) {
- // if property set & equal to value, then include overlay - otherwise skip
- if (!check_property(propName, propValue)) {
- return NO_OVERLAY_TAG;
- }
- }
-
- if (target == String16(target_package_name)) {
- return priority;
- }
- return NO_OVERLAY_TAG;
- }
-
- int parse_manifest(const void *data, size_t size, const char *target_package_name)
- {
- ResXMLTree parser;
- parser.setTo(data, size);
- if (parser.getError() != NO_ERROR) {
- ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
- return -1;
- }
-
- ResXMLParser::event_code_t type;
- bool is_static_overlay = false;
- int priority = NO_OVERLAY_TAG;
- do {
- type = parser.next();
- if (type == ResXMLParser::START_TAG) {
- size_t len;
- String16 tag(parser.getElementName(&len));
- if (tag == String16("overlay")) {
- priority = parse_overlay_tag(parser, target_package_name, &is_static_overlay);
- break;
- }
- }
- } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
-
- if (is_static_overlay) {
- return priority;
- }
- return NO_OVERLAY_TAG;
- }
-
- int parse_apk(const char *path, const char *target_package_name)
- {
- std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(path));
- if (zip.get() == NULL) {
- ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path);
- return -1;
- }
- ZipEntryRO entry;
- if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) {
- ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__);
- return -1;
- }
- uint32_t uncompLen = 0;
- uint16_t method;
- if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) {
- ALOGW("%s: failed to read entry info\n", __FUNCTION__);
- return -1;
- }
- if (method != ZipFileRO::kCompressDeflated) {
- ALOGW("%s: cannot handle zip compression method %" PRIu16 "\n", __FUNCTION__, method);
- return -1;
- }
- FileMap *dataMap = zip->createEntryFileMap(entry);
- if (dataMap == NULL) {
- ALOGW("%s: failed to create FileMap\n", __FUNCTION__);
- return -1;
- }
- char *buf = new char[uncompLen];
- if (NULL == buf) {
- ALOGW("%s: failed to allocate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
- delete dataMap;
- return -1;
- }
- StreamingZipInflater inflater(dataMap, uncompLen);
- if (inflater.read(buf, uncompLen) < 0) {
- ALOGW("%s: failed to inflate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
- delete[] buf;
- delete dataMap;
- return -1;
- }
-
- int priority = parse_manifest(buf, static_cast<size_t>(uncompLen), target_package_name);
- delete[] buf;
- delete dataMap;
- return priority;
- }
-}
-
-int idmap_scan(const char *target_package_name, const char *target_apk_path,
- const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
-{
- String8 filename = String8(idmap_dir);
- filename.appendPath("overlays.list");
-
- SortedVector<Overlay> overlayVector;
- const size_t N = overlay_dirs->size();
- for (size_t i = 0; i < N; ++i) {
- const char *overlay_dir = overlay_dirs->itemAt(i);
- DIR *dir = opendir(overlay_dir);
- if (dir == NULL) {
- return EXIT_FAILURE;
- }
-
- struct dirent *dirent;
- while ((dirent = readdir(dir)) != NULL) {
- struct stat st;
- char overlay_apk_path[PATH_MAX + 1];
- snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
- if (stat(overlay_apk_path, &st) < 0) {
- continue;
- }
- if (!S_ISREG(st.st_mode)) {
- continue;
- }
-
- int priority = parse_apk(overlay_apk_path, target_package_name);
- if (priority < 0) {
- continue;
- }
-
- String8 idmap_path(idmap_dir);
- idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
- idmap_path.append("@idmap");
-
- if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
- ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
- target_apk_path, overlay_apk_path, idmap_path.string());
- continue;
- }
-
- Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
- overlayVector.add(overlay);
- }
-
- closedir(dir);
- }
-
- if (!writePackagesList(filename.string(), overlayVector)) {
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index cf286e662630..360ddd44955a 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -69,9 +69,11 @@ cc_defaults {
"src/external/GpuStatsPuller.cpp",
"src/external/Perfetto.cpp",
"src/external/PowerStatsPuller.cpp",
+ "src/external/PullResultReceiver.cpp",
"src/external/puller_util.cpp",
"src/external/ResourceHealthManagerPuller.cpp",
"src/external/StatsCallbackPuller.cpp",
+ "src/external/StatsCallbackPullerDeprecated.cpp",
"src/external/StatsCompanionServicePuller.cpp",
"src/external/StatsPuller.cpp",
"src/external/StatsPullerManager.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 2c325ba6ac0a..1fd3abfc5adc 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1293,7 +1293,11 @@ Status StatsService::registerPullerCallback(int32_t atomTag,
Status StatsService::registerPullAtomCallback(int32_t uid, int32_t atomTag, int64_t coolDownNs,
int64_t timeoutNs, const std::vector<int32_t>& additiveFields,
const sp<android::os::IPullAtomCallback>& pullerCallback) {
+ ENFORCE_UID(AID_SYSTEM);
+
VLOG("StatsService::registerPuller called.");
+ mPullerManager->RegisterPullAtomCallback(uid, atomTag, coolDownNs, timeoutNs, additiveFields,
+ pullerCallback);
return Status::ok();
}
diff --git a/cmds/statsd/src/external/PullResultReceiver.cpp b/cmds/statsd/src/external/PullResultReceiver.cpp
new file mode 100644
index 000000000000..6bd05452f3b0
--- /dev/null
+++ b/cmds/statsd/src/external/PullResultReceiver.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include "PullResultReceiver.h"
+
+using namespace android::binder;
+using namespace android::util;
+using namespace std;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+PullResultReceiver::PullResultReceiver(
+ std::function<void(int32_t, bool, const vector<android::util::StatsEvent>&)> pullFinishCb)
+ : pullFinishCallback(std::move(pullFinishCb)) {
+}
+
+Status PullResultReceiver::pullFinished(int32_t atomTag, bool success,
+ const vector<StatsEvent>& output) {
+ pullFinishCallback(atomTag, success, output);
+ return Status::ok();
+}
+
+PullResultReceiver::~PullResultReceiver() {
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android \ No newline at end of file
diff --git a/cmds/statsd/src/external/PullResultReceiver.h b/cmds/statsd/src/external/PullResultReceiver.h
new file mode 100644
index 000000000000..f731f778a337
--- /dev/null
+++ b/cmds/statsd/src/external/PullResultReceiver.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <android/os/BnPullAtomResultReceiver.h>
+
+using namespace std;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class PullResultReceiver : public BnPullAtomResultReceiver {
+public:
+ PullResultReceiver(function<void(int32_t, bool, const vector<android::util::StatsEvent>&)>
+ pullFinishCallback);
+ ~PullResultReceiver();
+
+ /**
+ * Binder call for finishing a pull.
+ */
+ binder::Status pullFinished(int32_t atomTag, bool success,
+ const vector<android::util::StatsEvent>& output) override;
+
+private:
+ function<void(int32_t, bool, const vector<android::util::StatsEvent>&)> pullFinishCallback;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index d718273e9b85..92db68477dbd 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -17,21 +17,27 @@
#define DEBUG false // STOPSHIP if true
#include "Log.h"
-#include <android/os/IStatsPullerCallback.h>
-
#include "StatsCallbackPuller.h"
+
+#include <android/os/IPullAtomCallback.h>
+#include <android/util/StatsEvent.h>
+
+#include "PullResultReceiver.h"
+#include "StatsPullerManager.h"
#include "logd/LogEvent.h"
#include "stats_log_util.h"
using namespace android::binder;
+using namespace android::util;
+using namespace std;
namespace android {
namespace os {
namespace statsd {
-StatsCallbackPuller::StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback) :
- StatsPuller(tagId), mCallback(callback) {
- VLOG("StatsCallbackPuller created for tag %d", tagId);
+StatsCallbackPuller::StatsCallbackPuller(int tagId, const sp<IPullAtomCallback>& callback)
+ : StatsPuller(tagId), mCallback(callback) {
+ VLOG("StatsCallbackPuller created for tag %d", tagId);
}
bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
@@ -40,20 +46,57 @@ bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
ALOGW("No callback registered");
return false;
}
- int64_t wallClockTimeNs = getWallClockNs();
- int64_t elapsedTimeNs = getElapsedRealtimeNs();
- vector<StatsLogEventWrapper> returned_value;
- Status status = mCallback->pullData(mTagId, elapsedTimeNs, wallClockTimeNs, &returned_value);
+
+ // Shared variables needed in the result receiver.
+ shared_ptr<mutex> cv_mutex = make_shared<mutex>();
+ shared_ptr<condition_variable> cv = make_shared<condition_variable>();
+ shared_ptr<bool> pullFinish = make_shared<bool>(false);
+ shared_ptr<bool> pullSuccess = make_shared<bool>(false);
+ shared_ptr<vector<shared_ptr<LogEvent>>> sharedData =
+ make_shared<vector<shared_ptr<LogEvent>>>();
+
+ sp<PullResultReceiver> resultReceiver = new PullResultReceiver(
+ [cv_mutex, cv, pullFinish, pullSuccess, sharedData](
+ int32_t atomTag, bool success, const vector<StatsEvent>& output) {
+ // This is the result of the pull, executing in a statsd binder thread.
+ // The pull could have taken a long time, and we should only modify
+ // data (the output param) if the pointer is in scope and the pull did not time out.
+ {
+ lock_guard<mutex> lk(*cv_mutex);
+ // TODO: fill the shared vector of LogEvents once StatsEvent is complete.
+ *pullSuccess = success;
+ *pullFinish = true;
+ }
+ cv->notify_one();
+ });
+
+ // Initiate the pull.
+ Status status = mCallback->onPullAtom(mTagId, resultReceiver);
if (!status.isOk()) {
- ALOGW("StatsCallbackPuller::pull failed for %d", mTagId);
return false;
}
- data->clear();
- for (const StatsLogEventWrapper& it: returned_value) {
- LogEvent::createLogEvents(it, *data);
+
+ {
+ unique_lock<mutex> unique_lk(*cv_mutex);
+ int64_t pullTimeoutNs =
+ StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).pullTimeoutNs;
+ // Wait until the pull finishes, or until the pull timeout.
+ cv->wait_for(unique_lk, chrono::nanoseconds(pullTimeoutNs),
+ [pullFinish] { return *pullFinish; });
+ if (!*pullFinish) {
+ // Note: The parent stats puller will also note that there was a timeout and that the
+ // cache should be cleared. Once we migrate all pullers to this callback, we could
+ // consolidate the logic.
+ return true;
+ } else {
+ // Only copy the data if we did not timeout and the pull was successful.
+ if (pullSuccess) {
+ *data = std::move(*sharedData);
+ }
+ VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId);
+ return *pullSuccess;
+ }
}
- VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId);
- return true;
}
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.h b/cmds/statsd/src/external/StatsCallbackPuller.h
index c4bfa89ba9a7..ce506c7f9785 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.h
+++ b/cmds/statsd/src/external/StatsCallbackPuller.h
@@ -16,8 +16,9 @@
#pragma once
-#include <android/os/IStatsPullerCallback.h>
+#include <android/os/IPullAtomCallback.h>
#include <utils/String16.h>
+
#include "StatsPuller.h"
namespace android {
@@ -26,11 +27,11 @@ namespace statsd {
class StatsCallbackPuller : public StatsPuller {
public:
- explicit StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback);
+ explicit StatsCallbackPuller(int tagId, const sp<IPullAtomCallback>& callback);
private:
bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
- const sp<IStatsPullerCallback> mCallback;
+ const sp<IPullAtomCallback> mCallback;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp
new file mode 100644
index 000000000000..4f88a91f9ec6
--- /dev/null
+++ b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include "StatsCallbackPullerDeprecated.h"
+
+#include <android/os/IStatsPullerCallback.h>
+
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+
+using namespace android::binder;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+StatsCallbackPullerDeprecated::StatsCallbackPullerDeprecated(
+ int tagId, const sp<IStatsPullerCallback>& callback)
+ : StatsPuller(tagId), mCallback(callback) {
+ VLOG("StatsCallbackPuller created for tag %d", tagId);
+}
+
+bool StatsCallbackPullerDeprecated::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ VLOG("StatsCallbackPuller called for tag %d", mTagId)
+ if (mCallback == nullptr) {
+ ALOGW("No callback registered");
+ return false;
+ }
+ int64_t wallClockTimeNs = getWallClockNs();
+ int64_t elapsedTimeNs = getElapsedRealtimeNs();
+ vector<StatsLogEventWrapper> returned_value;
+ Status status = mCallback->pullData(mTagId, elapsedTimeNs, wallClockTimeNs, &returned_value);
+ if (!status.isOk()) {
+ ALOGW("StatsCallbackPuller::pull failed for %d", mTagId);
+ return false;
+ }
+ data->clear();
+ for (const StatsLogEventWrapper& it : returned_value) {
+ LogEvent::createLogEvents(it, *data);
+ }
+ VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId);
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserTests.java b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.h
index 525382d50d72..028902975923 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserTests.java
+++ b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.h
@@ -14,24 +14,26 @@
* limitations under the License.
*/
-package com.android.server.pm;
+#pragma once
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
+#include <android/os/IStatsPullerCallback.h>
+#include <utils/String16.h>
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
- UserDataPreparerTest.class,
- UserLifecycleStressTest.class,
- UserManagerServiceCreateProfileTest.class,
- UserManagerServiceIdRecyclingTest.class,
- UserManagerServiceTest.class,
- UserManagerServiceUserInfoTest.class,
- UserManagerServiceUserTypeTest.class,
- UserManagerTest.class,
- UserRestrictionsUtilsTest.class,
- UserSystemPackageInstallerTest.class,
-})
-public class UserTests {
-}
+#include "StatsPuller.h"
+namespace android {
+namespace os {
+namespace statsd {
+
+class StatsCallbackPullerDeprecated : public StatsPuller {
+public:
+ explicit StatsCallbackPullerDeprecated(int tagId, const sp<IStatsPullerCallback>& callback);
+
+private:
+ bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
+ const sp<IStatsPullerCallback> mCallback;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 9552c0a5e35e..3c6bc2db1d62 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -40,8 +40,9 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
lock_guard<std::mutex> lock(mLock);
int64_t elapsedTimeNs = getElapsedRealtimeNs();
StatsdStats::getInstance().notePull(mTagId);
- const bool shouldUseCache = elapsedTimeNs - mLastPullTimeNs <
- StatsPullerManager::kAllPullAtomInfo.at(mTagId).coolDownNs;
+ const bool shouldUseCache =
+ elapsedTimeNs - mLastPullTimeNs <
+ StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).coolDownNs;
if (shouldUseCache) {
if (mHasGoodData) {
(*data) = mCachedData;
@@ -63,7 +64,8 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
const int64_t pullDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
StatsdStats::getInstance().notePullTime(mTagId, pullDurationNs);
const bool pullTimeOut =
- pullDurationNs > StatsPullerManager::kAllPullAtomInfo.at(mTagId).pullTimeoutNs;
+ pullDurationNs >
+ StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).pullTimeoutNs;
if (pullTimeOut) {
// Something went wrong. Discard the data.
clearCacheLocked();
@@ -100,7 +102,7 @@ int StatsPuller::clearCacheLocked() {
int StatsPuller::ClearCacheIfNecessary(int64_t timestampNs) {
if (timestampNs - mLastPullTimeNs >
- StatsPullerManager::kAllPullAtomInfo.at(mTagId).coolDownNs) {
+ StatsPullerManager::kAllPullAtomInfo.at({.atomTag = mTagId}).coolDownNs) {
return clearCache();
} else {
return 0;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 535fcfbfc454..ce27ce6853e8 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -19,6 +19,7 @@
#include "StatsPullerManager.h"
+#include <android/os/IPullAtomCallback.h>
#include <android/os/IStatsCompanionService.h>
#include <android/os/IStatsPullerCallback.h>
#include <cutils/log.h>
@@ -37,6 +38,7 @@
#include "PowerStatsPuller.h"
#include "ResourceHealthManagerPuller.h"
#include "StatsCallbackPuller.h"
+#include "StatsCallbackPullerDeprecated.h"
#include "StatsCompanionServicePuller.h"
#include "SubsystemSleepStatePuller.h"
#include "SurfaceflingerStatsPuller.h"
@@ -57,224 +59,226 @@ namespace statsd {
// Values smaller than this may require to update the alarm.
const int64_t NO_ALARM_UPDATE = INT64_MAX;
-std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
+std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
// wifi_bytes_transfer
- {android::util::WIFI_BYTES_TRANSFER,
+ {{.atomTag = android::util::WIFI_BYTES_TRANSFER},
{.additiveFields = {2, 3, 4, 5},
.puller = new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}},
// wifi_bytes_transfer_by_fg_bg
- {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
+ {{.atomTag = android::util::WIFI_BYTES_TRANSFER_BY_FG_BG},
{.additiveFields = {3, 4, 5, 6},
.puller = new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
// mobile_bytes_transfer
- {android::util::MOBILE_BYTES_TRANSFER,
+ {{.atomTag = android::util::MOBILE_BYTES_TRANSFER},
{.additiveFields = {2, 3, 4, 5},
.puller = new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
// mobile_bytes_transfer_by_fg_bg
- {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
+ {{.atomTag = android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG},
{.additiveFields = {3, 4, 5, 6},
.puller =
new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
// bluetooth_bytes_transfer
- {android::util::BLUETOOTH_BYTES_TRANSFER,
+ {{.atomTag = android::util::BLUETOOTH_BYTES_TRANSFER},
{.additiveFields = {2, 3},
.puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}},
// kernel_wakelock
- {android::util::KERNEL_WAKELOCK,
+ {{.atomTag = android::util::KERNEL_WAKELOCK},
{.puller = new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
// subsystem_sleep_state
- {android::util::SUBSYSTEM_SLEEP_STATE, {.puller = new SubsystemSleepStatePuller()}},
+ {{.atomTag = android::util::SUBSYSTEM_SLEEP_STATE},
+ {.puller = new SubsystemSleepStatePuller()}},
// on_device_power_measurement
- {android::util::ON_DEVICE_POWER_MEASUREMENT, {.puller = new PowerStatsPuller()}},
+ {{.atomTag = android::util::ON_DEVICE_POWER_MEASUREMENT},
+ {.puller = new PowerStatsPuller()}},
// cpu_time_per_freq
- {android::util::CPU_TIME_PER_FREQ,
+ {{.atomTag = android::util::CPU_TIME_PER_FREQ},
{.additiveFields = {3},
.puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
// cpu_time_per_uid
- {android::util::CPU_TIME_PER_UID,
+ {{.atomTag = android::util::CPU_TIME_PER_UID},
{.additiveFields = {2, 3},
.puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}},
// cpu_time_per_uid_freq
// the throttling is 3sec, handled in
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
- {android::util::CPU_TIME_PER_UID_FREQ,
+ {{.atomTag = android::util::CPU_TIME_PER_UID_FREQ},
{.additiveFields = {4},
.puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}},
// cpu_active_time
// the throttling is 3sec, handled in
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
- {android::util::CPU_ACTIVE_TIME,
+ {{.atomTag = android::util::CPU_ACTIVE_TIME},
{.additiveFields = {2},
.puller = new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
// cpu_cluster_time
// the throttling is 3sec, handled in
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
- {android::util::CPU_CLUSTER_TIME,
+ {{.atomTag = android::util::CPU_CLUSTER_TIME},
{.additiveFields = {3},
.puller = new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
// wifi_activity_energy_info
- {android::util::WIFI_ACTIVITY_INFO,
+ {{.atomTag = android::util::WIFI_ACTIVITY_INFO},
{.puller = new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}},
// modem_activity_info
- {android::util::MODEM_ACTIVITY_INFO,
+ {{.atomTag = android::util::MODEM_ACTIVITY_INFO},
{.puller = new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
// bluetooth_activity_info
- {android::util::BLUETOOTH_ACTIVITY_INFO,
+ {{.atomTag = android::util::BLUETOOTH_ACTIVITY_INFO},
{.puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
// system_elapsed_realtime
- {android::util::SYSTEM_ELAPSED_REALTIME,
+ {{.atomTag = android::util::SYSTEM_ELAPSED_REALTIME},
{.coolDownNs = NS_PER_SEC,
.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME),
.pullTimeoutNs = NS_PER_SEC / 2,
}},
// system_uptime
- {android::util::SYSTEM_UPTIME,
+ {{.atomTag = android::util::SYSTEM_UPTIME},
{.puller = new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
// remaining_battery_capacity
- {android::util::REMAINING_BATTERY_CAPACITY,
+ {{.atomTag = android::util::REMAINING_BATTERY_CAPACITY},
{.puller = new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}},
// full_battery_capacity
- {android::util::FULL_BATTERY_CAPACITY,
+ {{.atomTag = android::util::FULL_BATTERY_CAPACITY},
{.puller = new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
// battery_voltage
- {android::util::BATTERY_VOLTAGE,
+ {{.atomTag = android::util::BATTERY_VOLTAGE},
{.puller = new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
// battery_level
- {android::util::BATTERY_LEVEL,
+ {{.atomTag = android::util::BATTERY_LEVEL},
{.puller = new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
// battery_cycle_count
- {android::util::BATTERY_CYCLE_COUNT,
+ {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
{.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
// process_memory_state
- {android::util::PROCESS_MEMORY_STATE,
+ {{.atomTag = android::util::PROCESS_MEMORY_STATE},
{.additiveFields = {4, 5, 6, 7, 8},
.puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
// process_memory_high_water_mark
- {android::util::PROCESS_MEMORY_HIGH_WATER_MARK,
+ {{.atomTag = android::util::PROCESS_MEMORY_HIGH_WATER_MARK},
{.puller =
new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
// process_memory_snapshot
- {android::util::PROCESS_MEMORY_SNAPSHOT,
+ {{.atomTag = android::util::PROCESS_MEMORY_SNAPSHOT},
{.puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_SNAPSHOT)}},
// system_ion_heap_size
- {android::util::SYSTEM_ION_HEAP_SIZE,
+ {{.atomTag = android::util::SYSTEM_ION_HEAP_SIZE},
{.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}},
// process_system_ion_heap_size
- {android::util::PROCESS_SYSTEM_ION_HEAP_SIZE,
+ {{.atomTag = android::util::PROCESS_SYSTEM_ION_HEAP_SIZE},
{.puller = new StatsCompanionServicePuller(android::util::PROCESS_SYSTEM_ION_HEAP_SIZE)}},
// temperature
- {android::util::TEMPERATURE,
+ {{.atomTag = android::util::TEMPERATURE},
{.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
// cooling_device
- {android::util::COOLING_DEVICE,
+ {{.atomTag = android::util::COOLING_DEVICE},
{.puller = new StatsCompanionServicePuller(android::util::COOLING_DEVICE)}},
// binder_calls
- {android::util::BINDER_CALLS,
+ {{.atomTag = android::util::BINDER_CALLS},
{.additiveFields = {4, 5, 6, 8, 12},
.puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS)}},
// binder_calls_exceptions
- {android::util::BINDER_CALLS_EXCEPTIONS,
+ {{.atomTag = android::util::BINDER_CALLS_EXCEPTIONS},
{.puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
// looper_stats
- {android::util::LOOPER_STATS,
+ {{.atomTag = android::util::LOOPER_STATS},
{.additiveFields = {5, 6, 7, 8, 9},
.puller = new StatsCompanionServicePuller(android::util::LOOPER_STATS)}},
// Disk Stats
- {android::util::DISK_STATS,
+ {{.atomTag = android::util::DISK_STATS},
{.puller = new StatsCompanionServicePuller(android::util::DISK_STATS)}},
// Directory usage
- {android::util::DIRECTORY_USAGE,
+ {{.atomTag = android::util::DIRECTORY_USAGE},
{.puller = new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
// Size of app's code, data, and cache
- {android::util::APP_SIZE,
+ {{.atomTag = android::util::APP_SIZE},
{.puller = new StatsCompanionServicePuller(android::util::APP_SIZE)}},
// Size of specific categories of files. Eg. Music.
- {android::util::CATEGORY_SIZE,
+ {{.atomTag = android::util::CATEGORY_SIZE},
{.puller = new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
// Number of fingerprints enrolled for each user.
- {android::util::NUM_FINGERPRINTS_ENROLLED,
+ {{.atomTag = android::util::NUM_FINGERPRINTS_ENROLLED},
{.puller = new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS_ENROLLED)}},
// Number of faces enrolled for each user.
- {android::util::NUM_FACES_ENROLLED,
+ {{.atomTag = android::util::NUM_FACES_ENROLLED},
{.puller = new StatsCompanionServicePuller(android::util::NUM_FACES_ENROLLED)}},
// ProcStats.
- {android::util::PROC_STATS,
+ {{.atomTag = android::util::PROC_STATS},
{.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}},
// ProcStatsPkgProc.
- {android::util::PROC_STATS_PKG_PROC,
+ {{.atomTag = android::util::PROC_STATS_PKG_PROC},
{.puller = new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},
// Disk I/O stats per uid.
- {android::util::DISK_IO,
+ {{.atomTag = android::util::DISK_IO},
{.additiveFields = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
.coolDownNs = 3 * NS_PER_SEC,
.puller = new StatsCompanionServicePuller(android::util::DISK_IO)}},
// PowerProfile constants for power model calculations.
- {android::util::POWER_PROFILE,
+ {{.atomTag = android::util::POWER_PROFILE},
{.puller = new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
// Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
- {android::util::PROCESS_CPU_TIME,
+ {{.atomTag = android::util::PROCESS_CPU_TIME},
{.coolDownNs = 5 * NS_PER_SEC /* min cool-down in seconds*/,
.puller = new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
- {android::util::CPU_TIME_PER_THREAD_FREQ,
+ {{.atomTag = android::util::CPU_TIME_PER_THREAD_FREQ},
{.additiveFields = {7, 9, 11, 13, 15, 17, 19, 21},
.puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
// DeviceCalculatedPowerUse.
- {android::util::DEVICE_CALCULATED_POWER_USE,
+ {{.atomTag = android::util::DEVICE_CALCULATED_POWER_USE},
{.puller = new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
// DeviceCalculatedPowerBlameUid.
- {android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
+ {{.atomTag = android::util::DEVICE_CALCULATED_POWER_BLAME_UID},
{.puller = new StatsCompanionServicePuller(
android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
// DeviceCalculatedPowerBlameOther.
- {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
+ {{.atomTag = android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER},
{.puller = new StatsCompanionServicePuller(
android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
// DebugElapsedClock.
- {android::util::DEBUG_ELAPSED_CLOCK,
+ {{.atomTag = android::util::DEBUG_ELAPSED_CLOCK},
{.additiveFields = {1, 2, 3, 4},
.puller = new StatsCompanionServicePuller(android::util::DEBUG_ELAPSED_CLOCK)}},
// DebugFailingElapsedClock.
- {android::util::DEBUG_FAILING_ELAPSED_CLOCK,
+ {{.atomTag = android::util::DEBUG_FAILING_ELAPSED_CLOCK},
{.additiveFields = {1, 2, 3, 4},
.puller = new StatsCompanionServicePuller(android::util::DEBUG_FAILING_ELAPSED_CLOCK)}},
// BuildInformation.
- {android::util::BUILD_INFORMATION,
+ {{.atomTag = android::util::BUILD_INFORMATION},
{.puller = new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
// RoleHolder.
- {android::util::ROLE_HOLDER,
+ {{.atomTag = android::util::ROLE_HOLDER},
{.puller = new StatsCompanionServicePuller(android::util::ROLE_HOLDER)}},
// PermissionState.
- {android::util::DANGEROUS_PERMISSION_STATE,
+ {{.atomTag = android::util::DANGEROUS_PERMISSION_STATE},
{.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}},
// TrainInfo.
- {android::util::TRAIN_INFO, {.puller = new TrainInfoPuller()}},
+ {{.atomTag = android::util::TRAIN_INFO}, {.puller = new TrainInfoPuller()}},
// TimeZoneDataInfo.
- {android::util::TIME_ZONE_DATA_INFO,
+ {{.atomTag = android::util::TIME_ZONE_DATA_INFO},
{.puller = new StatsCompanionServicePuller(android::util::TIME_ZONE_DATA_INFO)}},
// ExternalStorageInfo
- {android::util::EXTERNAL_STORAGE_INFO,
+ {{.atomTag = android::util::EXTERNAL_STORAGE_INFO},
{.puller = new StatsCompanionServicePuller(android::util::EXTERNAL_STORAGE_INFO)}},
// GpuStatsGlobalInfo
- {android::util::GPU_STATS_GLOBAL_INFO,
+ {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO},
{.puller = new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}},
// GpuStatsAppInfo
- {android::util::GPU_STATS_APP_INFO,
+ {{.atomTag = android::util::GPU_STATS_APP_INFO},
{.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}},
// AppsOnExternalStorageInfo
- {android::util::APPS_ON_EXTERNAL_STORAGE_INFO,
+ {{.atomTag = android::util::APPS_ON_EXTERNAL_STORAGE_INFO},
{.puller = new StatsCompanionServicePuller(android::util::APPS_ON_EXTERNAL_STORAGE_INFO)}},
// Face Settings
- {android::util::FACE_SETTINGS,
+ {{.atomTag = android::util::FACE_SETTINGS},
{.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}},
// App ops
- {android::util::APP_OPS,
+ {{.atomTag = android::util::APP_OPS},
{.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}},
// SurfaceflingerStatsGlobalInfo
- {android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
+ {{.atomTag = android::util::SURFACEFLINGER_STATS_GLOBAL_INFO},
{.puller =
new SurfaceflingerStatsPuller(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO)}},
// VmsClientStats
- {android::util::VMS_CLIENT_STATS,
+ {{.atomTag = android::util::VMS_CLIENT_STATS},
{.additiveFields = {5, 6, 7, 8, 9, 10},
.puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
};
@@ -285,8 +289,8 @@ StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
VLOG("Initiating pulling %d", tagId);
- if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) {
- bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data);
+ if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
+ bool ret = kAllPullAtomInfo.find({.atomTag = tagId})->second.puller->Pull(data);
VLOG("pulled %d items", (int)data->size());
if (!ret) {
StatsdStats::getInstance().notePullFailed(tagId);
@@ -300,7 +304,8 @@ bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
bool StatsPullerManager::PullerForMatcherExists(int tagId) const {
// Vendor pulled atoms might be registered after we parse the config.
- return isVendorPulledAtom(tagId) || kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end();
+ return isVendorPulledAtom(tagId) ||
+ kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end();
}
void StatsPullerManager::updateAlarmLocked() {
@@ -469,6 +474,7 @@ int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
return totalCleared;
}
+// Deprecated, remove after puller API is complete.
void StatsPullerManager::RegisterPullerCallback(int32_t atomTag,
const sp<IStatsPullerCallback>& callback) {
AutoMutex _l(mLock);
@@ -479,7 +485,22 @@ void StatsPullerManager::RegisterPullerCallback(int32_t atomTag,
}
VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
- kAllPullAtomInfo[atomTag] = {.puller = new StatsCallbackPuller(atomTag, callback)};
+ kAllPullAtomInfo[{.atomTag = atomTag}] = {
+ .puller = new StatsCallbackPullerDeprecated(atomTag, callback)};
+}
+
+void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag,
+ const int64_t coolDownNs, const int64_t timeoutNs,
+ const vector<int32_t>& additiveFields,
+ const sp<IPullAtomCallback>& callback) {
+ AutoMutex _l(mLock);
+ VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
+ // TODO: linkToDeath with the callback so that we can remove it and delete the puller.
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
+ kAllPullAtomInfo[{.atomTag = atomTag}] = {.additiveFields = additiveFields,
+ .coolDownNs = coolDownNs,
+ .pullTimeoutNs = timeoutNs,
+ .puller = new StatsCallbackPuller(atomTag, callback)};
}
void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
@@ -489,7 +510,7 @@ void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
return;
}
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
- kAllPullAtomInfo.erase(atomTag);
+ kAllPullAtomInfo.erase({.atomTag = atomTag});
}
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 4ea1386bf78a..1bd9f92e4448 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -16,15 +16,18 @@
#pragma once
+#include <android/os/IPullAtomCallback.h>
#include <android/os/IStatsCompanionService.h>
#include <android/os/IStatsPullerCallback.h>
#include <binder/IServiceManager.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
+
#include <list>
#include <string>
#include <unordered_map>
#include <vector>
+
#include "PullDataReceiver.h"
#include "StatsPuller.h"
#include "guardrail/StatsdStats.h"
@@ -53,6 +56,27 @@ typedef struct {
int64_t pullTimeoutNs = StatsdStats::kPullMaxDelayNs;
} PullAtomInfo;
+typedef struct PullerKey {
+ // The uid of the process that registers this puller.
+ const int uid = -1;
+ // The atom that this puller is for.
+ const int atomTag;
+
+ bool operator<(const PullerKey& that) const {
+ if (uid < that.uid) {
+ return true;
+ }
+ if (uid > that.uid) {
+ return false;
+ }
+ return atomTag < that.atomTag;
+ };
+
+ bool operator==(const PullerKey& that) const {
+ return uid == that.uid && atomTag == that.atomTag;
+ };
+} PullerKey;
+
class StatsPullerManager : public virtual RefBase {
public:
StatsPullerManager();
@@ -92,12 +116,16 @@ public:
void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService);
- void RegisterPullerCallback(int32_t atomTag,
- const sp<IStatsPullerCallback>& callback);
+ // Deprecated, remove after puller API is complete.
+ void RegisterPullerCallback(int32_t atomTag, const sp<IStatsPullerCallback>& callback);
+
+ void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
+ const int64_t timeoutNs, const vector<int32_t>& additiveFields,
+ const sp<IPullAtomCallback>& callback);
void UnregisterPullerCallback(int32_t atomTag);
- static std::map<int, PullAtomInfo> kAllPullAtomInfo;
+ static std::map<PullerKey, PullAtomInfo> kAllPullAtomInfo;
private:
sp<IStatsCompanionService> mStatsCompanionService = nullptr;
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 0b9b6abfd6d6..53fa6301a836 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -55,7 +55,7 @@ using std::vector;
*/
void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
int tagId) {
- if (StatsPullerManager::kAllPullAtomInfo.find(tagId) ==
+ if (StatsPullerManager::kAllPullAtomInfo.find({.atomTag = tagId}) ==
StatsPullerManager::kAllPullAtomInfo.end()) {
VLOG("Unknown pull atom id %d", tagId);
return;
@@ -121,7 +121,7 @@ void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const
vector<shared_ptr<LogEvent>> mergedData;
const vector<int>& additiveFieldsVec =
- StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields;
+ StatsPullerManager::kAllPullAtomInfo.find({.atomTag = tagId})->second.additiveFields;
const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end());
bool needMerge = true;
diff --git a/config/hiddenapi-greylist-max-q.txt b/config/hiddenapi-greylist-max-q.txt
new file mode 100644
index 000000000000..a895a44f4023
--- /dev/null
+++ b/config/hiddenapi-greylist-max-q.txt
@@ -0,0 +1,703 @@
+Landroid/R$styleable;->ActionBar:[I
+Landroid/R$styleable;->ActionBar_background:I
+Landroid/R$styleable;->ActionBar_backgroundSplit:I
+Landroid/R$styleable;->ActionBar_backgroundStacked:I
+Landroid/R$styleable;->ActionBar_divider:I
+Landroid/R$styleable;->ActionBar_itemPadding:I
+Landroid/R$styleable;->CalendarView:[I
+Landroid/R$styleable;->CalendarView_dateTextAppearance:I
+Landroid/R$styleable;->CalendarView_firstDayOfWeek:I
+Landroid/R$styleable;->CalendarView_focusedMonthDateColor:I
+Landroid/R$styleable;->CalendarView_selectedDateVerticalBar:I
+Landroid/R$styleable;->CalendarView_selectedWeekBackgroundColor:I
+Landroid/R$styleable;->CalendarView_shownWeekCount:I
+Landroid/R$styleable;->CalendarView_showWeekNumber:I
+Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I
+Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I
+Landroid/R$styleable;->CalendarView_weekNumberColor:I
+Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I
+Landroid/R$styleable;->CheckBoxPreference:[I
+Landroid/R$styleable;->CheckedTextView:[I
+Landroid/R$styleable;->CheckedTextView_checkMark:I
+Landroid/R$styleable;->CompoundButton:[I
+Landroid/R$styleable;->CompoundButton_button:I
+Landroid/R$styleable;->ContactsDataKind:[I
+Landroid/R$styleable;->DatePicker:[I
+Landroid/R$styleable;->DialogPreference:[I
+Landroid/R$styleable;->DrawableStates:[I
+Landroid/R$styleable;->ExpandableListView:[I
+Landroid/R$styleable;->FrameLayout_Layout:[I
+Landroid/R$styleable;->HorizontalScrollView:[I
+Landroid/R$styleable;->ImageView:[I
+Landroid/R$styleable;->ImageView_adjustViewBounds:I
+Landroid/R$styleable;->ImageView_baselineAlignBottom:I
+Landroid/R$styleable;->ImageView_cropToPadding:I
+Landroid/R$styleable;->ImageView_maxHeight:I
+Landroid/R$styleable;->ImageView_maxWidth:I
+Landroid/R$styleable;->ImageView_scaleType:I
+Landroid/R$styleable;->ImageView_src:I
+Landroid/R$styleable;->ImageView_tint:I
+Landroid/R$styleable;->Keyboard:[I
+Landroid/R$styleable;->Keyboard_horizontalGap:I
+Landroid/R$styleable;->Keyboard_Key:[I
+Landroid/R$styleable;->Keyboard_keyHeight:I
+Landroid/R$styleable;->Keyboard_keyWidth:I
+Landroid/R$styleable;->Keyboard_Key_codes:I
+Landroid/R$styleable;->Keyboard_Key_iconPreview:I
+Landroid/R$styleable;->Keyboard_Key_isModifier:I
+Landroid/R$styleable;->Keyboard_Key_isRepeatable:I
+Landroid/R$styleable;->Keyboard_Key_isSticky:I
+Landroid/R$styleable;->Keyboard_Key_keyEdgeFlags:I
+Landroid/R$styleable;->Keyboard_Key_keyIcon:I
+Landroid/R$styleable;->Keyboard_Key_keyLabel:I
+Landroid/R$styleable;->Keyboard_Key_keyOutputText:I
+Landroid/R$styleable;->Keyboard_Key_popupCharacters:I
+Landroid/R$styleable;->Keyboard_Key_popupKeyboard:I
+Landroid/R$styleable;->Keyboard_Row:[I
+Landroid/R$styleable;->Keyboard_Row_keyboardMode:I
+Landroid/R$styleable;->Keyboard_Row_rowEdgeFlags:I
+Landroid/R$styleable;->Keyboard_verticalGap:I
+Landroid/R$styleable;->LinearLayout:[I
+Landroid/R$styleable;->LinearLayout_baselineAligned:I
+Landroid/R$styleable;->LinearLayout_baselineAlignedChildIndex:I
+Landroid/R$styleable;->LinearLayout_divider:I
+Landroid/R$styleable;->LinearLayout_dividerPadding:I
+Landroid/R$styleable;->LinearLayout_gravity:I
+Landroid/R$styleable;->LinearLayout_Layout:[I
+Landroid/R$styleable;->LinearLayout_Layout_layout_gravity:I
+Landroid/R$styleable;->LinearLayout_Layout_layout_height:I
+Landroid/R$styleable;->LinearLayout_Layout_layout_weight:I
+Landroid/R$styleable;->LinearLayout_Layout_layout_width:I
+Landroid/R$styleable;->LinearLayout_measureWithLargestChild:I
+Landroid/R$styleable;->LinearLayout_orientation:I
+Landroid/R$styleable;->LinearLayout_showDividers:I
+Landroid/R$styleable;->ListView:[I
+Landroid/R$styleable;->ListView_divider:I
+Landroid/R$styleable;->ListView_dividerHeight:I
+Landroid/R$styleable;->LockPatternView:[I
+Landroid/R$styleable;->NumberPicker:[I
+Landroid/R$styleable;->NumberPicker_solidColor:I
+Landroid/R$styleable;->PopupWindow:[I
+Landroid/R$styleable;->ProgressBar:[I
+Landroid/R$styleable;->ProgressBar_indeterminateDrawable:I
+Landroid/R$styleable;->ProgressBar_indeterminateDuration:I
+Landroid/R$styleable;->ProgressBar_maxHeight:I
+Landroid/R$styleable;->ProgressBar_maxWidth:I
+Landroid/R$styleable;->ProgressBar_minHeight:I
+Landroid/R$styleable;->ProgressBar_minWidth:I
+Landroid/R$styleable;->ProgressBar_progressDrawable:I
+Landroid/R$styleable;->RingtonePreference:[I
+Landroid/R$styleable;->ScrollView:[I
+Landroid/R$styleable;->SearchView:[I
+Landroid/R$styleable;->SeekBar:[I
+Landroid/R$styleable;->SeekBar_thumb:I
+Landroid/R$styleable;->SeekBar_thumbOffset:I
+Landroid/R$styleable;->SlidingDrawer:[I
+Landroid/R$styleable;->SlidingDrawer_allowSingleTap:I
+Landroid/R$styleable;->SlidingDrawer_animateOnClick:I
+Landroid/R$styleable;->SlidingDrawer_bottomOffset:I
+Landroid/R$styleable;->SlidingDrawer_content:I
+Landroid/R$styleable;->SlidingDrawer_handle:I
+Landroid/R$styleable;->SlidingDrawer_orientation:I
+Landroid/R$styleable;->SlidingDrawer_topOffset:I
+Landroid/R$styleable;->Switch:[I
+Landroid/R$styleable;->Switch_showText:I
+Landroid/R$styleable;->Switch_splitTrack:I
+Landroid/R$styleable;->Switch_switchMinWidth:I
+Landroid/R$styleable;->Switch_switchPadding:I
+Landroid/R$styleable;->Switch_switchTextAppearance:I
+Landroid/R$styleable;->Switch_textOff:I
+Landroid/R$styleable;->Switch_textOn:I
+Landroid/R$styleable;->Switch_thumb:I
+Landroid/R$styleable;->Switch_thumbTextPadding:I
+Landroid/R$styleable;->Switch_track:I
+Landroid/R$styleable;->TextAppearance:[I
+Landroid/R$styleable;->TextAppearance_textAllCaps:I
+Landroid/R$styleable;->TextAppearance_textColor:I
+Landroid/R$styleable;->TextAppearance_textColorHighlight:I
+Landroid/R$styleable;->TextAppearance_textColorHint:I
+Landroid/R$styleable;->TextAppearance_textColorLink:I
+Landroid/R$styleable;->TextAppearance_textSize:I
+Landroid/R$styleable;->TextAppearance_textStyle:I
+Landroid/R$styleable;->TextAppearance_typeface:I
+Landroid/R$styleable;->TextView:[I
+Landroid/R$styleable;->TextView_autoLink:I
+Landroid/R$styleable;->TextView_autoText:I
+Landroid/R$styleable;->TextView_bufferType:I
+Landroid/R$styleable;->TextView_capitalize:I
+Landroid/R$styleable;->TextView_cursorVisible:I
+Landroid/R$styleable;->TextView_digits:I
+Landroid/R$styleable;->TextView_drawableBottom:I
+Landroid/R$styleable;->TextView_drawableEnd:I
+Landroid/R$styleable;->TextView_drawableLeft:I
+Landroid/R$styleable;->TextView_drawablePadding:I
+Landroid/R$styleable;->TextView_drawableRight:I
+Landroid/R$styleable;->TextView_drawableStart:I
+Landroid/R$styleable;->TextView_drawableTop:I
+Landroid/R$styleable;->TextView_editable:I
+Landroid/R$styleable;->TextView_ellipsize:I
+Landroid/R$styleable;->TextView_ems:I
+Landroid/R$styleable;->TextView_enabled:I
+Landroid/R$styleable;->TextView_freezesText:I
+Landroid/R$styleable;->TextView_gravity:I
+Landroid/R$styleable;->TextView_height:I
+Landroid/R$styleable;->TextView_hint:I
+Landroid/R$styleable;->TextView_imeActionId:I
+Landroid/R$styleable;->TextView_imeActionLabel:I
+Landroid/R$styleable;->TextView_imeOptions:I
+Landroid/R$styleable;->TextView_includeFontPadding:I
+Landroid/R$styleable;->TextView_inputMethod:I
+Landroid/R$styleable;->TextView_inputType:I
+Landroid/R$styleable;->TextView_lines:I
+Landroid/R$styleable;->TextView_lineSpacingExtra:I
+Landroid/R$styleable;->TextView_lineSpacingMultiplier:I
+Landroid/R$styleable;->TextView_linksClickable:I
+Landroid/R$styleable;->TextView_marqueeRepeatLimit:I
+Landroid/R$styleable;->TextView_maxEms:I
+Landroid/R$styleable;->TextView_maxHeight:I
+Landroid/R$styleable;->TextView_maxLength:I
+Landroid/R$styleable;->TextView_maxLines:I
+Landroid/R$styleable;->TextView_maxWidth:I
+Landroid/R$styleable;->TextView_minEms:I
+Landroid/R$styleable;->TextView_minHeight:I
+Landroid/R$styleable;->TextView_minLines:I
+Landroid/R$styleable;->TextView_minWidth:I
+Landroid/R$styleable;->TextView_numeric:I
+Landroid/R$styleable;->TextView_password:I
+Landroid/R$styleable;->TextView_phoneNumber:I
+Landroid/R$styleable;->TextView_privateImeOptions:I
+Landroid/R$styleable;->TextView_scrollHorizontally:I
+Landroid/R$styleable;->TextView_selectAllOnFocus:I
+Landroid/R$styleable;->TextView_shadowColor:I
+Landroid/R$styleable;->TextView_shadowDx:I
+Landroid/R$styleable;->TextView_shadowDy:I
+Landroid/R$styleable;->TextView_shadowRadius:I
+Landroid/R$styleable;->TextView_singleLine:I
+Landroid/R$styleable;->TextView_text:I
+Landroid/R$styleable;->TextView_textAllCaps:I
+Landroid/R$styleable;->TextView_textAppearance:I
+Landroid/R$styleable;->TextView_textColor:I
+Landroid/R$styleable;->TextView_textColorHighlight:I
+Landroid/R$styleable;->TextView_textColorHint:I
+Landroid/R$styleable;->TextView_textColorLink:I
+Landroid/R$styleable;->TextView_textCursorDrawable:I
+Landroid/R$styleable;->TextView_textIsSelectable:I
+Landroid/R$styleable;->TextView_textScaleX:I
+Landroid/R$styleable;->TextView_textSelectHandle:I
+Landroid/R$styleable;->TextView_textSelectHandleLeft:I
+Landroid/R$styleable;->TextView_textSelectHandleRight:I
+Landroid/R$styleable;->TextView_textSize:I
+Landroid/R$styleable;->TextView_textStyle:I
+Landroid/R$styleable;->TextView_typeface:I
+Landroid/R$styleable;->TextView_width:I
+Landroid/R$styleable;->Theme:[I
+Landroid/R$styleable;->View:[I
+Landroid/R$styleable;->ViewDrawableStates:[I
+Landroid/R$styleable;->ViewGroup_Layout:[I
+Landroid/R$styleable;->ViewGroup_Layout_layout_height:I
+Landroid/R$styleable;->ViewGroup_Layout_layout_width:I
+Landroid/R$styleable;->ViewGroup_MarginLayout:[I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_height:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_margin:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginBottom:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginLeft:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginRight:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginTop:I
+Landroid/R$styleable;->ViewGroup_MarginLayout_layout_width:I
+Landroid/R$styleable;->View_alpha:I
+Landroid/R$styleable;->View_background:I
+Landroid/R$styleable;->View_clickable:I
+Landroid/R$styleable;->View_contentDescription:I
+Landroid/R$styleable;->View_drawingCacheQuality:I
+Landroid/R$styleable;->View_duplicateParentState:I
+Landroid/R$styleable;->View_fadingEdge:I
+Landroid/R$styleable;->View_filterTouchesWhenObscured:I
+Landroid/R$styleable;->View_fitsSystemWindows:I
+Landroid/R$styleable;->View_focusable:I
+Landroid/R$styleable;->View_focusableInTouchMode:I
+Landroid/R$styleable;->View_hapticFeedbackEnabled:I
+Landroid/R$styleable;->View_id:I
+Landroid/R$styleable;->View_isScrollContainer:I
+Landroid/R$styleable;->View_keepScreenOn:I
+Landroid/R$styleable;->View_longClickable:I
+Landroid/R$styleable;->View_minHeight:I
+Landroid/R$styleable;->View_minWidth:I
+Landroid/R$styleable;->View_nextFocusDown:I
+Landroid/R$styleable;->View_nextFocusLeft:I
+Landroid/R$styleable;->View_nextFocusRight:I
+Landroid/R$styleable;->View_nextFocusUp:I
+Landroid/R$styleable;->View_onClick:I
+Landroid/R$styleable;->View_overScrollMode:I
+Landroid/R$styleable;->View_padding:I
+Landroid/R$styleable;->View_paddingBottom:I
+Landroid/R$styleable;->View_paddingEnd:I
+Landroid/R$styleable;->View_paddingLeft:I
+Landroid/R$styleable;->View_paddingRight:I
+Landroid/R$styleable;->View_paddingStart:I
+Landroid/R$styleable;->View_paddingTop:I
+Landroid/R$styleable;->View_rotation:I
+Landroid/R$styleable;->View_rotationX:I
+Landroid/R$styleable;->View_rotationY:I
+Landroid/R$styleable;->View_saveEnabled:I
+Landroid/R$styleable;->View_scaleX:I
+Landroid/R$styleable;->View_scaleY:I
+Landroid/R$styleable;->View_scrollbarDefaultDelayBeforeFade:I
+Landroid/R$styleable;->View_scrollbarFadeDuration:I
+Landroid/R$styleable;->View_scrollbars:I
+Landroid/R$styleable;->View_scrollbarSize:I
+Landroid/R$styleable;->View_scrollbarStyle:I
+Landroid/R$styleable;->View_scrollbarThumbHorizontal:I
+Landroid/R$styleable;->View_scrollbarThumbVertical:I
+Landroid/R$styleable;->View_scrollbarTrackHorizontal:I
+Landroid/R$styleable;->View_scrollbarTrackVertical:I
+Landroid/R$styleable;->View_scrollX:I
+Landroid/R$styleable;->View_scrollY:I
+Landroid/R$styleable;->View_soundEffectsEnabled:I
+Landroid/R$styleable;->View_tag:I
+Landroid/R$styleable;->View_transformPivotX:I
+Landroid/R$styleable;->View_transformPivotY:I
+Landroid/R$styleable;->View_translationX:I
+Landroid/R$styleable;->View_translationY:I
+Landroid/R$styleable;->View_visibility:I
+Landroid/R$styleable;->Window:[I
+Landroid/R$styleable;->Window_windowBackground:I
+Landroid/R$styleable;->Window_windowFrame:I
+Lcom/android/internal/R$anim;->fade_in:I
+Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
+Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
+Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I
+Lcom/android/internal/R$array;->config_sms_enabled_locking_shift_tables:I
+Lcom/android/internal/R$array;->config_sms_enabled_single_shift_tables:I
+Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I
+Lcom/android/internal/R$array;->config_tether_upstream_types:I
+Lcom/android/internal/R$array;->config_tether_usb_regexs:I
+Lcom/android/internal/R$array;->config_tether_wifi_regexs:I
+Lcom/android/internal/R$array;->maps_starting_lat_lng:I
+Lcom/android/internal/R$array;->maps_starting_zoom:I
+Lcom/android/internal/R$attr;->actionBarStyle:I
+Lcom/android/internal/R$attr;->buttonStyle:I
+Lcom/android/internal/R$attr;->description:I
+Lcom/android/internal/R$attr;->editTextStyle:I
+Lcom/android/internal/R$attr;->mapViewStyle:I
+Lcom/android/internal/R$attr;->popupWindowStyle:I
+Lcom/android/internal/R$attr;->state_above_anchor:I
+Lcom/android/internal/R$attr;->state_focused:I
+Lcom/android/internal/R$attr;->state_pressed:I
+Lcom/android/internal/R$attr;->state_selected:I
+Lcom/android/internal/R$attr;->switchStyle:I
+Lcom/android/internal/R$attr;->text:I
+Lcom/android/internal/R$attr;->title:I
+Lcom/android/internal/R$attr;->webViewStyle:I
+Lcom/android/internal/R$bool;-><init>()V
+Lcom/android/internal/R$bool;->config_automatic_brightness_available:I
+Lcom/android/internal/R$bool;->config_intrusiveNotificationLed:I
+Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I
+Lcom/android/internal/R$bool;->config_showNavigationBar:I
+Lcom/android/internal/R$dimen;-><init>()V
+Lcom/android/internal/R$dimen;->item_touch_helper_max_drag_scroll_per_frame:I
+Lcom/android/internal/R$dimen;->navigation_bar_height:I
+Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I
+Lcom/android/internal/R$dimen;->navigation_bar_width:I
+Lcom/android/internal/R$dimen;->status_bar_height:I
+Lcom/android/internal/R$dimen;->toast_y_offset:I
+Lcom/android/internal/R$drawable;->btn_check_off:I
+Lcom/android/internal/R$drawable;->compass_arrow:I
+Lcom/android/internal/R$drawable;->compass_base:I
+Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I
+Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I
+Lcom/android/internal/R$drawable;->loading_tile_android:I
+Lcom/android/internal/R$drawable;->maps_google_logo:I
+Lcom/android/internal/R$drawable;->no_tile_256:I
+Lcom/android/internal/R$drawable;->reticle:I
+Lcom/android/internal/R$drawable;->stat_sys_download:I
+Lcom/android/internal/R$fraction;->config_autoBrightnessAdjustmentMaxGamma:I
+Lcom/android/internal/R$id;->account_name:I
+Lcom/android/internal/R$id;->account_type:I
+Lcom/android/internal/R$id;->alertTitle:I
+Lcom/android/internal/R$id;->allow_button:I
+Lcom/android/internal/R$id;->amPm:I
+Lcom/android/internal/R$id;->authtoken_type:I
+Lcom/android/internal/R$id;->background:I
+Lcom/android/internal/R$id;->back_button:I
+Lcom/android/internal/R$id;->body:I
+Lcom/android/internal/R$id;->buttonPanel:I
+Lcom/android/internal/R$id;->camera:I
+Lcom/android/internal/R$id;->cancel:I
+Lcom/android/internal/R$id;->clip_children_set_tag:I
+Lcom/android/internal/R$id;->clip_children_tag:I
+Lcom/android/internal/R$id;->clip_to_padding_tag:I
+Lcom/android/internal/R$id;->closeButton:I
+Lcom/android/internal/R$id;->content:I
+Lcom/android/internal/R$id;->contentPanel:I
+Lcom/android/internal/R$id;->custom:I
+Lcom/android/internal/R$id;->customPanel:I
+Lcom/android/internal/R$id;->datePicker:I
+Lcom/android/internal/R$id;->day:I
+Lcom/android/internal/R$id;->deny_button:I
+Lcom/android/internal/R$id;->description:I
+Lcom/android/internal/R$id;->edit:I
+Lcom/android/internal/R$id;->edittext_container:I
+Lcom/android/internal/R$id;->find_next:I
+Lcom/android/internal/R$id;->find_prev:I
+Lcom/android/internal/R$id;->icon:I
+Lcom/android/internal/R$id;->keyboard:I
+Lcom/android/internal/R$id;->keyboardView:I
+Lcom/android/internal/R$id;->line1:I
+Lcom/android/internal/R$id;->list_item:I
+Lcom/android/internal/R$id;->matches:I
+Lcom/android/internal/R$id;->mediacontroller_progress:I
+Lcom/android/internal/R$id;->media_actions:I
+Lcom/android/internal/R$id;->message:I
+Lcom/android/internal/R$id;->minute:I
+Lcom/android/internal/R$id;->month:I
+Lcom/android/internal/R$id;->notification_header:I
+Lcom/android/internal/R$id;->ok:I
+Lcom/android/internal/R$id;->overlay:I
+Lcom/android/internal/R$id;->packages_list:I
+Lcom/android/internal/R$id;->package_label:I
+Lcom/android/internal/R$id;->parentPanel:I
+Lcom/android/internal/R$id;->pause:I
+Lcom/android/internal/R$id;->pending_intent_tag:I
+Lcom/android/internal/R$id;->progress:I
+Lcom/android/internal/R$id;->redo:I
+Lcom/android/internal/R$id;->remote_input_tag:I
+Lcom/android/internal/R$id;->right_icon:I
+Lcom/android/internal/R$id;->search_src_text:I
+Lcom/android/internal/R$id;->share:I
+Lcom/android/internal/R$id;->shortcut:I
+Lcom/android/internal/R$id;->status_bar_latest_event_content:I
+Lcom/android/internal/R$id;->tabcontent:I
+Lcom/android/internal/R$id;->tabs:I
+Lcom/android/internal/R$id;->text1:I
+Lcom/android/internal/R$id;->text2:I
+Lcom/android/internal/R$id;->text:I
+Lcom/android/internal/R$id;->time:I
+Lcom/android/internal/R$id;->timePicker:I
+Lcom/android/internal/R$id;->time_current:I
+Lcom/android/internal/R$id;->title:I
+Lcom/android/internal/R$id;->titleDivider:I
+Lcom/android/internal/R$id;->titleDividerTop:I
+Lcom/android/internal/R$id;->title_container:I
+Lcom/android/internal/R$id;->title_template:I
+Lcom/android/internal/R$id;->topPanel:I
+Lcom/android/internal/R$id;->up:I
+Lcom/android/internal/R$id;->year:I
+Lcom/android/internal/R$id;->zoomControls:I
+Lcom/android/internal/R$id;->zoomMagnify:I
+Lcom/android/internal/R$integer;->config_screenBrightnessDim:I
+Lcom/android/internal/R$integer;->config_screenBrightnessSettingMaximum:I
+Lcom/android/internal/R$integer;->config_screenBrightnessSettingMinimum:I
+Lcom/android/internal/R$integer;->config_toastDefaultGravity:I
+Lcom/android/internal/R$interpolator;->accelerate_cubic:I
+Lcom/android/internal/R$interpolator;->decelerate_cubic:I
+Lcom/android/internal/R$layout;->notification_template_material_base:I
+Lcom/android/internal/R$layout;->preference_header_item:I
+Lcom/android/internal/R$layout;->screen_title:I
+Lcom/android/internal/R$layout;->select_dialog:I
+Lcom/android/internal/R$layout;->select_dialog_multichoice:I
+Lcom/android/internal/R$layout;->select_dialog_singlechoice:I
+Lcom/android/internal/R$layout;->webview_find:I
+Lcom/android/internal/R$layout;->zoom_magnify:I
+Lcom/android/internal/R$plurals;->matches_found:I
+Lcom/android/internal/R$raw;->loaderror:I
+Lcom/android/internal/R$raw;->nodomain:I
+Lcom/android/internal/R$string;->byteShort:I
+Lcom/android/internal/R$string;->cancel:I
+Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I
+Lcom/android/internal/R$string;->gigabyteShort:I
+Lcom/android/internal/R$string;->kilobyteShort:I
+Lcom/android/internal/R$string;->map:I
+Lcom/android/internal/R$string;->megabyteShort:I
+Lcom/android/internal/R$string;->notification_title:I
+Lcom/android/internal/R$string;->no_matches:I
+Lcom/android/internal/R$string;->ok:I
+Lcom/android/internal/R$string;->petabyteShort:I
+Lcom/android/internal/R$string;->redo:I
+Lcom/android/internal/R$string;->share:I
+Lcom/android/internal/R$string;->terabyteShort:I
+Lcom/android/internal/R$string;->whichApplication:I
+Lcom/android/internal/R$style;->Animation_DropDownDown:I
+Lcom/android/internal/R$style;->Animation_DropDownUp:I
+Lcom/android/internal/R$style;->Animation_PopupWindow:I
+Lcom/android/internal/R$style;->Theme:I
+Lcom/android/internal/R$style;->Theme_Dialog_Alert:I
+Lcom/android/internal/R$style;->Theme_Holo_Light:I
+Lcom/android/internal/R$style;->Theme_Light:I
+Lcom/android/internal/R$styleable;-><init>()V
+Lcom/android/internal/R$styleable;->AbsListView:[I
+Lcom/android/internal/R$styleable;->AbsListView_cacheColorHint:I
+Lcom/android/internal/R$styleable;->AbsListView_choiceMode:I
+Lcom/android/internal/R$styleable;->AbsListView_drawSelectorOnTop:I
+Lcom/android/internal/R$styleable;->AbsListView_fastScrollAlwaysVisible:I
+Lcom/android/internal/R$styleable;->AbsListView_fastScrollEnabled:I
+Lcom/android/internal/R$styleable;->AbsListView_listSelector:I
+Lcom/android/internal/R$styleable;->AbsListView_scrollingCache:I
+Lcom/android/internal/R$styleable;->AbsListView_smoothScrollbar:I
+Lcom/android/internal/R$styleable;->AbsListView_stackFromBottom:I
+Lcom/android/internal/R$styleable;->AbsListView_textFilterEnabled:I
+Lcom/android/internal/R$styleable;->AbsListView_transcriptMode:I
+Lcom/android/internal/R$styleable;->AbsSpinner:[I
+Lcom/android/internal/R$styleable;->AccountAuthenticator:[I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_accountPreferences:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon:I
+Lcom/android/internal/R$styleable;->ActionMode:[I
+Lcom/android/internal/R$styleable;->AdapterViewAnimator:[I
+Lcom/android/internal/R$styleable;->AdapterViewFlipper:[I
+Lcom/android/internal/R$styleable;->AlertDialog:[I
+Lcom/android/internal/R$styleable;->AnalogClock:[I
+Lcom/android/internal/R$styleable;->AndroidManifest:[I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity:[I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_allowTaskReparenting:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_configChanges:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_description:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_enabled:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_excludeFromRecents:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_exported:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_hardwareAccelerated:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_icon:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_immersive:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_label:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_launchMode:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_logo:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_noHistory:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_permission:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_process:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_screenOrientation:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_taskAffinity:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_theme:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_uiOptions:I
+Lcom/android/internal/R$styleable;->AndroidManifestActivity_windowSoftInputMode:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I
+Lcom/android/internal/R$styleable;->AndroidManifestData:[I
+Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter:[I
+Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter_priority:I
+Lcom/android/internal/R$styleable;->AndroidManifestMetaData:[I
+Lcom/android/internal/R$styleable;->AndroidManifestMetaData_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestMetaData_resource:I
+Lcom/android/internal/R$styleable;->AndroidManifestMetaData_value:I
+Lcom/android/internal/R$styleable;->AndroidManifestPackageVerifier:[I
+Lcom/android/internal/R$styleable;->AndroidManifestProvider:[I
+Lcom/android/internal/R$styleable;->AndroidManifestService:[I
+Lcom/android/internal/R$styleable;->AndroidManifestService_enabled:I
+Lcom/android/internal/R$styleable;->AndroidManifestService_exported:I
+Lcom/android/internal/R$styleable;->AndroidManifestService_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestService_permission:I
+Lcom/android/internal/R$styleable;->AndroidManifestService_process:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesLibrary:[I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I
+Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I
+Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I
+Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I
+Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I
+Lcom/android/internal/R$styleable;->AutoCompleteTextView:[I
+Lcom/android/internal/R$styleable;->CheckBoxPreference:[I
+Lcom/android/internal/R$styleable;->CheckBoxPreference_disableDependentsState:I
+Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOff:I
+Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOn:I
+Lcom/android/internal/R$styleable;->CheckedTextView:[I
+Lcom/android/internal/R$styleable;->CheckedTextView_checked:I
+Lcom/android/internal/R$styleable;->CheckedTextView_checkMark:I
+Lcom/android/internal/R$styleable;->CompoundButton:[I
+Lcom/android/internal/R$styleable;->CompoundButton_button:I
+Lcom/android/internal/R$styleable;->CompoundButton_checked:I
+Lcom/android/internal/R$styleable;->ContactsDataKind:[I
+Lcom/android/internal/R$styleable;->DatePicker:[I
+Lcom/android/internal/R$styleable;->DialogPreference:[I
+Lcom/android/internal/R$styleable;->DialogPreference_dialogTitle:I
+Lcom/android/internal/R$styleable;->Dream:[I
+Lcom/android/internal/R$styleable;->EdgeEffect:[I
+Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I
+Lcom/android/internal/R$styleable;->FastScroll:[I
+Lcom/android/internal/R$styleable;->FrameLayout:[I
+Lcom/android/internal/R$styleable;->FrameLayout_Layout:[I
+Lcom/android/internal/R$styleable;->Gallery:[I
+Lcom/android/internal/R$styleable;->GridView:[I
+Lcom/android/internal/R$styleable;->IconMenuView:[I
+Lcom/android/internal/R$styleable;->ImageView:[I
+Lcom/android/internal/R$styleable;->ImageView_scaleType:I
+Lcom/android/internal/R$styleable;->ImageView_src:I
+Lcom/android/internal/R$styleable;->Keyboard:[I
+Lcom/android/internal/R$styleable;->KeyboardView:[I
+Lcom/android/internal/R$styleable;->Keyboard_Key:[I
+Lcom/android/internal/R$styleable;->Keyboard_Row:[I
+Lcom/android/internal/R$styleable;->ListPreference:[I
+Lcom/android/internal/R$styleable;->ListPreference_entries:I
+Lcom/android/internal/R$styleable;->ListView:[I
+Lcom/android/internal/R$styleable;->ListView_divider:I
+Lcom/android/internal/R$styleable;->ListView_dividerHeight:I
+Lcom/android/internal/R$styleable;->ListView_entries:I
+Lcom/android/internal/R$styleable;->ListView_footerDividersEnabled:I
+Lcom/android/internal/R$styleable;->ListView_headerDividersEnabled:I
+Lcom/android/internal/R$styleable;->ListView_overScrollFooter:I
+Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I
+Lcom/android/internal/R$styleable;->MapView:[I
+Lcom/android/internal/R$styleable;->MapView_apiKey:I
+Lcom/android/internal/R$styleable;->MenuGroup:[I
+Lcom/android/internal/R$styleable;->MenuItem:[I
+Lcom/android/internal/R$styleable;->NumberPicker:[I
+Lcom/android/internal/R$styleable;->PopupWindow:[I
+Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I
+Lcom/android/internal/R$styleable;->PopupWindow_popupBackground:I
+Lcom/android/internal/R$styleable;->Preference:[I
+Lcom/android/internal/R$styleable;->PreferenceGroup:[I
+Lcom/android/internal/R$styleable;->PreferenceGroup_orderingFromXml:I
+Lcom/android/internal/R$styleable;->Preference_defaultValue:I
+Lcom/android/internal/R$styleable;->Preference_dependency:I
+Lcom/android/internal/R$styleable;->Preference_enabled:I
+Lcom/android/internal/R$styleable;->Preference_fragment:I
+Lcom/android/internal/R$styleable;->Preference_icon:I
+Lcom/android/internal/R$styleable;->Preference_key:I
+Lcom/android/internal/R$styleable;->Preference_layout:I
+Lcom/android/internal/R$styleable;->Preference_order:I
+Lcom/android/internal/R$styleable;->Preference_persistent:I
+Lcom/android/internal/R$styleable;->Preference_selectable:I
+Lcom/android/internal/R$styleable;->Preference_shouldDisableView:I
+Lcom/android/internal/R$styleable;->Preference_summary:I
+Lcom/android/internal/R$styleable;->Preference_title:I
+Lcom/android/internal/R$styleable;->Preference_widgetLayout:I
+Lcom/android/internal/R$styleable;->ProgressBar:[I
+Lcom/android/internal/R$styleable;->QuickContactBadge:[I
+Lcom/android/internal/R$styleable;->RingtonePreference:[I
+Lcom/android/internal/R$styleable;->ScrollView:[I
+Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I
+Lcom/android/internal/R$styleable;->SelectionModeDrawables:[I
+Lcom/android/internal/R$styleable;->Switch:[I
+Lcom/android/internal/R$styleable;->SwitchPreference:[I
+Lcom/android/internal/R$styleable;->SyncAdapter:[I
+Lcom/android/internal/R$styleable;->SyncAdapter_accountType:I
+Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I
+Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I
+Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I
+Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I
+Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I
+Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I
+Lcom/android/internal/R$styleable;->TabWidget:[I
+Lcom/android/internal/R$styleable;->TextAppearance:[I
+Lcom/android/internal/R$styleable;->TextAppearance_fontFamily:I
+Lcom/android/internal/R$styleable;->TextAppearance_textAllCaps:I
+Lcom/android/internal/R$styleable;->TextAppearance_textColor:I
+Lcom/android/internal/R$styleable;->TextAppearance_textColorHighlight:I
+Lcom/android/internal/R$styleable;->TextAppearance_textColorHint:I
+Lcom/android/internal/R$styleable;->TextAppearance_textColorLink:I
+Lcom/android/internal/R$styleable;->TextAppearance_textSize:I
+Lcom/android/internal/R$styleable;->TextAppearance_textStyle:I
+Lcom/android/internal/R$styleable;->TextAppearance_typeface:I
+Lcom/android/internal/R$styleable;->TextClock:[I
+Lcom/android/internal/R$styleable;->TextView:[I
+Lcom/android/internal/R$styleable;->TextViewAppearance:[I
+Lcom/android/internal/R$styleable;->TextViewAppearance_textAppearance:I
+Lcom/android/internal/R$styleable;->TextView_autoLink:I
+Lcom/android/internal/R$styleable;->TextView_autoText:I
+Lcom/android/internal/R$styleable;->TextView_bufferType:I
+Lcom/android/internal/R$styleable;->TextView_capitalize:I
+Lcom/android/internal/R$styleable;->TextView_cursorVisible:I
+Lcom/android/internal/R$styleable;->TextView_digits:I
+Lcom/android/internal/R$styleable;->TextView_drawableBottom:I
+Lcom/android/internal/R$styleable;->TextView_drawableEnd:I
+Lcom/android/internal/R$styleable;->TextView_drawableLeft:I
+Lcom/android/internal/R$styleable;->TextView_drawablePadding:I
+Lcom/android/internal/R$styleable;->TextView_drawableRight:I
+Lcom/android/internal/R$styleable;->TextView_drawableStart:I
+Lcom/android/internal/R$styleable;->TextView_drawableTop:I
+Lcom/android/internal/R$styleable;->TextView_editable:I
+Lcom/android/internal/R$styleable;->TextView_editorExtras:I
+Lcom/android/internal/R$styleable;->TextView_ellipsize:I
+Lcom/android/internal/R$styleable;->TextView_ems:I
+Lcom/android/internal/R$styleable;->TextView_enabled:I
+Lcom/android/internal/R$styleable;->TextView_freezesText:I
+Lcom/android/internal/R$styleable;->TextView_gravity:I
+Lcom/android/internal/R$styleable;->TextView_height:I
+Lcom/android/internal/R$styleable;->TextView_hint:I
+Lcom/android/internal/R$styleable;->TextView_imeActionId:I
+Lcom/android/internal/R$styleable;->TextView_imeActionLabel:I
+Lcom/android/internal/R$styleable;->TextView_imeOptions:I
+Lcom/android/internal/R$styleable;->TextView_includeFontPadding:I
+Lcom/android/internal/R$styleable;->TextView_inputMethod:I
+Lcom/android/internal/R$styleable;->TextView_inputType:I
+Lcom/android/internal/R$styleable;->TextView_lines:I
+Lcom/android/internal/R$styleable;->TextView_lineSpacingExtra:I
+Lcom/android/internal/R$styleable;->TextView_lineSpacingMultiplier:I
+Lcom/android/internal/R$styleable;->TextView_linksClickable:I
+Lcom/android/internal/R$styleable;->TextView_marqueeRepeatLimit:I
+Lcom/android/internal/R$styleable;->TextView_maxEms:I
+Lcom/android/internal/R$styleable;->TextView_maxHeight:I
+Lcom/android/internal/R$styleable;->TextView_maxLength:I
+Lcom/android/internal/R$styleable;->TextView_maxLines:I
+Lcom/android/internal/R$styleable;->TextView_maxWidth:I
+Lcom/android/internal/R$styleable;->TextView_minEms:I
+Lcom/android/internal/R$styleable;->TextView_minHeight:I
+Lcom/android/internal/R$styleable;->TextView_minLines:I
+Lcom/android/internal/R$styleable;->TextView_minWidth:I
+Lcom/android/internal/R$styleable;->TextView_numeric:I
+Lcom/android/internal/R$styleable;->TextView_password:I
+Lcom/android/internal/R$styleable;->TextView_phoneNumber:I
+Lcom/android/internal/R$styleable;->TextView_privateImeOptions:I
+Lcom/android/internal/R$styleable;->TextView_scrollHorizontally:I
+Lcom/android/internal/R$styleable;->TextView_selectAllOnFocus:I
+Lcom/android/internal/R$styleable;->TextView_shadowColor:I
+Lcom/android/internal/R$styleable;->TextView_shadowDx:I
+Lcom/android/internal/R$styleable;->TextView_shadowDy:I
+Lcom/android/internal/R$styleable;->TextView_shadowRadius:I
+Lcom/android/internal/R$styleable;->TextView_singleLine:I
+Lcom/android/internal/R$styleable;->TextView_text:I
+Lcom/android/internal/R$styleable;->TextView_textAllCaps:I
+Lcom/android/internal/R$styleable;->TextView_textAppearance:I
+Lcom/android/internal/R$styleable;->TextView_textColor:I
+Lcom/android/internal/R$styleable;->TextView_textColorHighlight:I
+Lcom/android/internal/R$styleable;->TextView_textColorHint:I
+Lcom/android/internal/R$styleable;->TextView_textColorLink:I
+Lcom/android/internal/R$styleable;->TextView_textCursorDrawable:I
+Lcom/android/internal/R$styleable;->TextView_textEditSuggestionItemLayout:I
+Lcom/android/internal/R$styleable;->TextView_textIsSelectable:I
+Lcom/android/internal/R$styleable;->TextView_textScaleX:I
+Lcom/android/internal/R$styleable;->TextView_textSelectHandle:I
+Lcom/android/internal/R$styleable;->TextView_textSelectHandleLeft:I
+Lcom/android/internal/R$styleable;->TextView_textSelectHandleRight:I
+Lcom/android/internal/R$styleable;->TextView_textSize:I
+Lcom/android/internal/R$styleable;->TextView_textStyle:I
+Lcom/android/internal/R$styleable;->TextView_typeface:I
+Lcom/android/internal/R$styleable;->TextView_width:I
+Lcom/android/internal/R$styleable;->Theme:[I
+Lcom/android/internal/R$styleable;->TwoLineListItem:[I
+Lcom/android/internal/R$styleable;->View:[I
+Lcom/android/internal/R$styleable;->ViewAnimator:[I
+Lcom/android/internal/R$styleable;->ViewFlipper:[I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I
+Lcom/android/internal/R$styleable;->ViewStub:[I
+Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I
+Lcom/android/internal/R$styleable;->ViewStub_layout:I
+Lcom/android/internal/R$styleable;->View_background:I
+Lcom/android/internal/R$styleable;->View_clickable:I
+Lcom/android/internal/R$styleable;->View_focusable:I
+Lcom/android/internal/R$styleable;->View_id:I
+Lcom/android/internal/R$styleable;->View_longClickable:I
+Lcom/android/internal/R$styleable;->WallpaperPreviewInfo:[I
+Lcom/android/internal/R$styleable;->Window:[I
+Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
+Lcom/android/internal/R$styleable;->Window_windowBackground:I
+Lcom/android/internal/R$styleable;->Window_windowFullscreen:I
+Lcom/android/internal/R$styleable;->Window_windowIsFloating:I
+Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I
+Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I
+Lcom/android/internal/R$xml;->power_profile:I
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index e5750b9d64b5..a3543dc7f4ee 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -238,270 +238,6 @@ Landroid/os/IVibratorService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os
Landroid/os/storage/IObbActionListener$Stub;-><init>()V
Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
-Landroid/R$styleable;->ActionBar:[I
-Landroid/R$styleable;->ActionBar_background:I
-Landroid/R$styleable;->ActionBar_backgroundSplit:I
-Landroid/R$styleable;->ActionBar_backgroundStacked:I
-Landroid/R$styleable;->ActionBar_divider:I
-Landroid/R$styleable;->ActionBar_itemPadding:I
-Landroid/R$styleable;->CalendarView:[I
-Landroid/R$styleable;->CalendarView_dateTextAppearance:I
-Landroid/R$styleable;->CalendarView_firstDayOfWeek:I
-Landroid/R$styleable;->CalendarView_focusedMonthDateColor:I
-Landroid/R$styleable;->CalendarView_selectedDateVerticalBar:I
-Landroid/R$styleable;->CalendarView_selectedWeekBackgroundColor:I
-Landroid/R$styleable;->CalendarView_shownWeekCount:I
-Landroid/R$styleable;->CalendarView_showWeekNumber:I
-Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I
-Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I
-Landroid/R$styleable;->CalendarView_weekNumberColor:I
-Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I
-Landroid/R$styleable;->CheckBoxPreference:[I
-Landroid/R$styleable;->CheckedTextView:[I
-Landroid/R$styleable;->CheckedTextView_checkMark:I
-Landroid/R$styleable;->CompoundButton:[I
-Landroid/R$styleable;->CompoundButton_button:I
-Landroid/R$styleable;->ContactsDataKind:[I
-Landroid/R$styleable;->DatePicker:[I
-Landroid/R$styleable;->DialogPreference:[I
-Landroid/R$styleable;->DrawableStates:[I
-Landroid/R$styleable;->ExpandableListView:[I
-Landroid/R$styleable;->FrameLayout_Layout:[I
-Landroid/R$styleable;->HorizontalScrollView:[I
-Landroid/R$styleable;->ImageView:[I
-Landroid/R$styleable;->ImageView_adjustViewBounds:I
-Landroid/R$styleable;->ImageView_baselineAlignBottom:I
-Landroid/R$styleable;->ImageView_cropToPadding:I
-Landroid/R$styleable;->ImageView_maxHeight:I
-Landroid/R$styleable;->ImageView_maxWidth:I
-Landroid/R$styleable;->ImageView_scaleType:I
-Landroid/R$styleable;->ImageView_src:I
-Landroid/R$styleable;->ImageView_tint:I
-Landroid/R$styleable;->Keyboard:[I
-Landroid/R$styleable;->Keyboard_horizontalGap:I
-Landroid/R$styleable;->Keyboard_Key:[I
-Landroid/R$styleable;->Keyboard_keyHeight:I
-Landroid/R$styleable;->Keyboard_keyWidth:I
-Landroid/R$styleable;->Keyboard_Key_codes:I
-Landroid/R$styleable;->Keyboard_Key_iconPreview:I
-Landroid/R$styleable;->Keyboard_Key_isModifier:I
-Landroid/R$styleable;->Keyboard_Key_isRepeatable:I
-Landroid/R$styleable;->Keyboard_Key_isSticky:I
-Landroid/R$styleable;->Keyboard_Key_keyEdgeFlags:I
-Landroid/R$styleable;->Keyboard_Key_keyIcon:I
-Landroid/R$styleable;->Keyboard_Key_keyLabel:I
-Landroid/R$styleable;->Keyboard_Key_keyOutputText:I
-Landroid/R$styleable;->Keyboard_Key_popupCharacters:I
-Landroid/R$styleable;->Keyboard_Key_popupKeyboard:I
-Landroid/R$styleable;->Keyboard_Row:[I
-Landroid/R$styleable;->Keyboard_Row_keyboardMode:I
-Landroid/R$styleable;->Keyboard_Row_rowEdgeFlags:I
-Landroid/R$styleable;->Keyboard_verticalGap:I
-Landroid/R$styleable;->LinearLayout:[I
-Landroid/R$styleable;->LinearLayout_baselineAligned:I
-Landroid/R$styleable;->LinearLayout_baselineAlignedChildIndex:I
-Landroid/R$styleable;->LinearLayout_divider:I
-Landroid/R$styleable;->LinearLayout_dividerPadding:I
-Landroid/R$styleable;->LinearLayout_gravity:I
-Landroid/R$styleable;->LinearLayout_Layout:[I
-Landroid/R$styleable;->LinearLayout_Layout_layout_gravity:I
-Landroid/R$styleable;->LinearLayout_Layout_layout_height:I
-Landroid/R$styleable;->LinearLayout_Layout_layout_weight:I
-Landroid/R$styleable;->LinearLayout_Layout_layout_width:I
-Landroid/R$styleable;->LinearLayout_measureWithLargestChild:I
-Landroid/R$styleable;->LinearLayout_orientation:I
-Landroid/R$styleable;->LinearLayout_showDividers:I
-Landroid/R$styleable;->ListView:[I
-Landroid/R$styleable;->ListView_divider:I
-Landroid/R$styleable;->ListView_dividerHeight:I
-Landroid/R$styleable;->LockPatternView:[I
-Landroid/R$styleable;->NumberPicker:[I
-Landroid/R$styleable;->NumberPicker_solidColor:I
-Landroid/R$styleable;->PopupWindow:[I
-Landroid/R$styleable;->ProgressBar:[I
-Landroid/R$styleable;->ProgressBar_indeterminateDrawable:I
-Landroid/R$styleable;->ProgressBar_indeterminateDuration:I
-Landroid/R$styleable;->ProgressBar_maxHeight:I
-Landroid/R$styleable;->ProgressBar_maxWidth:I
-Landroid/R$styleable;->ProgressBar_minHeight:I
-Landroid/R$styleable;->ProgressBar_minWidth:I
-Landroid/R$styleable;->ProgressBar_progressDrawable:I
-Landroid/R$styleable;->RingtonePreference:[I
-Landroid/R$styleable;->ScrollView:[I
-Landroid/R$styleable;->SearchView:[I
-Landroid/R$styleable;->SeekBar:[I
-Landroid/R$styleable;->SeekBar_thumb:I
-Landroid/R$styleable;->SeekBar_thumbOffset:I
-Landroid/R$styleable;->SlidingDrawer:[I
-Landroid/R$styleable;->SlidingDrawer_allowSingleTap:I
-Landroid/R$styleable;->SlidingDrawer_animateOnClick:I
-Landroid/R$styleable;->SlidingDrawer_bottomOffset:I
-Landroid/R$styleable;->SlidingDrawer_content:I
-Landroid/R$styleable;->SlidingDrawer_handle:I
-Landroid/R$styleable;->SlidingDrawer_orientation:I
-Landroid/R$styleable;->SlidingDrawer_topOffset:I
-Landroid/R$styleable;->Switch:[I
-Landroid/R$styleable;->Switch_showText:I
-Landroid/R$styleable;->Switch_splitTrack:I
-Landroid/R$styleable;->Switch_switchMinWidth:I
-Landroid/R$styleable;->Switch_switchPadding:I
-Landroid/R$styleable;->Switch_switchTextAppearance:I
-Landroid/R$styleable;->Switch_textOff:I
-Landroid/R$styleable;->Switch_textOn:I
-Landroid/R$styleable;->Switch_thumb:I
-Landroid/R$styleable;->Switch_thumbTextPadding:I
-Landroid/R$styleable;->Switch_track:I
-Landroid/R$styleable;->TextAppearance:[I
-Landroid/R$styleable;->TextAppearance_textAllCaps:I
-Landroid/R$styleable;->TextAppearance_textColor:I
-Landroid/R$styleable;->TextAppearance_textColorHighlight:I
-Landroid/R$styleable;->TextAppearance_textColorHint:I
-Landroid/R$styleable;->TextAppearance_textColorLink:I
-Landroid/R$styleable;->TextAppearance_textSize:I
-Landroid/R$styleable;->TextAppearance_textStyle:I
-Landroid/R$styleable;->TextAppearance_typeface:I
-Landroid/R$styleable;->TextView:[I
-Landroid/R$styleable;->TextView_autoLink:I
-Landroid/R$styleable;->TextView_autoText:I
-Landroid/R$styleable;->TextView_bufferType:I
-Landroid/R$styleable;->TextView_capitalize:I
-Landroid/R$styleable;->TextView_cursorVisible:I
-Landroid/R$styleable;->TextView_digits:I
-Landroid/R$styleable;->TextView_drawableBottom:I
-Landroid/R$styleable;->TextView_drawableEnd:I
-Landroid/R$styleable;->TextView_drawableLeft:I
-Landroid/R$styleable;->TextView_drawablePadding:I
-Landroid/R$styleable;->TextView_drawableRight:I
-Landroid/R$styleable;->TextView_drawableStart:I
-Landroid/R$styleable;->TextView_drawableTop:I
-Landroid/R$styleable;->TextView_editable:I
-Landroid/R$styleable;->TextView_ellipsize:I
-Landroid/R$styleable;->TextView_ems:I
-Landroid/R$styleable;->TextView_enabled:I
-Landroid/R$styleable;->TextView_freezesText:I
-Landroid/R$styleable;->TextView_gravity:I
-Landroid/R$styleable;->TextView_height:I
-Landroid/R$styleable;->TextView_hint:I
-Landroid/R$styleable;->TextView_imeActionId:I
-Landroid/R$styleable;->TextView_imeActionLabel:I
-Landroid/R$styleable;->TextView_imeOptions:I
-Landroid/R$styleable;->TextView_includeFontPadding:I
-Landroid/R$styleable;->TextView_inputMethod:I
-Landroid/R$styleable;->TextView_inputType:I
-Landroid/R$styleable;->TextView_lines:I
-Landroid/R$styleable;->TextView_lineSpacingExtra:I
-Landroid/R$styleable;->TextView_lineSpacingMultiplier:I
-Landroid/R$styleable;->TextView_linksClickable:I
-Landroid/R$styleable;->TextView_marqueeRepeatLimit:I
-Landroid/R$styleable;->TextView_maxEms:I
-Landroid/R$styleable;->TextView_maxHeight:I
-Landroid/R$styleable;->TextView_maxLength:I
-Landroid/R$styleable;->TextView_maxLines:I
-Landroid/R$styleable;->TextView_maxWidth:I
-Landroid/R$styleable;->TextView_minEms:I
-Landroid/R$styleable;->TextView_minHeight:I
-Landroid/R$styleable;->TextView_minLines:I
-Landroid/R$styleable;->TextView_minWidth:I
-Landroid/R$styleable;->TextView_numeric:I
-Landroid/R$styleable;->TextView_password:I
-Landroid/R$styleable;->TextView_phoneNumber:I
-Landroid/R$styleable;->TextView_privateImeOptions:I
-Landroid/R$styleable;->TextView_scrollHorizontally:I
-Landroid/R$styleable;->TextView_selectAllOnFocus:I
-Landroid/R$styleable;->TextView_shadowColor:I
-Landroid/R$styleable;->TextView_shadowDx:I
-Landroid/R$styleable;->TextView_shadowDy:I
-Landroid/R$styleable;->TextView_shadowRadius:I
-Landroid/R$styleable;->TextView_singleLine:I
-Landroid/R$styleable;->TextView_text:I
-Landroid/R$styleable;->TextView_textAllCaps:I
-Landroid/R$styleable;->TextView_textAppearance:I
-Landroid/R$styleable;->TextView_textColor:I
-Landroid/R$styleable;->TextView_textColorHighlight:I
-Landroid/R$styleable;->TextView_textColorHint:I
-Landroid/R$styleable;->TextView_textColorLink:I
-Landroid/R$styleable;->TextView_textCursorDrawable:I
-Landroid/R$styleable;->TextView_textIsSelectable:I
-Landroid/R$styleable;->TextView_textScaleX:I
-Landroid/R$styleable;->TextView_textSelectHandle:I
-Landroid/R$styleable;->TextView_textSelectHandleLeft:I
-Landroid/R$styleable;->TextView_textSelectHandleRight:I
-Landroid/R$styleable;->TextView_textSize:I
-Landroid/R$styleable;->TextView_textStyle:I
-Landroid/R$styleable;->TextView_typeface:I
-Landroid/R$styleable;->TextView_width:I
-Landroid/R$styleable;->Theme:[I
-Landroid/R$styleable;->View:[I
-Landroid/R$styleable;->ViewDrawableStates:[I
-Landroid/R$styleable;->ViewGroup_Layout:[I
-Landroid/R$styleable;->ViewGroup_Layout_layout_height:I
-Landroid/R$styleable;->ViewGroup_Layout_layout_width:I
-Landroid/R$styleable;->ViewGroup_MarginLayout:[I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_height:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_margin:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginBottom:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginLeft:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginRight:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginTop:I
-Landroid/R$styleable;->ViewGroup_MarginLayout_layout_width:I
-Landroid/R$styleable;->View_alpha:I
-Landroid/R$styleable;->View_background:I
-Landroid/R$styleable;->View_clickable:I
-Landroid/R$styleable;->View_contentDescription:I
-Landroid/R$styleable;->View_drawingCacheQuality:I
-Landroid/R$styleable;->View_duplicateParentState:I
-Landroid/R$styleable;->View_fadingEdge:I
-Landroid/R$styleable;->View_filterTouchesWhenObscured:I
-Landroid/R$styleable;->View_fitsSystemWindows:I
-Landroid/R$styleable;->View_focusable:I
-Landroid/R$styleable;->View_focusableInTouchMode:I
-Landroid/R$styleable;->View_hapticFeedbackEnabled:I
-Landroid/R$styleable;->View_id:I
-Landroid/R$styleable;->View_isScrollContainer:I
-Landroid/R$styleable;->View_keepScreenOn:I
-Landroid/R$styleable;->View_longClickable:I
-Landroid/R$styleable;->View_minHeight:I
-Landroid/R$styleable;->View_minWidth:I
-Landroid/R$styleable;->View_nextFocusDown:I
-Landroid/R$styleable;->View_nextFocusLeft:I
-Landroid/R$styleable;->View_nextFocusRight:I
-Landroid/R$styleable;->View_nextFocusUp:I
-Landroid/R$styleable;->View_onClick:I
-Landroid/R$styleable;->View_overScrollMode:I
-Landroid/R$styleable;->View_padding:I
-Landroid/R$styleable;->View_paddingBottom:I
-Landroid/R$styleable;->View_paddingEnd:I
-Landroid/R$styleable;->View_paddingLeft:I
-Landroid/R$styleable;->View_paddingRight:I
-Landroid/R$styleable;->View_paddingStart:I
-Landroid/R$styleable;->View_paddingTop:I
-Landroid/R$styleable;->View_rotation:I
-Landroid/R$styleable;->View_rotationX:I
-Landroid/R$styleable;->View_rotationY:I
-Landroid/R$styleable;->View_saveEnabled:I
-Landroid/R$styleable;->View_scaleX:I
-Landroid/R$styleable;->View_scaleY:I
-Landroid/R$styleable;->View_scrollbarDefaultDelayBeforeFade:I
-Landroid/R$styleable;->View_scrollbarFadeDuration:I
-Landroid/R$styleable;->View_scrollbars:I
-Landroid/R$styleable;->View_scrollbarSize:I
-Landroid/R$styleable;->View_scrollbarStyle:I
-Landroid/R$styleable;->View_scrollbarThumbHorizontal:I
-Landroid/R$styleable;->View_scrollbarThumbVertical:I
-Landroid/R$styleable;->View_scrollbarTrackHorizontal:I
-Landroid/R$styleable;->View_scrollbarTrackVertical:I
-Landroid/R$styleable;->View_scrollX:I
-Landroid/R$styleable;->View_scrollY:I
-Landroid/R$styleable;->View_soundEffectsEnabled:I
-Landroid/R$styleable;->View_tag:I
-Landroid/R$styleable;->View_transformPivotX:I
-Landroid/R$styleable;->View_transformPivotY:I
-Landroid/R$styleable;->View_translationX:I
-Landroid/R$styleable;->View_translationY:I
-Landroid/R$styleable;->View_visibility:I
-Landroid/R$styleable;->Window:[I
-Landroid/R$styleable;->Window_windowBackground:I
-Landroid/R$styleable;->Window_windowFrame:I
Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
@@ -589,445 +325,6 @@ Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landr
Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
-Lcom/android/internal/R$anim;->fade_in:I
-Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
-Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
-Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I
-Lcom/android/internal/R$array;->config_sms_enabled_locking_shift_tables:I
-Lcom/android/internal/R$array;->config_sms_enabled_single_shift_tables:I
-Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I
-Lcom/android/internal/R$array;->config_tether_upstream_types:I
-Lcom/android/internal/R$array;->config_tether_usb_regexs:I
-Lcom/android/internal/R$array;->config_tether_wifi_regexs:I
-Lcom/android/internal/R$array;->maps_starting_lat_lng:I
-Lcom/android/internal/R$array;->maps_starting_zoom:I
-Lcom/android/internal/R$attr;->actionBarStyle:I
-Lcom/android/internal/R$attr;->buttonStyle:I
-Lcom/android/internal/R$attr;->description:I
-Lcom/android/internal/R$attr;->editTextStyle:I
-Lcom/android/internal/R$attr;->mapViewStyle:I
-Lcom/android/internal/R$attr;->popupWindowStyle:I
-Lcom/android/internal/R$attr;->state_above_anchor:I
-Lcom/android/internal/R$attr;->state_focused:I
-Lcom/android/internal/R$attr;->state_pressed:I
-Lcom/android/internal/R$attr;->state_selected:I
-Lcom/android/internal/R$attr;->switchStyle:I
-Lcom/android/internal/R$attr;->text:I
-Lcom/android/internal/R$attr;->title:I
-Lcom/android/internal/R$attr;->webViewStyle:I
-Lcom/android/internal/R$bool;-><init>()V
-Lcom/android/internal/R$bool;->config_automatic_brightness_available:I
-Lcom/android/internal/R$bool;->config_intrusiveNotificationLed:I
-Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I
-Lcom/android/internal/R$bool;->config_showNavigationBar:I
-Lcom/android/internal/R$dimen;-><init>()V
-Lcom/android/internal/R$dimen;->item_touch_helper_max_drag_scroll_per_frame:I
-Lcom/android/internal/R$dimen;->navigation_bar_height:I
-Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I
-Lcom/android/internal/R$dimen;->navigation_bar_width:I
-Lcom/android/internal/R$dimen;->status_bar_height:I
-Lcom/android/internal/R$dimen;->toast_y_offset:I
-Lcom/android/internal/R$drawable;->btn_check_off:I
-Lcom/android/internal/R$drawable;->compass_arrow:I
-Lcom/android/internal/R$drawable;->compass_base:I
-Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I
-Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I
-Lcom/android/internal/R$drawable;->loading_tile_android:I
-Lcom/android/internal/R$drawable;->maps_google_logo:I
-Lcom/android/internal/R$drawable;->no_tile_256:I
-Lcom/android/internal/R$drawable;->reticle:I
-Lcom/android/internal/R$drawable;->stat_sys_download:I
-Lcom/android/internal/R$fraction;->config_autoBrightnessAdjustmentMaxGamma:I
-Lcom/android/internal/R$id;->account_name:I
-Lcom/android/internal/R$id;->account_type:I
-Lcom/android/internal/R$id;->alertTitle:I
-Lcom/android/internal/R$id;->allow_button:I
-Lcom/android/internal/R$id;->amPm:I
-Lcom/android/internal/R$id;->authtoken_type:I
-Lcom/android/internal/R$id;->background:I
-Lcom/android/internal/R$id;->back_button:I
-Lcom/android/internal/R$id;->body:I
-Lcom/android/internal/R$id;->buttonPanel:I
-Lcom/android/internal/R$id;->camera:I
-Lcom/android/internal/R$id;->cancel:I
-Lcom/android/internal/R$id;->clip_children_set_tag:I
-Lcom/android/internal/R$id;->clip_children_tag:I
-Lcom/android/internal/R$id;->clip_to_padding_tag:I
-Lcom/android/internal/R$id;->closeButton:I
-Lcom/android/internal/R$id;->content:I
-Lcom/android/internal/R$id;->contentPanel:I
-Lcom/android/internal/R$id;->custom:I
-Lcom/android/internal/R$id;->customPanel:I
-Lcom/android/internal/R$id;->datePicker:I
-Lcom/android/internal/R$id;->day:I
-Lcom/android/internal/R$id;->deny_button:I
-Lcom/android/internal/R$id;->description:I
-Lcom/android/internal/R$id;->edit:I
-Lcom/android/internal/R$id;->edittext_container:I
-Lcom/android/internal/R$id;->find_next:I
-Lcom/android/internal/R$id;->find_prev:I
-Lcom/android/internal/R$id;->icon:I
-Lcom/android/internal/R$id;->keyboard:I
-Lcom/android/internal/R$id;->keyboardView:I
-Lcom/android/internal/R$id;->line1:I
-Lcom/android/internal/R$id;->list_item:I
-Lcom/android/internal/R$id;->matches:I
-Lcom/android/internal/R$id;->mediacontroller_progress:I
-Lcom/android/internal/R$id;->media_actions:I
-Lcom/android/internal/R$id;->message:I
-Lcom/android/internal/R$id;->minute:I
-Lcom/android/internal/R$id;->month:I
-Lcom/android/internal/R$id;->notification_header:I
-Lcom/android/internal/R$id;->ok:I
-Lcom/android/internal/R$id;->overlay:I
-Lcom/android/internal/R$id;->packages_list:I
-Lcom/android/internal/R$id;->package_label:I
-Lcom/android/internal/R$id;->parentPanel:I
-Lcom/android/internal/R$id;->pause:I
-Lcom/android/internal/R$id;->pending_intent_tag:I
-Lcom/android/internal/R$id;->progress:I
-Lcom/android/internal/R$id;->redo:I
-Lcom/android/internal/R$id;->remote_input_tag:I
-Lcom/android/internal/R$id;->right_icon:I
-Lcom/android/internal/R$id;->search_src_text:I
-Lcom/android/internal/R$id;->share:I
-Lcom/android/internal/R$id;->shortcut:I
-Lcom/android/internal/R$id;->status_bar_latest_event_content:I
-Lcom/android/internal/R$id;->tabcontent:I
-Lcom/android/internal/R$id;->tabs:I
-Lcom/android/internal/R$id;->text1:I
-Lcom/android/internal/R$id;->text2:I
-Lcom/android/internal/R$id;->text:I
-Lcom/android/internal/R$id;->time:I
-Lcom/android/internal/R$id;->timePicker:I
-Lcom/android/internal/R$id;->time_current:I
-Lcom/android/internal/R$id;->title:I
-Lcom/android/internal/R$id;->titleDivider:I
-Lcom/android/internal/R$id;->titleDividerTop:I
-Lcom/android/internal/R$id;->title_container:I
-Lcom/android/internal/R$id;->title_template:I
-Lcom/android/internal/R$id;->topPanel:I
-Lcom/android/internal/R$id;->up:I
-Lcom/android/internal/R$id;->year:I
-Lcom/android/internal/R$id;->zoomControls:I
-Lcom/android/internal/R$id;->zoomMagnify:I
-Lcom/android/internal/R$integer;->config_screenBrightnessDim:I
-Lcom/android/internal/R$integer;->config_screenBrightnessSettingMaximum:I
-Lcom/android/internal/R$integer;->config_screenBrightnessSettingMinimum:I
-Lcom/android/internal/R$integer;->config_toastDefaultGravity:I
-Lcom/android/internal/R$interpolator;->accelerate_cubic:I
-Lcom/android/internal/R$interpolator;->decelerate_cubic:I
-Lcom/android/internal/R$layout;->notification_template_material_base:I
-Lcom/android/internal/R$layout;->preference_header_item:I
-Lcom/android/internal/R$layout;->screen_title:I
-Lcom/android/internal/R$layout;->select_dialog:I
-Lcom/android/internal/R$layout;->select_dialog_multichoice:I
-Lcom/android/internal/R$layout;->select_dialog_singlechoice:I
-Lcom/android/internal/R$layout;->webview_find:I
-Lcom/android/internal/R$layout;->zoom_magnify:I
-Lcom/android/internal/R$plurals;->matches_found:I
-Lcom/android/internal/R$raw;->loaderror:I
-Lcom/android/internal/R$raw;->nodomain:I
-Lcom/android/internal/R$string;->byteShort:I
-Lcom/android/internal/R$string;->cancel:I
-Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I
-Lcom/android/internal/R$string;->gigabyteShort:I
-Lcom/android/internal/R$string;->kilobyteShort:I
-Lcom/android/internal/R$string;->map:I
-Lcom/android/internal/R$string;->megabyteShort:I
-Lcom/android/internal/R$string;->notification_title:I
-Lcom/android/internal/R$string;->no_matches:I
-Lcom/android/internal/R$string;->ok:I
-Lcom/android/internal/R$string;->petabyteShort:I
-Lcom/android/internal/R$string;->redo:I
-Lcom/android/internal/R$string;->share:I
-Lcom/android/internal/R$string;->terabyteShort:I
-Lcom/android/internal/R$string;->whichApplication:I
-Lcom/android/internal/R$style;->Animation_DropDownDown:I
-Lcom/android/internal/R$style;->Animation_DropDownUp:I
-Lcom/android/internal/R$style;->Animation_PopupWindow:I
-Lcom/android/internal/R$style;->Theme:I
-Lcom/android/internal/R$style;->Theme_Dialog_Alert:I
-Lcom/android/internal/R$style;->Theme_Holo_Light:I
-Lcom/android/internal/R$style;->Theme_Light:I
-Lcom/android/internal/R$styleable;-><init>()V
-Lcom/android/internal/R$styleable;->AbsListView:[I
-Lcom/android/internal/R$styleable;->AbsListView_cacheColorHint:I
-Lcom/android/internal/R$styleable;->AbsListView_choiceMode:I
-Lcom/android/internal/R$styleable;->AbsListView_drawSelectorOnTop:I
-Lcom/android/internal/R$styleable;->AbsListView_fastScrollAlwaysVisible:I
-Lcom/android/internal/R$styleable;->AbsListView_fastScrollEnabled:I
-Lcom/android/internal/R$styleable;->AbsListView_listSelector:I
-Lcom/android/internal/R$styleable;->AbsListView_scrollingCache:I
-Lcom/android/internal/R$styleable;->AbsListView_smoothScrollbar:I
-Lcom/android/internal/R$styleable;->AbsListView_stackFromBottom:I
-Lcom/android/internal/R$styleable;->AbsListView_textFilterEnabled:I
-Lcom/android/internal/R$styleable;->AbsListView_transcriptMode:I
-Lcom/android/internal/R$styleable;->AbsSpinner:[I
-Lcom/android/internal/R$styleable;->AccountAuthenticator:[I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_accountPreferences:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon:I
-Lcom/android/internal/R$styleable;->ActionMode:[I
-Lcom/android/internal/R$styleable;->AdapterViewAnimator:[I
-Lcom/android/internal/R$styleable;->AdapterViewFlipper:[I
-Lcom/android/internal/R$styleable;->AlertDialog:[I
-Lcom/android/internal/R$styleable;->AnalogClock:[I
-Lcom/android/internal/R$styleable;->AndroidManifest:[I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity:[I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_allowTaskReparenting:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_configChanges:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_description:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_excludeFromRecents:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_exported:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_hardwareAccelerated:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_icon:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_immersive:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_label:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_launchMode:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_logo:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_noHistory:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_screenOrientation:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_taskAffinity:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_theme:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_uiOptions:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_windowSoftInputMode:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I
-Lcom/android/internal/R$styleable;->AndroidManifestData:[I
-Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter:[I
-Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter_priority:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData:[I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_resource:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_value:I
-Lcom/android/internal/R$styleable;->AndroidManifestPackageVerifier:[I
-Lcom/android/internal/R$styleable;->AndroidManifestProvider:[I
-Lcom/android/internal/R$styleable;->AndroidManifestService:[I
-Lcom/android/internal/R$styleable;->AndroidManifestService_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_exported:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesLibrary:[I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I
-Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I
-Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I
-Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I
-Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I
-Lcom/android/internal/R$styleable;->AutoCompleteTextView:[I
-Lcom/android/internal/R$styleable;->CheckBoxPreference:[I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_disableDependentsState:I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOff:I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOn:I
-Lcom/android/internal/R$styleable;->CheckedTextView:[I
-Lcom/android/internal/R$styleable;->CheckedTextView_checked:I
-Lcom/android/internal/R$styleable;->CheckedTextView_checkMark:I
-Lcom/android/internal/R$styleable;->CompoundButton:[I
-Lcom/android/internal/R$styleable;->CompoundButton_button:I
-Lcom/android/internal/R$styleable;->CompoundButton_checked:I
-Lcom/android/internal/R$styleable;->ContactsDataKind:[I
-Lcom/android/internal/R$styleable;->DatePicker:[I
-Lcom/android/internal/R$styleable;->DialogPreference:[I
-Lcom/android/internal/R$styleable;->DialogPreference_dialogTitle:I
-Lcom/android/internal/R$styleable;->Dream:[I
-Lcom/android/internal/R$styleable;->EdgeEffect:[I
-Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I
-Lcom/android/internal/R$styleable;->FastScroll:[I
-Lcom/android/internal/R$styleable;->FrameLayout:[I
-Lcom/android/internal/R$styleable;->FrameLayout_Layout:[I
-Lcom/android/internal/R$styleable;->Gallery:[I
-Lcom/android/internal/R$styleable;->GridView:[I
-Lcom/android/internal/R$styleable;->IconMenuView:[I
-Lcom/android/internal/R$styleable;->ImageView:[I
-Lcom/android/internal/R$styleable;->ImageView_scaleType:I
-Lcom/android/internal/R$styleable;->ImageView_src:I
-Lcom/android/internal/R$styleable;->Keyboard:[I
-Lcom/android/internal/R$styleable;->KeyboardView:[I
-Lcom/android/internal/R$styleable;->Keyboard_Key:[I
-Lcom/android/internal/R$styleable;->Keyboard_Row:[I
-Lcom/android/internal/R$styleable;->ListPreference:[I
-Lcom/android/internal/R$styleable;->ListPreference_entries:I
-Lcom/android/internal/R$styleable;->ListView:[I
-Lcom/android/internal/R$styleable;->ListView_divider:I
-Lcom/android/internal/R$styleable;->ListView_dividerHeight:I
-Lcom/android/internal/R$styleable;->ListView_entries:I
-Lcom/android/internal/R$styleable;->ListView_footerDividersEnabled:I
-Lcom/android/internal/R$styleable;->ListView_headerDividersEnabled:I
-Lcom/android/internal/R$styleable;->ListView_overScrollFooter:I
-Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I
-Lcom/android/internal/R$styleable;->MapView:[I
-Lcom/android/internal/R$styleable;->MapView_apiKey:I
-Lcom/android/internal/R$styleable;->MenuGroup:[I
-Lcom/android/internal/R$styleable;->MenuItem:[I
-Lcom/android/internal/R$styleable;->NumberPicker:[I
-Lcom/android/internal/R$styleable;->PopupWindow:[I
-Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I
-Lcom/android/internal/R$styleable;->PopupWindow_popupBackground:I
-Lcom/android/internal/R$styleable;->Preference:[I
-Lcom/android/internal/R$styleable;->PreferenceGroup:[I
-Lcom/android/internal/R$styleable;->PreferenceGroup_orderingFromXml:I
-Lcom/android/internal/R$styleable;->Preference_defaultValue:I
-Lcom/android/internal/R$styleable;->Preference_dependency:I
-Lcom/android/internal/R$styleable;->Preference_enabled:I
-Lcom/android/internal/R$styleable;->Preference_fragment:I
-Lcom/android/internal/R$styleable;->Preference_icon:I
-Lcom/android/internal/R$styleable;->Preference_key:I
-Lcom/android/internal/R$styleable;->Preference_layout:I
-Lcom/android/internal/R$styleable;->Preference_order:I
-Lcom/android/internal/R$styleable;->Preference_persistent:I
-Lcom/android/internal/R$styleable;->Preference_selectable:I
-Lcom/android/internal/R$styleable;->Preference_shouldDisableView:I
-Lcom/android/internal/R$styleable;->Preference_summary:I
-Lcom/android/internal/R$styleable;->Preference_title:I
-Lcom/android/internal/R$styleable;->Preference_widgetLayout:I
-Lcom/android/internal/R$styleable;->ProgressBar:[I
-Lcom/android/internal/R$styleable;->QuickContactBadge:[I
-Lcom/android/internal/R$styleable;->RingtonePreference:[I
-Lcom/android/internal/R$styleable;->ScrollView:[I
-Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I
-Lcom/android/internal/R$styleable;->SelectionModeDrawables:[I
-Lcom/android/internal/R$styleable;->Switch:[I
-Lcom/android/internal/R$styleable;->SwitchPreference:[I
-Lcom/android/internal/R$styleable;->SyncAdapter:[I
-Lcom/android/internal/R$styleable;->SyncAdapter_accountType:I
-Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I
-Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I
-Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I
-Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I
-Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I
-Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I
-Lcom/android/internal/R$styleable;->TabWidget:[I
-Lcom/android/internal/R$styleable;->TextAppearance:[I
-Lcom/android/internal/R$styleable;->TextAppearance_fontFamily:I
-Lcom/android/internal/R$styleable;->TextAppearance_textAllCaps:I
-Lcom/android/internal/R$styleable;->TextAppearance_textColor:I
-Lcom/android/internal/R$styleable;->TextAppearance_textColorHighlight:I
-Lcom/android/internal/R$styleable;->TextAppearance_textColorHint:I
-Lcom/android/internal/R$styleable;->TextAppearance_textColorLink:I
-Lcom/android/internal/R$styleable;->TextAppearance_textSize:I
-Lcom/android/internal/R$styleable;->TextAppearance_textStyle:I
-Lcom/android/internal/R$styleable;->TextAppearance_typeface:I
-Lcom/android/internal/R$styleable;->TextClock:[I
-Lcom/android/internal/R$styleable;->TextView:[I
-Lcom/android/internal/R$styleable;->TextViewAppearance:[I
-Lcom/android/internal/R$styleable;->TextViewAppearance_textAppearance:I
-Lcom/android/internal/R$styleable;->TextView_autoLink:I
-Lcom/android/internal/R$styleable;->TextView_autoText:I
-Lcom/android/internal/R$styleable;->TextView_bufferType:I
-Lcom/android/internal/R$styleable;->TextView_capitalize:I
-Lcom/android/internal/R$styleable;->TextView_cursorVisible:I
-Lcom/android/internal/R$styleable;->TextView_digits:I
-Lcom/android/internal/R$styleable;->TextView_drawableBottom:I
-Lcom/android/internal/R$styleable;->TextView_drawableEnd:I
-Lcom/android/internal/R$styleable;->TextView_drawableLeft:I
-Lcom/android/internal/R$styleable;->TextView_drawablePadding:I
-Lcom/android/internal/R$styleable;->TextView_drawableRight:I
-Lcom/android/internal/R$styleable;->TextView_drawableStart:I
-Lcom/android/internal/R$styleable;->TextView_drawableTop:I
-Lcom/android/internal/R$styleable;->TextView_editable:I
-Lcom/android/internal/R$styleable;->TextView_editorExtras:I
-Lcom/android/internal/R$styleable;->TextView_ellipsize:I
-Lcom/android/internal/R$styleable;->TextView_ems:I
-Lcom/android/internal/R$styleable;->TextView_enabled:I
-Lcom/android/internal/R$styleable;->TextView_freezesText:I
-Lcom/android/internal/R$styleable;->TextView_gravity:I
-Lcom/android/internal/R$styleable;->TextView_height:I
-Lcom/android/internal/R$styleable;->TextView_hint:I
-Lcom/android/internal/R$styleable;->TextView_imeActionId:I
-Lcom/android/internal/R$styleable;->TextView_imeActionLabel:I
-Lcom/android/internal/R$styleable;->TextView_imeOptions:I
-Lcom/android/internal/R$styleable;->TextView_includeFontPadding:I
-Lcom/android/internal/R$styleable;->TextView_inputMethod:I
-Lcom/android/internal/R$styleable;->TextView_inputType:I
-Lcom/android/internal/R$styleable;->TextView_lines:I
-Lcom/android/internal/R$styleable;->TextView_lineSpacingExtra:I
-Lcom/android/internal/R$styleable;->TextView_lineSpacingMultiplier:I
-Lcom/android/internal/R$styleable;->TextView_linksClickable:I
-Lcom/android/internal/R$styleable;->TextView_marqueeRepeatLimit:I
-Lcom/android/internal/R$styleable;->TextView_maxEms:I
-Lcom/android/internal/R$styleable;->TextView_maxHeight:I
-Lcom/android/internal/R$styleable;->TextView_maxLength:I
-Lcom/android/internal/R$styleable;->TextView_maxLines:I
-Lcom/android/internal/R$styleable;->TextView_maxWidth:I
-Lcom/android/internal/R$styleable;->TextView_minEms:I
-Lcom/android/internal/R$styleable;->TextView_minHeight:I
-Lcom/android/internal/R$styleable;->TextView_minLines:I
-Lcom/android/internal/R$styleable;->TextView_minWidth:I
-Lcom/android/internal/R$styleable;->TextView_numeric:I
-Lcom/android/internal/R$styleable;->TextView_password:I
-Lcom/android/internal/R$styleable;->TextView_phoneNumber:I
-Lcom/android/internal/R$styleable;->TextView_privateImeOptions:I
-Lcom/android/internal/R$styleable;->TextView_scrollHorizontally:I
-Lcom/android/internal/R$styleable;->TextView_selectAllOnFocus:I
-Lcom/android/internal/R$styleable;->TextView_shadowColor:I
-Lcom/android/internal/R$styleable;->TextView_shadowDx:I
-Lcom/android/internal/R$styleable;->TextView_shadowDy:I
-Lcom/android/internal/R$styleable;->TextView_shadowRadius:I
-Lcom/android/internal/R$styleable;->TextView_singleLine:I
-Lcom/android/internal/R$styleable;->TextView_text:I
-Lcom/android/internal/R$styleable;->TextView_textAllCaps:I
-Lcom/android/internal/R$styleable;->TextView_textAppearance:I
-Lcom/android/internal/R$styleable;->TextView_textColor:I
-Lcom/android/internal/R$styleable;->TextView_textColorHighlight:I
-Lcom/android/internal/R$styleable;->TextView_textColorHint:I
-Lcom/android/internal/R$styleable;->TextView_textColorLink:I
-Lcom/android/internal/R$styleable;->TextView_textCursorDrawable:I
-Lcom/android/internal/R$styleable;->TextView_textEditSuggestionItemLayout:I
-Lcom/android/internal/R$styleable;->TextView_textIsSelectable:I
-Lcom/android/internal/R$styleable;->TextView_textScaleX:I
-Lcom/android/internal/R$styleable;->TextView_textSelectHandle:I
-Lcom/android/internal/R$styleable;->TextView_textSelectHandleLeft:I
-Lcom/android/internal/R$styleable;->TextView_textSelectHandleRight:I
-Lcom/android/internal/R$styleable;->TextView_textSize:I
-Lcom/android/internal/R$styleable;->TextView_textStyle:I
-Lcom/android/internal/R$styleable;->TextView_typeface:I
-Lcom/android/internal/R$styleable;->TextView_width:I
-Lcom/android/internal/R$styleable;->Theme:[I
-Lcom/android/internal/R$styleable;->TwoLineListItem:[I
-Lcom/android/internal/R$styleable;->View:[I
-Lcom/android/internal/R$styleable;->ViewAnimator:[I
-Lcom/android/internal/R$styleable;->ViewFlipper:[I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I
-Lcom/android/internal/R$styleable;->ViewStub:[I
-Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I
-Lcom/android/internal/R$styleable;->ViewStub_layout:I
-Lcom/android/internal/R$styleable;->View_background:I
-Lcom/android/internal/R$styleable;->View_clickable:I
-Lcom/android/internal/R$styleable;->View_focusable:I
-Lcom/android/internal/R$styleable;->View_id:I
-Lcom/android/internal/R$styleable;->View_longClickable:I
-Lcom/android/internal/R$styleable;->WallpaperPreviewInfo:[I
-Lcom/android/internal/R$styleable;->Window:[I
-Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
-Lcom/android/internal/R$styleable;->Window_windowBackground:I
-Lcom/android/internal/R$styleable;->Window_windowFullscreen:I
-Lcom/android/internal/R$styleable;->Window_windowIsFloating:I
-Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I
-Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I
-Lcom/android/internal/R$xml;->power_profile:I
Lcom/android/internal/statusbar/IStatusBar$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBar;
Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V
Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index e738b19f420a..61c5dac03da6 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -22,6 +22,8 @@ import android.accessibilityservice.AccessibilityButtonController.AccessibilityB
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -32,8 +34,10 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.hardware.fingerprint.FingerprintManager;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -43,6 +47,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
+import com.android.internal.compat.IPlatformCompat;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -299,6 +304,11 @@ public class AccessibilityServiceInfo implements Parcelable {
/**
* This flag indicates to the system that the accessibility service requests that an
* accessibility button be shown within the system's navigation area, if available.
+ * <p>
+ * <strong>Note:</strong> For accessibility services targeting APIs greater than
+ * {@link Build.VERSION_CODES#Q API 29}, this flag must be specified in the
+ * accessibility service metadata file. Otherwise, it will be ignored.
+ * </p>
*/
public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
@@ -422,6 +432,12 @@ public class AccessibilityServiceInfo implements Parcelable {
* <p>
* <strong>Can be dynamically set at runtime.</strong>
* </p>
+ * <p>
+ * <strong>Note:</strong> Accessibility services with targetSdkVersion greater than
+ * {@link Build.VERSION_CODES#Q API 29} cannot dynamically set the
+ * {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} at runtime. It must be specified in the
+ * accessibility service metadata file.
+ * </p>
* @see #DEFAULT
* @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
* @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
@@ -497,6 +513,15 @@ public class AccessibilityServiceInfo implements Parcelable {
private String mNonLocalizedDescription;
/**
+ * For accessibility services targeting APIs greater than {@link Build.VERSION_CODES#Q API 29},
+ * {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} must be specified in the accessibility service
+ * metadata file. Otherwise, it will be ignored.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
+ private static final long REQUEST_ACCESSIBILITY_BUTTON_CHANGE = 136293963L;
+
+ /**
* Creates a new instance.
*/
public AccessibilityServiceInfo() {
@@ -623,13 +648,23 @@ public class AccessibilityServiceInfo implements Parcelable {
}
/**
- * Updates the properties that an AccessibilitySerivice can change dynamically.
+ * Updates the properties that an AccessibilityService can change dynamically.
+ * <p>
+ * Note: A11y services targeting APIs > Q, it cannot update flagRequestAccessibilityButton
+ * dynamically.
+ * </p>
*
+ * @param platformCompat The platform compat service to check the compatibility change.
* @param other The info from which to update the properties.
*
* @hide
*/
- public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) {
+ public void updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat,
+ AccessibilityServiceInfo other) {
+ if (isRequestAccessibilityButtonChangeEnabled(platformCompat)) {
+ other.flags &= ~FLAG_REQUEST_ACCESSIBILITY_BUTTON;
+ other.flags |= (flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON);
+ }
eventTypes = other.eventTypes;
packageNames = other.packageNames;
feedbackType = other.feedbackType;
@@ -639,6 +674,21 @@ public class AccessibilityServiceInfo implements Parcelable {
flags = other.flags;
}
+ private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) {
+ if (mResolveInfo == null) {
+ return true;
+ }
+ try {
+ if (platformCompat != null) {
+ return platformCompat.isChangeEnabledByPackageName(
+ REQUEST_ACCESSIBILITY_BUTTON_CHANGE, mResolveInfo.serviceInfo.packageName,
+ mResolveInfo.serviceInfo.applicationInfo.uid);
+ }
+ } catch (RemoteException ignore) {
+ }
+ return mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.Q;
+ }
+
/**
* @hide
*/
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/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index ac8b604ad103..9aca22360fd8 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -44,6 +44,8 @@ interface INotificationManager
void cancelAllNotifications(String pkg, int userId);
void clearData(String pkg, int uid, boolean fromApp);
+ // TODO: Replace parameter (ITransientNotification callback) with (CharSequence text)
+ void enqueueTextToast(String pkg, ITransientNotification callback, int duration, int displayId);
@UnsupportedAppUsage
void enqueueToast(String pkg, ITransientNotification callback, int duration, int displayId);
@UnsupportedAppUsage
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index f2c9f615c03f..f5809ba627ff 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();
@@ -62,4 +68,9 @@ interface IUiModeManager {
* Tells if Night mode is locked or not.
*/
boolean isNightModeLocked();
+
+ /**
+ * @hide
+ */
+ boolean setNightModeActivated(boolean active);
}
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 92bfee24d402..38ae5da0d815 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -517,7 +517,7 @@ public final class StatsManager {
}
}
- private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub {
+ private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub {
public final int mAtomId;
public final StatsPullAtomCallback mCallback;
public final Executor mExecutor;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 69c174a47127..d0ba879bd10e 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -657,7 +657,7 @@ public 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..d8c030d7aacf 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();
}
@@ -317,4 +473,18 @@ public class UiModeManager {
}
return true;
}
+
+ /**
+ * @hide*
+ */
+ public boolean setNightModeActivated(boolean active) {
+ if (mService != null) {
+ try {
+ return mService.setNightModeActivated(active);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
}
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/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 19f42b6a4c9e..0be3eca8239e 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1095,24 +1095,6 @@ public final class BluetoothDevice implements Parcelable {
}
/**
- * Get the Bluetooth alias of the remote device.
- * If Alias is null, get the Bluetooth name instead.
- *
- * @return the Bluetooth alias, or null if no alias or there was a problem
- * @hide
- * @see #getAlias()
- * @see #getName()
- */
- @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.")
- public String getAliasName() {
- String name = getAlias();
- if (name == null) {
- name = getName();
- }
- return name;
- }
-
- /**
* Get the most recent identified battery level of this Bluetooth device
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index dabe0fdac39a..f5aa01458481 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -324,4 +324,54 @@ public interface BluetoothProfile {
return "STATE_UNKNOWN";
}
}
+
+ /**
+ * Convert an integer value of profile ID into human readable string
+ *
+ * @param profile profile ID
+ * @return profile name as String, UNKOWN_PROFILE if the profile ID is not defined.
+ * @hide
+ */
+ static String getProfileName(int profile) {
+ switch(profile) {
+ case HEADSET:
+ return "HEADSET";
+ case A2DP:
+ return "A2DP";
+ case HID_HOST:
+ return "HID_HOST";
+ case PAN:
+ return "PAN";
+ case PBAP:
+ return "PBAP";
+ case GATT:
+ return "GATT";
+ case GATT_SERVER:
+ return "GATT_SERVER";
+ case MAP:
+ return "MAP";
+ case SAP:
+ return "SAP";
+ case A2DP_SINK:
+ return "A2DP_SINK";
+ case AVRCP_CONTROLLER:
+ return "AVRCP_CONTROLLER";
+ case AVRCP:
+ return "AVRCP";
+ case HEADSET_CLIENT:
+ return "HEADSET_CLIENT";
+ case PBAP_CLIENT:
+ return "PBAP_CLIENT";
+ case MAP_CLIENT:
+ return "MAP_CLIENT";
+ case HID_DEVICE:
+ return "HID_DEVICE";
+ case OPP:
+ return "OPP";
+ case HEARING_AID:
+ return "HEARING_AID";
+ default:
+ return "UNKNOWN_PROFILE";
+ }
+ }
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index b04f7810ed45..e44d6ae40356 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -672,7 +672,6 @@ public class ContextWrapper extends Context {
/** @hide */
@Override
@Nullable
- @SystemApi
public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
@NonNull IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler) {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 070e282a0eb2..2d9ca67a236d 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -38,18 +38,13 @@ import android.util.SparseArray;
import android.util.TypedValue;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
-import libcore.io.IoUtils;
-
-import java.io.BufferedReader;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.channels.FileLock;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
@@ -176,7 +171,7 @@ public final class AssetManager implements AutoCloseable {
public AssetManager() {
final ApkAssets[] assets;
synchronized (sSync) {
- createSystemAssetsInZygoteLocked();
+ createSystemAssetsInZygoteLocked(false, FRAMEWORK_APK_PATH);
assets = sSystemApkAssets;
}
@@ -205,17 +200,19 @@ public final class AssetManager implements AutoCloseable {
/**
* This must be called from Zygote so that system assets are shared by all applications.
+ * @hide
*/
@GuardedBy("sSync")
- private static void createSystemAssetsInZygoteLocked() {
- if (sSystem != null) {
+ @VisibleForTesting
+ public static void createSystemAssetsInZygoteLocked(boolean reinitialize,
+ String frameworkPath) {
+ if (sSystem != null || reinitialize) {
return;
}
-
try {
final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
- apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
+ apkAssets.add(ApkAssets.loadFromPath(frameworkPath, true /*system*/));
final String[] systemIdmapPaths = nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
if (systemIdmapPaths != null) {
for (String idmapPath : systemIdmapPaths) {
@@ -236,42 +233,6 @@ public final class AssetManager implements AutoCloseable {
}
/**
- * Loads the static runtime overlays declared in /data/resource-cache/overlays.list.
- * Throws an exception if the file is corrupt or if loading the APKs referenced by the file
- * fails. Returns quietly if the overlays.list file doesn't exist.
- * @param outApkAssets The list to fill with the loaded ApkAssets.
- */
- private static void loadStaticRuntimeOverlays(ArrayList<ApkAssets> outApkAssets)
- throws IOException {
- final FileInputStream fis;
- try {
- fis = new FileInputStream("/data/resource-cache/overlays.list");
- } catch (FileNotFoundException e) {
- // We might not have any overlays, this is fine. We catch here since ApkAssets
- // loading can also fail with the same exception, which we would want to propagate.
- Log.i(TAG, "no overlays.list file found");
- return;
- }
-
- try {
- // Acquire a lock so that any idmap scanning doesn't impact the current set.
- // The order of this try-with-resources block matters. We must release the lock, and
- // then close the file streams when exiting the block.
- try (final BufferedReader br = new BufferedReader(new InputStreamReader(fis));
- final FileLock flock = fis.getChannel().lock(0, Long.MAX_VALUE, true /*shared*/)) {
- for (String line; (line = br.readLine()) != null; ) {
- final String idmapPath = line.split(" ")[1];
- outApkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
- }
- }
- } finally {
- // When BufferedReader is closed above, FileInputStream is closed as well. But let's be
- // paranoid.
- IoUtils.closeQuietly(fis);
- }
- }
-
- /**
* Return a global shared asset manager that provides access to only
* system assets (no application assets).
* @hide
@@ -279,7 +240,7 @@ public final class AssetManager implements AutoCloseable {
@UnsupportedAppUsage
public static AssetManager getSystem() {
synchronized (sSync) {
- createSystemAssetsInZygoteLocked();
+ createSystemAssetsInZygoteLocked(false, FRAMEWORK_APK_PATH);
return sSystem;
}
}
@@ -1645,7 +1606,6 @@ public final class AssetManager implements AutoCloseable {
private static native long nativeAssetGetLength(long assetPtr);
private static native long nativeAssetGetRemainingLength(long assetPtr);
- private static native void nativeVerifySystemIdmaps();
private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
private static native @Nullable Map nativeGetOverlayableMap(long ptr,
@NonNull String packageName);
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 45a9cf5ab869..928df3c4ff97 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/AndroidDeviceConfig.java b/core/java/android/provider/AndroidDeviceConfig.java
new file mode 100644
index 000000000000..424632fca0a4
--- /dev/null
+++ b/core/java/android/provider/AndroidDeviceConfig.java
@@ -0,0 +1,48 @@
+/*
+ * 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.provider;
+
+import android.annotation.TestApi;
+
+/**
+ * Interface for accessing keys belonging to {@link DeviceConfig#NAMESPACE_ANDROID}.
+ * @hide
+ */
+@TestApi
+public interface AndroidDeviceConfig {
+
+ /**
+ * Key for accessing the system gesture exclusion limit (an integer in dp).
+ *
+ * <p>Note: On Devices running Q, this key is in the "android:window_manager" namespace.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_ANDROID
+ */
+ String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+
+ /**
+ * Key for controlling whether system gestures are implicitly excluded by windows requesting
+ * sticky immersive mode from apps that are targeting an SDK prior to Q.
+ *
+ * <p>Note: On Devices running Q, this key is in the "android:window_manager" namespace.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_ANDROID
+ */
+ String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
+ "system_gestures_excluded_by_pre_q_sticky_immersive";
+
+}
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index dd2ea81d747b..7995f2285482 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -16,6 +16,8 @@
package android.provider;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.WorkerThread;
import android.content.Context;
import android.net.Uri;
@@ -153,7 +155,12 @@ public class BlockedNumberContract {
/** The authority for the blocked number provider */
public static final String AUTHORITY = "com.android.blockednumber";
- /** A content:// style uri to the authority for the blocked number provider */
+ /**
+ * A content:// style uri to the authority for the blocked number provider
+ * @hide
+ */
+ @NonNull
+ @SystemApi
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
private static final String LOG_TAG = BlockedNumberContract.class.getSimpleName();
@@ -239,6 +246,7 @@ public class BlockedNumberContract {
* blocked.
* @hide
*/
+ @SystemApi
public static final int STATUS_NOT_BLOCKED = 0;
/**
@@ -246,6 +254,7 @@ public class BlockedNumberContract {
* because it is in the list of blocked numbers maintained by the provider.
* @hide
*/
+ @SystemApi
public static final int STATUS_BLOCKED_IN_LIST = 1;
/**
@@ -253,6 +262,7 @@ public class BlockedNumberContract {
* because it is from a restricted number.
* @hide
*/
+ @SystemApi
public static final int STATUS_BLOCKED_RESTRICTED = 2;
/**
@@ -260,6 +270,7 @@ public class BlockedNumberContract {
* because it is from an unknown number.
* @hide
*/
+ @SystemApi
public static final int STATUS_BLOCKED_UNKNOWN_NUMBER = 3;
/**
@@ -267,6 +278,7 @@ public class BlockedNumberContract {
* because it is from a pay phone.
* @hide
*/
+ @SystemApi
public static final int STATUS_BLOCKED_PAYPHONE = 4;
/**
@@ -274,12 +286,14 @@ public class BlockedNumberContract {
* because it is from a number not in the users contacts.
* @hide
*/
+ @SystemApi
public static final int STATUS_BLOCKED_NOT_IN_CONTACTS = 5;
/**
* Integer reason indicating whether a call was blocked, and if so why.
* @hide
*/
+ @SystemApi
public static final String RES_BLOCK_STATUS = "block_status";
/** @hide */
@@ -290,6 +304,31 @@ public class BlockedNumberContract {
"can_current_user_block_numbers";
/** @hide */
+ @SystemApi
+ public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
+
+ /** @hide */
+ public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression";
+
+ /** @hide */
+ @SystemApi
+ public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
+
+ /** @hide */
+ public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
+ "get_block_suppression_status";
+
+ /** @hide */
+ public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
+ "should_show_emergency_call_notification";
+
+ /** @hide */
+ public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
+
+ /** @hide */
+ public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
+
+ /** @hide */
public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
/** @hide */
@@ -406,26 +445,11 @@ public class BlockedNumberContract {
public static final String ACTION_BLOCK_SUPPRESSION_STATE_CHANGED =
"android.provider.action.BLOCK_SUPPRESSION_STATE_CHANGED";
- public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
-
- public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression";
-
- public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
-
- public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
- "get_block_suppression_status";
-
- public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
- "should_show_emergency_call_notification";
-
public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";
public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP =
"blocking_suppressed_until_timestamp";
- public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
- public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
-
/* Preference key of block numbers not in contacts setting. */
public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED =
"block_numbers_not_in_contacts_setting";
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 2cb0750a3346..30db6382fcd6 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;
/**
@@ -613,7 +611,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"
@@ -648,7 +646,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"
@@ -689,7 +687,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"
@@ -1051,22 +1049,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/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 0401d7fb8d5d..1d7e33806e0c 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -314,13 +314,22 @@ public final class DeviceConfig {
public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
/**
- * Namespace for window manager related features. The names to access the properties in this
- * namespace should be defined in {@link WindowManager}.
+ * Namespace for android related features, i.e. for flags that affect not just a single
+ * component, but the entire system.
+ *
+ * The keys for this namespace are defined in {@link AndroidDeviceConfig}.
*
* @hide
*/
@TestApi
- public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
+ public static final String NAMESPACE_ANDROID = "android";
+
+ /**
+ * Namespace for window manager related features.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_WINDOW_MANAGER = "window_manager";
/**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
@@ -348,48 +357,6 @@ public final class DeviceConfig {
@TestApi
public static final String NAMESPACE_PERMISSIONS = "permissions";
- /**
- * Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
- * @hide
- */
- @TestApi
- public interface WindowManager {
-
- /**
- * Key for accessing the system gesture exclusion limit (an integer in dp).
- *
- * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
- * @hide
- */
- @TestApi
- String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
-
- /**
- * Key for controlling whether system gestures are implicitly excluded by windows requesting
- * sticky immersive mode from apps that are targeting an SDK prior to Q.
- *
- * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
- * @hide
- */
- @TestApi
- String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
- "system_gestures_excluded_by_pre_q_sticky_immersive";
-
- /**
- * The minimum duration between gesture exclusion logging for a given window in
- * milliseconds.
- *
- * Events that happen in-between will be silently dropped.
- *
- * A non-positive value disables logging.
- *
- * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
- * @hide
- */
- String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
- "system_gesture_exclusion_log_debounce_millis";
- }
-
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index a0800910d1b3..f66a679ad87d 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -16,7 +16,10 @@
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;
@@ -225,14 +228,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
}
@@ -594,9 +616,9 @@ public class TelephonyRegistryManager {
* @hide
*/
public void notifyPreciseCallState(int subId, int slotIndex,
- @PreciseCallStates int ringCallPreciseState,
- @PreciseCallStates int foregroundCallPreciseState,
- @PreciseCallStates int backgroundCallPreciseState) {
+ @PreciseCallStates int ringCallPreciseState,
+ @PreciseCallStates int foregroundCallPreciseState,
+ @PreciseCallStates int backgroundCallPreciseState) {
try {
sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState,
foregroundCallPreciseState, backgroundCallPreciseState);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 12a55c74bd3e..7e0974033fa7 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -55,7 +55,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
DEFAULT_FLAGS.put("settings_skip_direction_mutable", "true");
DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "false");
- DEFAULT_FLAGS.put("settings_work_profile", "false");
+ DEFAULT_FLAGS.put("settings_work_profile", "true");
DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false");
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 27402a463d4f..187ab46b2e08 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2584,8 +2584,7 @@ public class Editor {
* @return True when the TextView isFocused and has a valid zero-length selection (cursor).
*/
private boolean shouldBlink() {
- if (!isCursorVisible() || !mTextView.isFocused() ||
- !mTextView.isVisibleToUser()) return false;
+ if (!isCursorVisible() || !mTextView.isFocused()) return false;
final int start = mTextView.getSelectionStart();
if (start < 0) return false;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index d58d858c3b8a..5cc0e0e5de25 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -66,6 +66,7 @@ import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;
+import java.text.NumberFormat;
import java.util.ArrayList;
/**
@@ -241,6 +242,8 @@ public class ProgressBar extends View {
private boolean mAggregatedIsVisible;
+ private CharSequence mCustomStateDescription = null;
+
private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
/**
@@ -1551,9 +1554,54 @@ public class ProgressBar extends View {
}
}
+ private float getPercent(int progress) {
+ final float maxProgress = getMax();
+ final float minProgress = getMin();
+ final float currentProgress = progress;
+ final float diffProgress = maxProgress - minProgress;
+ if (diffProgress <= 0.0f) {
+ return 0.0f;
+ }
+ final float percent = (currentProgress - minProgress) / diffProgress;
+ return Math.max(0.0f, Math.min(1.0f, percent));
+ }
+
+ /**
+ * Default percentage format of the state description based on progress, for example,
+ * "50 percent".
+ *
+ * @param progress the progress value, between {@link #getMin()} and {@link #getMax()}
+ * @return state description based on progress
+ */
+ private CharSequence formatStateDescription(int progress) {
+ return NumberFormat.getPercentInstance(mContext.getResources().getConfiguration().locale)
+ .format(getPercent(progress));
+ }
+
+ /**
+ * This function is called when an instance or subclass sets the state description. Once this
+ * is called and the argument is not null, the app developer will be responsible for updating
+ * state description when progress changes and the default state description will not be used.
+ * App developers can restore the default behavior by setting the argument to null. If set
+ * progress is called first and then setStateDescription is called, two state change events
+ * will be merged by event throttling and we can still get the correct state description.
+ *
+ * @param stateDescription The state description.
+ */
+ @Override
+ public void setStateDescription(@Nullable CharSequence stateDescription) {
+ mCustomStateDescription = stateDescription;
+ if (stateDescription == null) {
+ super.setStateDescription(formatStateDescription(mProgress));
+ } else {
+ super.setStateDescription(stateDescription);
+ }
+ }
+
void onProgressRefresh(float scale, boolean fromUser, int progress) {
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()
+ && mCustomStateDescription == null) {
+ super.setStateDescription(formatStateDescription(mProgress));
}
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index d037337d4546..bdc2f9af2775 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -100,6 +100,8 @@ public class Toast {
@UnsupportedAppUsage
int mDuration;
View mNextView;
+ // TODO(b/128611929): Remove this and check for null view when toast creation is in the system
+ boolean mIsCustomToast = false;
/**
* Construct an empty Toast object. You must call {@link #setView} before you
@@ -140,7 +142,11 @@ public class Toast {
final int displayId = mContext.getDisplayId();
try {
- service.enqueueToast(pkg, tn, mDuration, displayId);
+ if (mIsCustomToast) {
+ service.enqueueToast(pkg, tn, mDuration, displayId);
+ } else {
+ service.enqueueTextToast(pkg, tn, mDuration, displayId);
+ }
} catch (RemoteException e) {
// Empty
}
@@ -160,6 +166,7 @@ public class Toast {
* @see #getView
*/
public void setView(View view) {
+ mIsCustomToast = true;
mNextView = view;
}
@@ -168,6 +175,7 @@ public class Toast {
* @see #setView
*/
public View getView() {
+ mIsCustomToast = true;
return mNextView;
}
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 045a6800bb13..7dcb12c9e72b 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -171,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/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index 7a17253ffd35..b6d2dedc1bfd 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -30,10 +30,13 @@ import com.android.internal.util.function.OctConsumer;
import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuadPredicate;
import com.android.internal.util.function.QuintConsumer;
import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.QuintPredicate;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.TriPredicate;
import com.android.internal.util.function.UndecConsumer;
import com.android.internal.util.function.UndecFunction;
@@ -59,7 +62,8 @@ abstract class OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> implements
HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
NonaConsumer<A, B, C, D, E, F, G, H, I>, DecConsumer<A, B, C, D, E, F, G, H, I, J>,
UndecConsumer<A, B, C, D, E, F, G, H, I, J, K>,
- PooledPredicate<A>, BiPredicate<A, B>, PooledSupplier<R>, PooledRunnable, ThrowingRunnable,
+ PooledPredicate<A>, BiPredicate<A, B>, TriPredicate<A, B, C>, QuadPredicate<A, B, C, D>,
+ QuintPredicate<A, B, C, D, E>, PooledSupplier<R>, PooledRunnable, ThrowingRunnable,
ThrowingSupplier<R>, PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
@@ -99,6 +103,21 @@ abstract class OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> implements
}
@Override
+ public boolean test(A o, B o2, C o3, D o4, E o5) {
+ return (Boolean) invoke(o, o2, o3, o4, o5, null, null, null, null, null, null);
+ }
+
+ @Override
+ public boolean test(A o, B o2, C o3, D o4) {
+ return (Boolean) invoke(o, o2, o3, o4, null, null, null, null, null, null, null);
+ }
+
+ @Override
+ public boolean test(A o, B o2, C o3) {
+ return (Boolean) invoke(o, o2, o3, null, null, null, null, null, null, null, null);
+ }
+
+ @Override
public boolean test(A o, B o2) {
return (Boolean) invoke(o, o2, null, null, null, null, null, null, null, null, null);
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index b9bf9337c3d6..d32ff060a8d7 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -33,10 +33,13 @@ import com.android.internal.util.function.OctConsumer;
import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuadPredicate;
import com.android.internal.util.function.QuintConsumer;
import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.QuintPredicate;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.TriPredicate;
import com.android.internal.util.function.UndecConsumer;
import com.android.internal.util.function.UndecFunction;
import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType;
@@ -346,6 +349,66 @@ public interface PooledLambda {
}
/**
+ * {@link PooledPredicate} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @return a {@link PooledPredicate}, equivalent to lambda:
+ * {@code (arg1) -> function(arg1, arg2, arg3) }
+ */
+ static <A, B, C> PooledPredicate<A> obtainPredicate(
+ TriPredicate<? super A, ? super B, ? super C> function,
+ ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, null, null, null, null, null,
+ null, null, null);
+ }
+
+ /**
+ * {@link PooledPredicate} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @return a {@link PooledPredicate}, equivalent to lambda:
+ * {@code (arg1) -> function(arg1, arg2, arg3, arg4) }
+ */
+ static <A, B, C, D> PooledPredicate<A> obtainPredicate(
+ QuadPredicate<? super A, ? super B, ? super C, ? super D> function,
+ ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
+ null, null, null);
+ }
+
+ /**
+ * {@link PooledPredicate} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @return a {@link PooledPredicate}, equivalent to lambda:
+ * {@code (arg1) -> function(arg1, arg2, arg3, arg4, arg5) }
+ */
+ static <A, B, C, D, E> PooledPredicate<A> obtainPredicate(
+ QuintPredicate<? super A, ? super B, ? super C, ? super D, ? super E> function,
+ ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4, E arg5) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null, null, null);
+ }
+
+ /**
* {@link PooledFunction} factory
*
* @param function non-capturing lambda(typically an unbounded method reference)
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4f7f18e1bf04..32d62fe2cdba 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -622,6 +622,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];
@@ -911,6 +913,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/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 5c4dc2335822..ff596b440867 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -121,107 +121,6 @@ constexpr inline static ApkAssetsCookie JavaCookieToApkAssetsCookie(jint cookie)
return cookie > 0 ? static_cast<ApkAssetsCookie>(cookie - 1) : kInvalidCookie;
}
-// This is called by zygote (running as user root) as part of preloadResources.
-static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
- switch (pid_t pid = fork()) {
- case -1:
- PLOG(ERROR) << "failed to fork for idmap";
- break;
-
- // child
- case 0: {
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata;
-
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
-
- capheader.version = _LINUX_CAPABILITY_VERSION;
- capheader.pid = 0;
-
- if (capget(&capheader, &capdata) != 0) {
- PLOG(ERROR) << "capget";
- exit(1);
- }
-
- capdata.effective = capdata.permitted;
- if (capset(&capheader, &capdata) != 0) {
- PLOG(ERROR) << "capset";
- exit(1);
- }
-
- if (setgid(AID_SYSTEM) != 0) {
- PLOG(ERROR) << "setgid";
- exit(1);
- }
-
- if (setuid(AID_SYSTEM) != 0) {
- PLOG(ERROR) << "setuid";
- exit(1);
- }
-
- // Generic idmap parameters
- const char* argv[11];
- int argc = 0;
- struct stat st;
-
- memset(argv, 0, sizeof(argv));
- argv[argc++] = AssetManager::IDMAP_BIN;
- argv[argc++] = "--scan";
- argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
- argv[argc++] = AssetManager::TARGET_APK_PATH;
- argv[argc++] = AssetManager::IDMAP_DIR;
-
- // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
- // use VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
- // addition to VENDOR_OVERLAY_DIR.
- std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
- "");
- if (!overlay_theme_path.empty()) {
- overlay_theme_path =
- std::string(AssetManager::VENDOR_OVERLAY_DIR) + "/" + overlay_theme_path;
- if (stat(overlay_theme_path.c_str(), &st) == 0) {
- argv[argc++] = overlay_theme_path.c_str();
- }
- }
-
- if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::VENDOR_OVERLAY_DIR;
- }
-
- if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
- }
-
- if (stat(AssetManager::SYSTEM_EXT_OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::SYSTEM_EXT_OVERLAY_DIR;
- }
-
- if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::ODM_OVERLAY_DIR;
- }
-
- if (stat(AssetManager::OEM_OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::OEM_OVERLAY_DIR;
- }
-
- // Finally, invoke idmap (if any overlay directory exists)
- if (argc > 5) {
- execv(AssetManager::IDMAP_BIN, (char* const*)argv);
- PLOG(ERROR) << "failed to execv for idmap";
- exit(1); // should never get here
- } else {
- exit(0);
- }
- } break;
-
- // parent
- default:
- waitpid(pid, nullptr, 0);
- break;
- }
-}
-
static jobjectArray NativeCreateIdmapsForStaticOverlaysTargetingAndroid(JNIEnv* env,
jclass /*clazz*/) {
// --input-directory can be given multiple times, but idmap2 expects the directory to exist
@@ -1665,7 +1564,6 @@ static const JNINativeMethod gAssetManagerMethods[] = {
{"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength},
// System/idmap related methods.
- {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
{"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
(void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},
{"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;",
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 653d381e2960..56e879090665 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -244,7 +244,8 @@ message AppWindowTokenProto {
optional int32 num_drawn_windows = 15;
optional bool all_drawn = 16;
optional bool last_all_drawn = 17;
- optional bool removed = 18;
+ // Will be removed soon
+ optional bool removed = 18 [deprecated=true];
optional IdentifierProto starting_window = 19;
optional bool starting_displayed = 20;
optional bool starting_moved = 21;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e1ca1f6f346c..62001aabca76 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" />
@@ -4346,6 +4348,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
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e6f038a2829c..74bb2cf6658d 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).
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index d2ce4e0a03b9..fe539e4ca22b 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -244,6 +244,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"/>
@@ -338,6 +339,8 @@ applications that come with the platform
<permission name="android.permission.SYSTEM_CAMERA" />
<!-- 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/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 753f8a05cbe3..ed19a37de460 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -169,12 +169,6 @@
"group": "WM_DEBUG_RESIZE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
- "-1797409732": {
- "message": "Skipping %s because %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"-1782453012": {
"message": "Checking theme of starting window: 0x%x",
"level": "VERBOSE",
@@ -1453,12 +1447,6 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
- "789829331": {
- "message": "Aborted starting %s: removed=%b startingData=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_STARTING_WINDOW",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"791468751": {
"message": "Pausing rotation during re-position",
"level": "DEBUG",
@@ -1927,6 +1915,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1822843721": {
+ "message": "Aborted starting %s: startingData=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STARTING_WINDOW",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1831008694": {
"message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s",
"level": "DEBUG",
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 3c4783590c16..d9ed5f32cfc3 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/location/TEST_MAPPING b/location/TEST_MAPPING
new file mode 100644
index 000000000000..2f386271dcb7
--- /dev/null
+++ b/location/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsLocationCoarseTestCases"
+ },
+ {
+ "name": "CtsLocationNoneTestCases"
+ }
+ ]
+}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 2380077157c1..445420f130d0 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -66,9 +66,9 @@ public final class MediaRoute2Info implements Parcelable {
@Nullable
final String mProviderId;
@NonNull
- final String mName;
+ final CharSequence mName;
@Nullable
- final String mDescription;
+ final CharSequence mDescription;
@Nullable
final String mClientPackageName;
@NonNull
@@ -98,8 +98,8 @@ public final class MediaRoute2Info implements Parcelable {
MediaRoute2Info(@NonNull Parcel in) {
mId = in.readString();
mProviderId = in.readString();
- mName = in.readString();
- mDescription = in.readString();
+ mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mClientPackageName = in.readString();
mSupportedCategories = in.createStringArrayList();
mVolume = in.readInt();
@@ -194,12 +194,12 @@ public final class MediaRoute2Info implements Parcelable {
}
@NonNull
- public String getName() {
+ public CharSequence getName() {
return mName;
}
@Nullable
- public String getDescription() {
+ public CharSequence getDescription() {
return mDescription;
}
@@ -277,8 +277,8 @@ public final class MediaRoute2Info implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mId);
dest.writeString(mProviderId);
- dest.writeString(mName);
- dest.writeString(mDescription);
+ TextUtils.writeToParcel(mName, dest, flags);
+ TextUtils.writeToParcel(mDescription, dest, flags);
dest.writeString(mClientPackageName);
dest.writeStringList(mSupportedCategories);
dest.writeInt(mVolume);
@@ -308,8 +308,8 @@ public final class MediaRoute2Info implements Parcelable {
public static final class Builder {
String mId;
String mProviderId;
- String mName;
- String mDescription;
+ CharSequence mName;
+ CharSequence mDescription;
String mClientPackageName;
List<String> mSupportedCategories;
int mVolume;
@@ -317,13 +317,7 @@ public final class MediaRoute2Info implements Parcelable {
int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
Bundle mExtras;
- public Builder(@NonNull String id, @NonNull String name) {
- if (TextUtils.isEmpty(id)) {
- throw new IllegalArgumentException("id must not be null or empty");
- }
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must not be null or empty");
- }
+ public Builder(@NonNull String id, @NonNull CharSequence name) {
setId(id);
setName(name);
mSupportedCategories = new ArrayList<>();
@@ -379,10 +373,8 @@ public final class MediaRoute2Info implements Parcelable {
* Sets the user-visible name of the route.
*/
@NonNull
- public Builder setName(@NonNull String name) {
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must not be null or empty");
- }
+ public Builder setName(@NonNull CharSequence name) {
+ Objects.requireNonNull(name, "name must not be null");
mName = name;
return this;
}
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 8928c47cf4bb..64f81d5c34fb 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -38,7 +38,7 @@ static constexpr bool kStealActiveStream_OldestFirst = true;
// kPlayOnCallingThread = true prior to R.
// Changing to false means calls to play() are almost instantaneous instead of taking around
// ~10ms to launch the AudioTrack. It is perhaps 100x faster.
-static constexpr bool kPlayOnCallingThread = false;
+static constexpr bool kPlayOnCallingThread = true;
// Amount of time for a StreamManager thread to wait before closing.
static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
@@ -167,6 +167,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
if (!stream->getPairStream()->hasSound()) {
if (stream->getSoundID() == soundID) {
newStream = stream;
+ fromAvailableQueue = false;
break;
} else if (newStream == nullptr) {
newStream = stream;
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 240e7d1b6357..d0f7c780ceb2 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -82,6 +82,11 @@ public class MediaRouterManagerTest {
public static final String CATEGORY_SPECIAL =
"com.android.mediarouteprovider.CATEGORY_SPECIAL";
+ // system routes
+ private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+ private static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+ private static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
+
private static final int TIMEOUT_MS = 5000;
private Context mContext;
@@ -90,13 +95,17 @@ public class MediaRouterManagerTest {
private Executor mExecutor;
private String mPackageName;
- private static final List<String> CONTROL_CATEGORIES_ALL = new ArrayList();
- private static final List<String> CONTROL_CATEGORIES_SPECIAL = new ArrayList();
+ private static final List<String> CATEGORIES_ALL = new ArrayList();
+ private static final List<String> CATEGORIES_SPECIAL = new ArrayList();
+ private static final List<String> CATEGORIES_LIVE_AUDIO = new ArrayList<>();
static {
- CONTROL_CATEGORIES_ALL.add(CATEGORY_SAMPLE);
- CONTROL_CATEGORIES_ALL.add(CATEGORY_SPECIAL);
+ CATEGORIES_ALL.add(CATEGORY_SAMPLE);
+ CATEGORIES_ALL.add(CATEGORY_SPECIAL);
+ CATEGORIES_ALL.add(CATEGORY_LIVE_AUDIO);
+
+ CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
- CONTROL_CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
+ CATEGORIES_LIVE_AUDIO.add(CATEGORY_LIVE_AUDIO);
}
@Before
@@ -153,7 +162,7 @@ public class MediaRouterManagerTest {
mRouter2.registerCallback(mExecutor, routerCallback);
Map<String, MediaRoute2Info> routes =
- waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
+ waitAndGetRoutesWithManager(CATEGORIES_ALL);
CountDownLatch latch = new CountDownLatch(1);
MediaRouter2Manager.Callback callback = new MediaRouter2Manager.Callback() {
@@ -187,7 +196,7 @@ public class MediaRouterManagerTest {
mManager.registerCallback(mExecutor, mockCallback);
Map<String, MediaRoute2Info> routes =
- waitAndGetRoutesWithManager(CONTROL_CATEGORIES_SPECIAL);
+ waitAndGetRoutesWithManager(CATEGORIES_SPECIAL);
Assert.assertEquals(1, routes.size());
Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
@@ -203,7 +212,7 @@ public class MediaRouterManagerTest {
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
mRouter2.registerCallback(mExecutor, mockCallback);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_SPECIAL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_SPECIAL);
Assert.assertEquals(1, routes.size());
Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
@@ -219,7 +228,7 @@ public class MediaRouterManagerTest {
mManager.registerCallback(mExecutor, managerCallback);
mRouter2.registerCallback(mExecutor, routerCallback);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
assertNotNull(routeToSelect);
@@ -242,7 +251,7 @@ public class MediaRouterManagerTest {
mRouter2.registerCallback(mExecutor, routerCallback);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
awaitOnRouteChangedManager(
() -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)),
@@ -264,7 +273,7 @@ public class MediaRouterManagerTest {
@Test
public void testControlVolumeWithRouter() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
int originalVolume = volRoute.getVolume();
@@ -286,7 +295,7 @@ public class MediaRouterManagerTest {
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
mRouter2.registerCallback(mExecutor, mockCallback);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
int originalVolume = volRoute.getVolume();
@@ -309,7 +318,7 @@ public class MediaRouterManagerTest {
public void testVolumeHandling() throws Exception {
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
mRouter2.registerCallback(mExecutor, mockCallback);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
@@ -321,6 +330,13 @@ public class MediaRouterManagerTest {
mRouter2.unregisterCallback(mockCallback);
}
+ @Test
+ public void testDefaultRoute() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_LIVE_AUDIO);
+
+ assertNotNull(routes.get(DEFAULT_ROUTE_ID));
+ }
+
Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
MediaRouter2.Callback callback = new MediaRouter2.Callback() {
@@ -417,6 +433,7 @@ public class MediaRouterManagerTest {
static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
Map<String, MediaRoute2Info> routeMap = new HashMap<>();
for (MediaRoute2Info route : routes) {
+ // intentionally not route.getUniqueId() for convenience.
routeMap.put(route.getId(), route);
}
return routeMap;
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java b/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java
new file mode 100644
index 000000000000..bd86d673c0d1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.widget;
+
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog.Builder;
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceDialogFragmentCompat;
+
+import com.android.settingslib.core.instrumentation.Instrumentable;
+
+import java.util.ArrayList;
+
+/**
+ * {@link PreferenceDialogFragmentCompat} that updates the available options
+ * when {@code onListPreferenceUpdated} is called."
+ */
+public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragmentCompat implements
+ Instrumentable {
+
+ private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
+ private static final String SAVE_STATE_ENTRIES =
+ "UpdatableListPreferenceDialogFragment.entries";
+ private static final String SAVE_STATE_ENTRY_VALUES =
+ "UpdatableListPreferenceDialogFragment.entryValues";
+ private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
+ private ArrayAdapter mAdapter;
+ private int mClickedDialogEntryIndex;
+ private ArrayList<CharSequence> mEntries;
+ private CharSequence[] mEntryValues;
+ private int mMetricsCategory = METRICS_CATEGORY_UNKNOWN;
+
+ /**
+ * Creates a new instance of {@link UpdatableListPreferenceDialogFragment}.
+ */
+ public static UpdatableListPreferenceDialogFragment newInstance(
+ String key, int metricsCategory) {
+ UpdatableListPreferenceDialogFragment fragment =
+ new UpdatableListPreferenceDialogFragment();
+ Bundle args = new Bundle(1);
+ args.putString(ARG_KEY, key);
+ args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Bundle bundle = getArguments();
+ mMetricsCategory =
+ bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
+ if (savedInstanceState == null) {
+ mEntries = new ArrayList<>();
+ setPreferenceData(getListPreference());
+ } else {
+ mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
+ mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
+ mEntryValues =
+ savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
+ outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
+ outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult) {
+ if (positiveResult && mClickedDialogEntryIndex >= 0) {
+ final ListPreference preference = getListPreference();
+ final String value = mEntryValues[mClickedDialogEntryIndex].toString();
+ if (preference.callChangeListener(value)) {
+ preference.setValue(value);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ void setAdapter(ArrayAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ @VisibleForTesting
+ void setEntries(ArrayList<CharSequence> entries) {
+ mEntries = entries;
+ }
+
+ @VisibleForTesting
+ ArrayAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ @VisibleForTesting
+ void setMetricsCategory(Bundle bundle) {
+ mMetricsCategory =
+ bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ final TypedArray a = getContext().obtainStyledAttributes(
+ null,
+ com.android.internal.R.styleable.AlertDialog,
+ com.android.internal.R.attr.alertDialogStyle, 0);
+
+ mAdapter = new ArrayAdapter<>(
+ getContext(),
+ a.getResourceId(
+ com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
+ com.android.internal.R.layout.select_dialog_singlechoice),
+ mEntries);
+
+ builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
+ (dialog, which) -> {
+ mClickedDialogEntryIndex = which;
+ onClick(dialog, -1);
+ dialog.dismiss();
+ });
+ builder.setPositiveButton(null, null);
+ a.recycle();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return mMetricsCategory;
+ }
+
+ @VisibleForTesting
+ ListPreference getListPreference() {
+ return (ListPreference) getPreference();
+ }
+
+ private void setPreferenceData(ListPreference preference) {
+ mEntries.clear();
+ mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
+ for (CharSequence entry : preference.getEntries()) {
+ mEntries.add(entry);
+ }
+ mEntryValues = preference.getEntryValues();
+ }
+
+ /**
+ * Update new data set for list preference.
+ */
+ public void onListPreferenceUpdated(ListPreference preference) {
+ if (mAdapter != null) {
+ setPreferenceData(preference);
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
index 9a07ca885914..c9b066a5768e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
@@ -57,8 +57,7 @@ public class AppEntitiesHeaderControllerTest {
.setIcon(mContext.getDrawable(com.android.internal.R.drawable.ic_menu))
.setTitle(TITLE)
.setSummary(SUMMARY)
- .setOnClickListener(v -> {
- })
+ .setOnClickListener(v -> { })
.build();
mController.setAppEntity(0, mAppEntityInfo);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
new file mode 100644
index 000000000000..0b3495def21f
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+
+import androidx.preference.ListPreference;
+
+import com.android.internal.logging.nano.MetricsProto;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+
+@RunWith(RobolectricTestRunner.class)
+public class UpdatableListPreferenceDialogFragmentTest {
+
+ private static final String KEY = "Test_Key";
+ @Mock
+ private UpdatableListPreferenceDialogFragment mUpdatableListPrefDlgFragment;
+ private Context mContext;
+ private ArrayAdapter mAdapter;
+ private ArrayList<CharSequence> mEntries;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ mUpdatableListPrefDlgFragment = spy(UpdatableListPreferenceDialogFragment
+ .newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES));
+ mEntries = spy(new ArrayList<>());
+ mUpdatableListPrefDlgFragment.setEntries(mEntries);
+ mUpdatableListPrefDlgFragment
+ .setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
+ initAdapter();
+ }
+
+ private void initAdapter() {
+ mAdapter = spy(new ArrayAdapter<>(
+ mContext,
+ com.android.internal.R.layout.select_dialog_singlechoice,
+ mEntries));
+ mUpdatableListPrefDlgFragment.setAdapter(mAdapter);
+ }
+
+ @Test
+ public void getMetricsCategory() {
+ assertThat(mUpdatableListPrefDlgFragment.getMetricsCategory())
+ .isEqualTo(MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
+ }
+
+ @Test
+ public void onListPreferenceUpdated_verifyAdapterCanBeUpdate() {
+ assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(0);
+
+ ListPreference listPreference = new ListPreference(mContext);
+ final CharSequence[] charSequences = {"Test_DEVICE_1", "Test_DEVICE_2"};
+ listPreference.setEntries(charSequences);
+ mUpdatableListPrefDlgFragment.onListPreferenceUpdated(listPreference);
+
+ assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void onDialogClosed_emptyPreference() {
+ mUpdatableListPrefDlgFragment.onDialogClosed(false);
+
+ verify(mUpdatableListPrefDlgFragment, never()).getListPreference();
+ }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c59f342d81e1..1a658f49d516 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -215,6 +215,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/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index ab433d26cb3d..e9c20dbc75ad 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -369,6 +369,10 @@
<receiver android:name=".screenshot.GlobalScreenshot$DeleteScreenshotReceiver"
android:exported="false" />
+ <!-- Callback for invoking a smart action from the screenshot notification. -->
+ <receiver android:name=".screenshot.GlobalScreenshot$SmartActionsReceiver"
+ android:exported="false"/>
+
<!-- started from UsbDeviceSettingsManager -->
<activity android:name=".usb.UsbConfirmActivity"
android:exported="true"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cce4008abe8e..99da058a2e2b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -916,6 +916,10 @@
<string name="quick_settings_ui_mode_night_label">Dark theme</string>
<!-- QuickSettings: Label for the dark theme tile when enabled by battery saver. [CHAR LIMIT=40] -->
<string name="quick_settings_ui_mode_night_label_battery_saver">Dark theme\nBattery saver</string>
+ <!-- QuickSettings: Secondary text for when the Dark Mode will be enabled at sunset. [CHAR LIMIT=20] -->
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset">On at sunset</string>
+ <!-- QuickSettings: Secondary text for when the Dark Mode will be on until sunrise. [CHAR LIMIT=20] -->
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise">Until sunrise</string>
<!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
<string name="quick_settings_nfc_label">NFC</string>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 1a0690c1a273..a616484a3b21 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -163,10 +163,6 @@ public class Dependency {
*/
private static final String BG_LOOPER_NAME = "background_looper";
/**
- * Key for getting a background Handler for background work.
- */
- private static final String BG_HANDLER_NAME = "background_handler";
- /**
* Key for getting a Handler for receiving time tick broadcasts on.
*/
public static final String TIME_TICK_HANDLER_NAME = "time_tick_handler";
@@ -195,10 +191,6 @@ public class Dependency {
*/
public static final DependencyKey<Looper> MAIN_LOOPER = new DependencyKey<>(MAIN_LOOPER_NAME);
/**
- * Key for getting a background Handler for background work.
- */
- public static final DependencyKey<Handler> BG_HANDLER = new DependencyKey<>(BG_HANDLER_NAME);
- /**
* Key for getting a Handler for receiving time tick broadcasts on.
*/
public static final DependencyKey<Handler> TIME_TICK_HANDLER =
@@ -347,7 +339,6 @@ public class Dependency {
// on imports.
mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
mProviders.put(BG_LOOPER, mBgLooper::get);
- mProviders.put(BG_HANDLER, mBgHandler::get);
mProviders.put(MAIN_LOOPER, mMainLooper::get);
mProviders.put(MAIN_HANDLER, mMainHandler::get);
mProviders.put(ActivityStarter.class, mActivityStarter::get);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0d400fef6061..617dbdfe3fcc 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -45,6 +45,8 @@ import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.util.concurrent.Executor;
+
import dagger.Module;
import dagger.Provides;
@@ -124,7 +126,9 @@ public class SystemUIFactory {
* This method is overridden in vendor specific implementation of Sys UI.
*/
public ScreenshotNotificationSmartActionsProvider
- createScreenshotNotificationSmartActionsProvider() {
+ createScreenshotNotificationSmartActionsProvider(Context context,
+ Executor executor,
+ Handler uiHandler) {
return new ScreenshotNotificationSmartActionsProvider();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 0d4cc0170be9..add5f08d7d44 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -36,6 +36,7 @@ import android.service.dreams.IDreamManager;
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
@@ -54,6 +55,11 @@ import dagger.Provides;
*/
@Module
public class SystemServicesModule {
+ @Provides
+ @Singleton
+ static AccessibilityManager provideAccessibilityManager(Context context) {
+ return context.getSystemService(AccessibilityManager.class);
+ }
@Singleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index dd0ea5ef17f4..dc9a2ce1beef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -21,7 +21,7 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.widget.Switch;
+import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.R;
@@ -79,24 +79,33 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
return;
}
boolean newState = !mState.value;
- mUiModeManager.setNightMode(newState ? UiModeManager.MODE_NIGHT_YES
- : UiModeManager.MODE_NIGHT_NO);
+ mUiModeManager.setNightModeActivated(newState);
refreshState(newState);
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
+ int uiMode = mUiModeManager.getNightMode();
boolean powerSave = mBatteryController.isPowerSave();
+ boolean isAuto = uiMode == UiModeManager.MODE_NIGHT_AUTO;
boolean nightMode = (mContext.getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+ & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+ if (isAuto) {
+ state.secondaryLabel = mContext.getResources().getString(nightMode
+ ? R.string.quick_settings_dark_mode_secondary_label_until_sunrise
+ : R.string.quick_settings_dark_mode_secondary_label_on_at_sunset);
+ } else {
+ state.secondaryLabel = null;
+ }
state.value = nightMode;
state.label = mContext.getString(powerSave
? R.string.quick_settings_ui_mode_night_label_battery_saver
: R.string.quick_settings_ui_mode_night_label);
- state.contentDescription = state.label;
state.icon = mIcon;
- state.expandedAccessibilityClassName = Switch.class.getName();
+ state.contentDescription = TextUtils.isEmpty(state.secondaryLabel)
+ ? state.label
+ : TextUtils.concat(state.label, ", ", state.secondaryLabel);
if (powerSave) {
state.state = Tile.STATE_UNAVAILABLE;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e790c1d071ce..66cd91996cea 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -75,6 +75,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -126,8 +127,17 @@ public class GlobalScreenshot {
}
}
- static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
+ // These strings are used for communicating the action invoked to
+ // ScreenshotNotificationSmartActionsProvider.
+ static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
+ static final String EXTRA_ID = "android:screenshot_id";
+ static final String ACTION_TYPE_DELETE = "Delete";
+ static final String ACTION_TYPE_SHARE = "Share";
+ static final String ACTION_TYPE_EDIT = "Edit";
+ static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
+
+ static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
static final String EXTRA_DISALLOW_ENTER_PIP = "android:screenshot_disallow_enter_pip";
@@ -689,9 +699,9 @@ public class GlobalScreenshot {
}
@VisibleForTesting
- static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(Context context,
+ static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(String screenshotId,
Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
- Handler handler, boolean smartActionsEnabled, boolean isManagedProfile) {
+ boolean smartActionsEnabled, boolean isManagedProfile) {
if (!smartActionsEnabled) {
Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
return CompletableFuture.completedFuture(Collections.emptyList());
@@ -705,6 +715,7 @@ public class GlobalScreenshot {
Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
CompletableFuture<List<Notification.Action>> smartActionsFuture;
+ long startTimeMs = SystemClock.uptimeMillis();
try {
ActivityManager.RunningTaskInfo runningTask =
ActivityManagerWrapper.getInstance().getRunningTask();
@@ -712,34 +723,74 @@ public class GlobalScreenshot {
(runningTask != null && runningTask.topActivity != null)
? runningTask.topActivity
: new ComponentName("", "");
- smartActionsFuture = smartActionsProvider.getActions(image, context,
- THREAD_POOL_EXECUTOR,
- handler,
+ smartActionsFuture = smartActionsProvider.getActions(screenshotId, image,
componentName,
isManagedProfile);
} catch (Throwable e) {
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e);
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR,
+ waitTimeMs);
}
return smartActionsFuture;
}
@VisibleForTesting
- static List<Notification.Action> getSmartActions(
- CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs) {
+ static List<Notification.Action> getSmartActions(String screenshotId,
+ CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
+ long startTimeMs = SystemClock.uptimeMillis();
try {
- long startTimeMs = SystemClock.uptimeMillis();
List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
TimeUnit.MILLISECONDS);
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
Slog.d(TAG, String.format("Wait time for smart actions: %d ms",
- SystemClock.uptimeMillis() - startTimeMs));
+ waitTimeMs));
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS,
+ waitTimeMs);
return actions;
} catch (Throwable e) {
- Slog.e(TAG, "Failed to obtain screenshot notification smart actions.", e);
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
+ Slog.d(TAG, "Failed to obtain screenshot notification smart actions.", e);
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
+ (e instanceof TimeoutException)
+ ? ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT
+ : ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR;
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
+ status, waitTimeMs);
return Collections.emptyList();
}
}
+ static void notifyScreenshotOp(String screenshotId,
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp op,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status, long durationMs) {
+ try {
+ smartActionsProvider.notifyOp(screenshotId, op, status, durationMs);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Error in notifyScreenshotOp: ", e);
+ }
+ }
+
+ static void notifyScreenshotAction(Context context, String screenshotId, String action,
+ boolean isSmartAction) {
+ try {
+ ScreenshotNotificationSmartActionsProvider provider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
+ context, THREAD_POOL_EXECUTOR, new Handler());
+ provider.notifyAction(screenshotId, action, isSmartAction);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Error in notifyScreenshotAction: ", e);
+ }
+ }
+
/**
* Receiver to proxy the share or edit intent, used to clean up the notification and send
* appropriate signals to the system (ie. to dismiss the keyguard if necessary).
@@ -783,6 +834,13 @@ public class GlobalScreenshot {
} else {
startActivityRunnable.run();
}
+
+ if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
+ String actionType = Intent.ACTION_EDIT.equals(intent.getAction()) ? ACTION_TYPE_EDIT
+ : ACTION_TYPE_SHARE;
+ notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
+ actionType, false);
+ }
}
}
@@ -813,6 +871,29 @@ public class GlobalScreenshot {
// And delete the image from the media store
final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
new DeleteImageInBackgroundTask(context).execute(uri);
+ if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
+ notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
+ ACTION_TYPE_DELETE,
+ false);
+ }
+ }
+ }
+
+ /**
+ * Executes the smart action tapped by the user in the notification.
+ */
+ public static class SmartActionsReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ PendingIntent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+ ActivityOptions opts = ActivityOptions.makeBasic();
+ context.startActivityAsUser(actionIntent.getIntent(), opts.toBundle(),
+ UserHandle.CURRENT);
+
+ Slog.d(TAG, "Screenshot notification smart action is invoked.");
+ notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
+ intent.getStringExtra(EXTRA_ACTION_TYPE),
+ true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index e9dbe02371d5..5e5cf743b468 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -38,6 +38,7 @@ import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
+import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
@@ -50,6 +51,7 @@ import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.R;
@@ -69,9 +71,12 @@ import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
+import java.util.Random;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
/**
@@ -81,6 +86,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "SaveImageInBackgroundTask";
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+ private static final String SCREENSHOT_ID_TEMPLATE = "Screenshot_%s";
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
private final GlobalScreenshot.SaveImageInBackgroundData mParams;
@@ -91,8 +97,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private final Notification.BigPictureStyle mNotificationStyle;
private final int mImageWidth;
private final int mImageHeight;
- private final Handler mHandler;
private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
+ private final String mScreenshotId;
+ private final boolean mSmartActionsEnabled;
+ private final Random mRandom = new Random();
SaveImageInBackgroundTask(Context context, GlobalScreenshot.SaveImageInBackgroundData data,
NotificationManager nManager) {
@@ -103,11 +111,20 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mImageTime = System.currentTimeMillis();
String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+ mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, UUID.randomUUID());
// Initialize screenshot notification smart actions provider.
- mHandler = new Handler();
- mSmartActionsProvider =
- SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+ mSmartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, false);
+ if (mSmartActionsEnabled) {
+ mSmartActionsProvider =
+ SystemUIFactory.getInstance()
+ .createScreenshotNotificationSmartActionsProvider(
+ context, THREAD_POOL_EXECUTOR, new Handler());
+ } else {
+ // If smart actions is not enabled use empty implementation.
+ mSmartActionsProvider = new ScreenshotNotificationSmartActionsProvider();
+ }
// Create the large notification icon
mImageWidth = data.image.getWidth();
@@ -201,6 +218,38 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
return info.isManagedProfile();
}
+ private List<Notification.Action> buildSmartActions(
+ List<Notification.Action> actions, Context context) {
+ List<Notification.Action> broadcastActions = new ArrayList<>();
+ for (Notification.Action action : actions) {
+ // Proxy smart actions through {@link GlobalScreenshot.SmartActionsReceiver}
+ // for logging smart actions.
+ Bundle extras = action.getExtras();
+ String actionType = extras.getString(
+ ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
+ ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
+ Intent intent = new Intent(context,
+ GlobalScreenshot.SmartActionsReceiver.class).putExtra(
+ GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent);
+ addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
+ PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
+ mRandom.nextInt(),
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ broadcastActions.add(new Notification.Action.Builder(action.getIcon(), action.title,
+ broadcastIntent).setContextual(true).addExtras(extras).build());
+ }
+ return broadcastActions;
+ }
+
+ private static void addIntentExtras(String screenshotId, Intent intent, String actionType,
+ boolean smartActionsEnabled) {
+ intent
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_TYPE, actionType)
+ .putExtra(GlobalScreenshot.EXTRA_ID, screenshotId)
+ .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
+ }
+
/**
* Generates a new hardware bitmap with specified values, copying the content from the
* passed in bitmap.
@@ -227,16 +276,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
Context context = mParams.context;
Bitmap image = mParams.image;
- boolean smartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, true);
- CompletableFuture<List<Notification.Action>>
- smartActionsFuture = GlobalScreenshot.getSmartActionsFuture(
- context, image, mSmartActionsProvider, mHandler, smartActionsEnabled,
- isManagedProfile(context));
-
Resources r = context.getResources();
try {
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mScreenshotId, image,
+ mSmartActionsProvider, mSmartActionsEnabled, isManagedProfile(context));
+
// Save the screenshot to the MediaStore
final MediaStore.PendingParams params = new MediaStore.PendingParams(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
@@ -289,104 +335,11 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
IoUtils.closeQuietly(session);
}
- // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
- // order to do some common work like dismissing the keyguard and sending
- // closeSystemWindows
-
- // Create a share intent, this will always go through the chooser activity first
- // which should not trigger auto-enter PiP
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
- String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(uri));
- sharingIntent.setClipData(clipdata);
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Make sure pending intents for the system user are still unique across users
- // by setting the (otherwise unused) request code to the current user id.
- int requestCode = context.getUserId();
-
- PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
- chooserAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, sharingChooserIntent)
- .putExtra(GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP, true)
- .setAction(Intent.ACTION_SEND),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_share,
- r.getString(com.android.internal.R.string.share), shareAction);
- mNotificationBuilder.addAction(shareActionBuilder.build());
-
- // Create an edit intent, if a specific package is provided as the editor, then
- // launch that directly
- String editorPackage = context.getString(R.string.config_screenshotEditor);
- Intent editIntent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- editIntent.setType("image/png");
- editIntent.setData(uri);
- editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- // Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, editIntent)
- .putExtra(GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION,
- editIntent.getComponent() != null)
- .setAction(Intent.ACTION_EDIT),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_edit,
- r.getString(com.android.internal.R.string.screenshot_edit), editAction);
- mNotificationBuilder.addAction(editActionBuilder.build());
- if (editAction != null && mParams.onEditReady != null) {
- mParams.onEditReady.apply(editAction);
- }
-
- // Create a delete action for the notification
- PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_delete,
- r.getString(com.android.internal.R.string.delete), deleteAction);
- mNotificationBuilder.addAction(deleteActionBuilder.build());
+ populateNotificationActions(context, r, uri, smartActionsFuture, mNotificationBuilder);
mParams.imageUri = uri;
mParams.image = null;
mParams.errorMsgResId = 0;
-
- if (smartActionsEnabled) {
- int timeoutMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags
- .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
- 1000);
- List<Notification.Action> smartActions = GlobalScreenshot.getSmartActions(
- smartActionsFuture,
- timeoutMs);
- for (Notification.Action action : smartActions) {
- mNotificationBuilder.addAction(action);
- }
- }
} catch (Exception e) {
// IOException/UnsupportedOperationException may be thrown if external storage is
// not mounted
@@ -403,6 +356,115 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
return null;
}
+ @VisibleForTesting
+ void populateNotificationActions(Context context, Resources r, Uri uri,
+ CompletableFuture<List<Notification.Action>> smartActionsFuture,
+ Notification.Builder notificationBuilder) {
+ // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+ // order to do some common work like dismissing the keyguard and sending
+ // closeSystemWindows
+
+ // Create a share intent, this will always go through the chooser activity first
+ // which should not trigger auto-enter PiP
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+ String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/png");
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(uri));
+ sharingIntent.setClipData(clipdata);
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Make sure pending intents for the system user are still unique across users
+ // by setting the (otherwise unused) request code to the current user id.
+ int requestCode = context.getUserId();
+
+ PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
+ chooserAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Create a share action for the notification
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, sharingChooserIntent)
+ .putExtra(GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP, true)
+ .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
+ .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ mSmartActionsEnabled)
+ .setAction(Intent.ACTION_SEND),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_share,
+ r.getString(com.android.internal.R.string.share), shareAction);
+ notificationBuilder.addAction(shareActionBuilder.build());
+
+ // Create an edit intent, if a specific package is provided as the editor, then
+ // launch that directly
+ String editorPackage = context.getString(R.string.config_screenshotEditor);
+ Intent editIntent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ editIntent.setType("image/png");
+ editIntent.setData(uri);
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ // Create a edit action
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, editIntent)
+ .putExtra(GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION,
+ editIntent.getComponent() != null)
+ .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
+ .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ mSmartActionsEnabled)
+ .setAction(Intent.ACTION_EDIT),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_edit,
+ r.getString(com.android.internal.R.string.screenshot_edit), editAction);
+ notificationBuilder.addAction(editActionBuilder.build());
+ if (editAction != null && mParams.onEditReady != null) {
+ mParams.onEditReady.apply(editAction);
+ }
+
+ // Create a delete action for the notification
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
+ .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString())
+ .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
+ .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ mSmartActionsEnabled),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_delete,
+ r.getString(com.android.internal.R.string.delete), deleteAction);
+ notificationBuilder.addAction(deleteActionBuilder.build());
+
+ if (mSmartActionsEnabled) {
+ int timeoutMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags
+ .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
+ 1000);
+ List<Notification.Action> smartActions = buildSmartActions(
+ GlobalScreenshot.getSmartActions(mScreenshotId, smartActionsFuture,
+ timeoutMs, mSmartActionsProvider), context);
+ for (Notification.Action action : smartActions) {
+ notificationBuilder.addAction(action);
+ }
+ }
+ }
+
@Override
protected void onPostExecute(Void params) {
if (mParams.errorMsgResId != 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
index fa23bf7d5bde..b6f5447d2867 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -18,41 +18,84 @@ package com.android.systemui.screenshot;
import android.app.Notification;
import android.content.ComponentName;
-import android.content.Context;
import android.graphics.Bitmap;
-import android.os.Handler;
import android.util.Log;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
/**
* This class can be overridden by a vendor-specific sys UI implementation,
* in order to provide smart actions in the screenshot notification.
*/
public class ScreenshotNotificationSmartActionsProvider {
+ /* Key provided in the notification action to get the type of smart action. */
+ public static final String ACTION_TYPE = "action_type";
+ public static final String DEFAULT_ACTION_TYPE = "Smart Action";
+
+ /* Define phases of screenshot execution. */
+ protected enum ScreenshotOp {
+ OP_UNKNOWN,
+ RETRIEVE_SMART_ACTIONS,
+ REQUEST_SMART_ACTIONS,
+ WAIT_FOR_SMART_ACTIONS
+ }
+
+ /* Enum to report success or failure for screenshot execution phases. */
+ protected enum ScreenshotOpStatus {
+ OP_STATUS_UNKNOWN,
+ SUCCESS,
+ ERROR,
+ TIMEOUT
+ }
+
private static final String TAG = "ScreenshotActions";
/**
* Default implementation that returns an empty list.
* This method is overridden in vendor-specific Sys UI implementation.
*
+ * @param screenshotId A generated random unique id for the screenshot.
* @param bitmap The bitmap of the screenshot. The bitmap config must be {@link
* HARDWARE}.
- * @param context The current app {@link Context}.
- * @param executor A {@link Executor} that can be used to execute tasks in parallel.
- * @param handler A {@link Handler} to possibly run UI-thread code.
* @param componentName Contains package and activity class names where the screenshot was
* taken. This is used as an additional signal to generate and rank more
* relevant actions.
* @param isManagedProfile The screenshot was taken for a work profile app.
*/
- public CompletableFuture<List<Notification.Action>> getActions(Bitmap bitmap, Context context,
- Executor executor, Handler handler, ComponentName componentName,
+ public CompletableFuture<List<Notification.Action>> getActions(
+ String screenshotId,
+ Bitmap bitmap,
+ ComponentName componentName,
boolean isManagedProfile) {
Log.d(TAG, "Returning empty smart action list.");
return CompletableFuture.completedFuture(Collections.emptyList());
}
+
+ /**
+ * Notify exceptions and latency encountered during generating smart actions.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param screenshotId Unique id of the screenshot.
+ * @param op screenshot execution phase defined in {@link ScreenshotOp}
+ * @param status {@link ScreenshotOpStatus} to report success or failure.
+ * @param durationMs latency experienced in different phases of screenshots.
+ */
+ public void notifyOp(String screenshotId, ScreenshotOp op, ScreenshotOpStatus status,
+ long durationMs) {
+ Log.d(TAG, "Return without notify.");
+ }
+
+ /**
+ * Notify screenshot notification action invoked.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param screenshotId Unique id of the screenshot.
+ * @param action type of notification action invoked.
+ * @param isSmartAction whether action invoked was a smart action.
+ */
+ public void notifyAction(String screenshotId, String action, boolean isSmartAction) {
+ Log.d(TAG, "Return without notify.");
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 021e7e15c7f6..89aad8f37b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -333,7 +333,6 @@ public class NotificationLockscreenUserManagerImpl implements
}
private boolean hideSilentNotificationsOnLockscreen() {
- // TODO(b/140058091)
return whitelistIpcs(() -> Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 77c0a460f3b6..5a5f9e901514 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -26,6 +26,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -41,6 +42,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
@@ -101,16 +103,18 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
protected String mKeyToRemoveOnGutsClosed;
private final Lazy<StatusBar> mStatusBarLazy;
+ private final Handler mMainHandler;
private Runnable mOpenRunnable;
@Inject
public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager,
- Lazy<StatusBar> statusBarLazy) {
+ Lazy<StatusBar> statusBarLazy, @MainHandler Handler mainHandler,
+ AccessibilityManager accessibilityManager) {
mContext = context;
mVisualStabilityManager = visualStabilityManager;
mStatusBarLazy = statusBarLazy;
- mAccessibilityManager = (AccessibilityManager)
- mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ mMainHandler = mainHandler;
+ mAccessibilityManager = accessibilityManager;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -389,7 +393,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
.setLeaveOpenOnKeyguardHide(true);
}
- Runnable r = () -> Dependency.get(Dependency.MAIN_HANDLER).post(
+ Runnable r = () -> mMainHandler.post(
() -> openGutsInternal(view, x, y, menuItem));
mStatusBarLazy.get().executeRunnableDismissingKeyguard(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 098521fbda51..20148e11489a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -110,7 +110,6 @@ class PrivacyItemControllerTest : SysuiTestCase() {
handler = Handler(testableLooper.looper)
appOpsController = mDependency.injectMockDependency(AppOpsController::class.java)
- mDependency.injectTestDependency(Dependency.BG_HANDLER, handler)
mDependency.injectTestDependency(Dependency.MAIN_HANDLER, handler)
mContext.addMockSystemService(UserManager::class.java, userManager)
mContext.getOrCreateTestableResources().addOverride(R.string.device_services,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 99850e7c922e..3f32c66b2d03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -16,8 +16,12 @@
package com.android.systemui.screenshot;
+import static android.content.Context.NOTIFICATION_SERVICE;
+
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -25,14 +29,20 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Intent;
import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.NotificationChannels;
import org.junit.Assert;
import org.junit.Before;
@@ -70,12 +80,12 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
ScreenshotNotificationSmartActionsProvider.class);
- when(smartActionsProvider.getActions(any(), any(), any(), any(), any(),
+ when(smartActionsProvider.getActions(any(), any(), any(),
eq(false))).thenThrow(
RuntimeException.class);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
- smartActionsProvider, mHandler, true, false);
+ GlobalScreenshot.getSmartActionsFuture("", bitmap,
+ smartActionsProvider, true, false);
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
Assert.assertEquals(Collections.emptyList(), smartActions);
@@ -92,10 +102,19 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
RuntimeException.class);
List<Notification.Action> actions = GlobalScreenshot.getSmartActions(
- smartActionsFuture, timeoutMs);
+ "", smartActionsFuture, timeoutMs, mSmartActionsProvider);
Assert.assertEquals(Collections.emptyList(), actions);
}
+ // Tests any exception thrown in notifying feedback does not affect regular screenshot flow.
+ @Test
+ public void testExceptionHandlingInNotifyingFeedback()
+ throws Exception {
+ doThrow(RuntimeException.class).when(mSmartActionsProvider).notifyOp(any(), any(), any(),
+ anyLong());
+ GlobalScreenshot.notifyScreenshotOp(null, mSmartActionsProvider, null, null, -1);
+ }
+
// Tests for a non-hardware bitmap, ScreenshotNotificationSmartActionsProvider is never invoked
// and a completed future is returned.
@Test
@@ -104,9 +123,9 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
- mSmartActionsProvider, mHandler, true, true);
- verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any(),
+ GlobalScreenshot.getSmartActionsFuture("", bitmap,
+ mSmartActionsProvider, true, true);
+ verify(mSmartActionsProvider, never()).getActions(any(), any(), any(),
eq(false));
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
@@ -118,10 +137,10 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
- GlobalScreenshot.getSmartActionsFuture(mContext, bitmap, mSmartActionsProvider,
- mHandler, true, true);
+ GlobalScreenshot.getSmartActionsFuture("", bitmap, mSmartActionsProvider,
+ true, true);
verify(mSmartActionsProvider, times(1))
- .getActions(any(), any(), any(), any(), any(), eq(true));
+ .getActions(any(), any(), any(), eq(true));
}
// Tests for a hardware bitmap, a completed future is returned.
@@ -131,13 +150,65 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
ScreenshotNotificationSmartActionsProvider actionsProvider =
- SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
+ mContext, null, mHandler);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ GlobalScreenshot.getSmartActionsFuture("", bitmap,
actionsProvider,
- mHandler, true, true);
+ true, true);
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
Assert.assertEquals(smartActions.size(), 0);
}
+
+ // Tests for notification action extras.
+ @Test
+ public void testNotificationActionExtras() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ NotificationManager notificationManager =
+ (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
+ GlobalScreenshot.SaveImageInBackgroundData
+ data = new GlobalScreenshot.SaveImageInBackgroundData();
+ data.context = mContext;
+ data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ data.iconSize = 10;
+ data.finisher = null;
+ data.onEditReady = null;
+ data.previewWidth = 10;
+ data.previewheight = 10;
+ SaveImageInBackgroundTask task = new SaveImageInBackgroundTask(mContext, data,
+ notificationManager);
+ Notification.Builder notificationBuilder = new Notification.Builder(mContext,
+ NotificationChannels.SCREENSHOTS_HEADSUP);
+ task.populateNotificationActions(mContext, mContext.getResources(),
+ Uri.parse("Screenshot_123.png"),
+ CompletableFuture.completedFuture(Collections.emptyList()), notificationBuilder);
+
+ Notification notification = notificationBuilder.build();
+ Assert.assertEquals(notification.actions.length, 3);
+ boolean isShareFound = false;
+ boolean isEditFound = false;
+ boolean isDeleteFound = false;
+ for (Notification.Action action : notification.actions) {
+ Intent intent = action.actionIntent.getIntent();
+ Assert.assertNotNull(intent);
+ Bundle bundle = intent.getExtras();
+ Assert.assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_ID));
+ Assert.assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED));
+
+ if (action.title.equals(GlobalScreenshot.ACTION_TYPE_DELETE)) {
+ isDeleteFound = intent.getAction() == null;
+ } else if (action.title.equals(GlobalScreenshot.ACTION_TYPE_EDIT)) {
+ isEditFound = Intent.ACTION_EDIT.equals(intent.getAction());
+ } else if (action.title.equals(GlobalScreenshot.ACTION_TYPE_SHARE)) {
+ isShareFound = Intent.ACTION_SEND.equals(intent.getAction());
+ }
+ }
+
+ Assert.assertTrue(isEditFound);
+ Assert.assertTrue(isDeleteFound);
+ Assert.assertTrue(isShareFound);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 749dae5c9c8a..4b3249d788d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -56,6 +56,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
@@ -110,6 +111,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private StatusBar mStatusBar;
+ @Mock private AccessibilityManager mAccessibilityManager;
@Before
public void setUp() {
@@ -122,9 +124,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
mHandler = Handler.createAsync(mTestableLooper.getLooper());
mHelper = new NotificationTestHelper(mContext, mDependency);
+ when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
- () -> mStatusBar);
+ () -> mStatusBar, mHandler, mAccessibilityManager);
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
mCheckSaveListener, mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
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/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 950fa8d4038a..5eaa80a5143b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -47,6 +47,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseArray;
@@ -62,6 +63,7 @@ import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.compat.IPlatformCompat;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
@@ -95,6 +97,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
private final AccessibilityWindowManager mA11yWindowManager;
private final DisplayManager mDisplayManager;
private final PowerManager mPowerManager;
+ private final IPlatformCompat mIPlatformCompat;
// Handler for scheduling method invocations on the main thread.
public final InvocationHandler mInvocationHandler;
@@ -228,6 +231,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
mA11yWindowManager = a11yWindowManager;
mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mIPlatformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mEventDispatchHandler = new Handler(mainHandler.getLooper()) {
@Override
public void handleMessage(Message message) {
@@ -336,7 +341,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
// configurable properties.
AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
if (oldInfo != null) {
- oldInfo.updateDynamicallyConfigurableProperties(info);
+ oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info);
setDynamicallyConfigurableProperties(oldInfo);
} else {
setDynamicallyConfigurableProperties(info);
diff --git a/services/core/Android.bp b/services/core/Android.bp
index c6bc1068da39..b8caefd45135 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -92,6 +92,7 @@ java_library_static {
"android.hardware.power-V1.0-java",
"android.hardware.tv.cec-V1.0-java",
"app-compat-annotations",
+ "vintf-vibrator-java",
],
required: [
@@ -111,13 +112,16 @@ java_library_static {
"android.hardware.biometrics.fingerprint-V2.1-java",
"android.hardware.oemlock-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
- "android.hardware.vibrator-V1.4-java",
"android.hardware.configstore-V1.0-java",
"android.hardware.contexthub-V1.0-java",
"android.hidl.manager-V1.2-java",
"dnsresolver_aidl_interface-V2-java",
"netd_event_listener_interface-java",
],
+
+ plugins: [
+ "compat-changeid-annotation-processor",
+ ],
}
java_genrule {
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 5522396ac3e2..94793d0fb717 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -14,6 +14,15 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "CtsLocationFineTestCases"
+ },
+ {
+ "name": "CtsLocationCoarseTestCases"
+ },
+ {
+ "name": "CtsLocationNoneTestCases"
}
]
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index a51746767f0f..b5702541432a 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;
@@ -52,9 +54,10 @@ 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;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.DisableCarModeActivity;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -62,9 +65,15 @@ import com.android.internal.util.DumpUtils;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static android.content.Intent.ACTION_SCREEN_OFF;
final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
@@ -79,7 +88,12 @@ final class UiModeManagerService extends SystemService {
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
+ // we use the override auto mode
+ // for example: force night mode off in the night time while in auto mode
+ private int mNightModeOverride = mNightMode;
+ protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE + "_override";
+ private Map<Integer, String> mCarModePackagePriority = new HashMap<>();
private boolean mCarModeEnabled = false;
private boolean mCharging = false;
private boolean mPowerSave = false;
@@ -112,6 +126,7 @@ final class UiModeManagerService extends SystemService {
private TwilightManager mTwilightManager;
private NotificationManager mNotificationManager;
private StatusBarManager mStatusBarManager;
+ private WindowManagerInternal mWindowManager;
private PowerManager.WakeLock mWakeLock;
@@ -121,6 +136,17 @@ final class UiModeManagerService extends SystemService {
super(context);
}
+ @VisibleForTesting
+ protected UiModeManagerService(Context context, WindowManagerInternal wm,
+ PowerManager.WakeLock wl, TwilightManager tm,
+ boolean setupWizardComplete) {
+ super(context);
+ mWindowManager = wm;
+ mWakeLock = wl;
+ mTwilightManager = tm;
+ mSetupWizardComplete = setupWizardComplete;
+ }
+
private static Intent buildHomeIntent(String category) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category);
@@ -182,8 +208,23 @@ final class UiModeManagerService extends SystemService {
public void onTwilightStateChanged(@Nullable TwilightState state) {
synchronized (mLock) {
if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
- updateComputedNightModeLocked();
- updateLocked(0, 0);
+ final IntentFilter intentFilter =
+ new IntentFilter(ACTION_SCREEN_OFF);
+ getContext().registerReceiver(mOnScreenOffHandler, intentFilter);
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ updateLocked(0, 0);
+ try {
+ getContext().unregisterReceiver(mOnScreenOffHandler);
+ } catch (IllegalArgumentException e) {
+ // we ignore this exception if the receiver is unregistered already.
}
}
}
@@ -222,6 +263,8 @@ final class UiModeManagerService extends SystemService {
public void onChange(boolean selfChange, Uri uri) {
int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE,
mNightMode, 0);
+ mode = mode == UiModeManager.MODE_NIGHT_AUTO
+ ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode));
}
};
@@ -240,6 +283,7 @@ final class UiModeManagerService extends SystemService {
final PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+ mWindowManager = LocalServices.getService(WindowManagerInternal.class);
// If setup isn't complete for this user listen for completion so we can unblock
// being able to send a night mode configuration change event
@@ -306,6 +350,16 @@ final class UiModeManagerService extends SystemService {
false, mDarkThemeObserver, 0);
}
+ @VisibleForTesting
+ protected IUiModeManager getService() {
+ return mService;
+ }
+
+ @VisibleForTesting
+ protected Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
// Records whether setup wizard has happened or not and adds an observer for this user if not.
private void verifySetupWizardCompleted() {
final Context context = getContext();
@@ -340,8 +394,11 @@ final class UiModeManagerService extends SystemService {
if (mSetupWizardComplete) {
mNightMode = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE, defaultNightMode, userId);
+ mNightModeOverride = Secure.getIntForUser(context.getContentResolver(),
+ OVERRIDE_NIGHT_MODE, defaultNightMode, userId);
} else {
mNightMode = defaultNightMode;
+ mNightModeOverride = defaultNightMode;
}
return oldNightMode != mNightMode;
@@ -349,15 +406,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);
}
@@ -367,16 +434,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);
}
@@ -424,14 +524,30 @@ final class UiModeManagerService extends SystemService {
try {
synchronized (mLock) {
if (mNightMode != mode) {
+ if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+ try {
+ getContext().unregisterReceiver(mOnScreenOffHandler);
+ } catch (IllegalArgumentException e) {
+ // we ignore this exception if the receiver is unregistered already.
+ }
+ }
// Only persist setting if not in car mode
if (!mCarModeEnabled) {
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mode, user);
+ Secure.putIntForUser(getContext().getContentResolver(),
+ OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
}
mNightMode = mode;
- updateLocked(0, 0);
+ mNightModeOverride = mode;
+ //on screen off will update configuration instead
+ if (mNightMode != UiModeManager.MODE_NIGHT_AUTO) {
+ updateLocked(0, 0);
+ } else {
+ getContext().registerReceiver(
+ mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF));
+ }
}
}
} finally {
@@ -471,25 +587,66 @@ final class UiModeManagerService extends SystemService {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
dumpImpl(pw);
}
+
+ @Override
+ public boolean setNightModeActivated(boolean active) {
+ synchronized (mLock) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+ try {
+ getContext().unregisterReceiver(mOnScreenOffHandler);
+ } catch (IllegalArgumentException e) {
+ }
+ mNightModeOverride = active
+ ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
+ } else if (mNightMode == UiModeManager.MODE_NIGHT_NO
+ && active) {
+ mNightMode = UiModeManager.MODE_NIGHT_YES;
+ } else if (mNightMode == UiModeManager.MODE_NIGHT_YES
+ && !active) {
+ mNightMode = UiModeManager.MODE_NIGHT_NO;
+ }
+ updateConfigurationLocked();
+ sendConfigurationLocked();
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
};
void dumpImpl(PrintWriter pw) {
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()=");
@@ -512,12 +669,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(),
@@ -527,11 +704,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);
}
@@ -598,6 +866,8 @@ final class UiModeManagerService extends SystemService {
if (!mHoldingConfiguration) {
mConfiguration.uiMode = uiMode;
}
+ // load splash screen instead of screenshot
+ mWindowManager.clearSnapshotCache();
}
private void sendConfigurationLocked() {
@@ -848,6 +1118,20 @@ final class UiModeManagerService extends SystemService {
if (state != null) {
mComputedNightMode = state.isNight();
}
+ if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) {
+ mComputedNightMode = true;
+ return;
+ }
+ if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) {
+ mComputedNightMode = false;
+ return;
+ }
+
+ mNightModeOverride = mNightMode;
+ final int user = UserHandle.getCallingUserId();
+ Secure.putIntForUser(getContext().getContentResolver(),
+ OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
+
}
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index b8acd7ac108a..3330882cc07d 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -28,8 +28,8 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
+import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.V1_0.EffectStrength;
-import android.hardware.vibrator.V1_4.Capabilities;
import android.icu.text.DateFormat;
import android.media.AudioAttributes;
import android.media.AudioManager;
@@ -1154,7 +1154,7 @@ public class VibratorService extends IVibratorService.Stub
long duration = vibratorPerformEffect(prebaked.getId(),
prebaked.getEffectStrength(), vib);
long timeout = duration;
- if ((mCapabilities & Capabilities.PERFORM_COMPLETION_CALLBACK) != 0) {
+ if ((mCapabilities & IVibrator.CAP_PERFORM_CALLBACK) != 0) {
timeout *= ASYNC_TIMEOUT_MULTIPLIER;
}
if (timeout > 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/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 709f3f82d4c5..ae5ad7ea1261 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -126,6 +126,12 @@ public class PlatformCompat extends IPlatformCompat.Stub {
}
@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);
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
index 23d0b40f08f6..11a397948b14 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -40,16 +40,16 @@ public final class RuleXmlParser implements RuleParser {
public static final String TAG = "RuleXmlParser";
- // TODO: Use XML attributes
+ private static final String NAMESPACE = "";
private static final String RULE_LIST_TAG = "RL";
private static final String RULE_TAG = "R";
private static final String OPEN_FORMULA_TAG = "OF";
private static final String ATOMIC_FORMULA_TAG = "AF";
- private static final String EFFECT_TAG = "E";
- private static final String KEY_TAG = "K";
- private static final String OPERATOR_TAG = "O";
- private static final String VALUE_TAG = "V";
- private static final String CONNECTOR_TAG = "C";
+ private static final String EFFECT_ATTRIBUTE = "E";
+ private static final String KEY_ATTRIBUTE = "K";
+ private static final String OPERATOR_ATTRIBUTE = "O";
+ private static final String VALUE_ATTRIBUTE = "V";
+ private static final String CONNECTOR_ATTRIBUTE = "C";
@Override
public List<Rule> parse(String ruleText) throws RuleParseException {
@@ -106,7 +106,7 @@ public final class RuleXmlParser implements RuleParser {
private static Rule parseRule(XmlPullParser parser) throws IOException, XmlPullParserException {
Formula formula = null;
- @Rule.Effect int effect = 0;
+ @Rule.Effect int effect = Integer.parseInt(extractAttributeValue(parser, EFFECT_ATTRIBUTE));
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -124,9 +124,6 @@ public final class RuleXmlParser implements RuleParser {
case ATOMIC_FORMULA_TAG:
formula = parseAtomicFormula(parser);
break;
- case EFFECT_TAG:
- effect = Integer.parseInt(extractValue(parser));
- break;
default:
throw new RuntimeException(
String.format("Found unexpected tag: %s", nodeName));
@@ -142,7 +139,8 @@ public final class RuleXmlParser implements RuleParser {
private static Formula parseOpenFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
- @OpenFormula.Connector int connector = 0;
+ @OpenFormula.Connector int connector = Integer.parseInt(
+ extractAttributeValue(parser, CONNECTOR_ATTRIBUTE));
List<Formula> formulas = new ArrayList<>();
int eventType;
@@ -155,9 +153,6 @@ public final class RuleXmlParser implements RuleParser {
if (eventType == XmlPullParser.START_TAG) {
switch (nodeName) {
- case CONNECTOR_TAG:
- connector = Integer.parseInt(extractValue(parser));
- break;
case ATOMIC_FORMULA_TAG:
formulas.add(parseAtomicFormula(parser));
break;
@@ -179,37 +174,16 @@ public final class RuleXmlParser implements RuleParser {
private static Formula parseAtomicFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
- @AtomicFormula.Key int key = 0;
- @AtomicFormula.Operator int operator = 0;
- String value = null;
+ @AtomicFormula.Key int key = Integer.parseInt(extractAttributeValue(parser, KEY_ATTRIBUTE));
+ @AtomicFormula.Operator int operator = Integer.parseInt(
+ extractAttributeValue(parser, OPERATOR_ATTRIBUTE));
+ String value = extractAttributeValue(parser, VALUE_ATTRIBUTE);
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
- String nodeName = parser.getName();
-
if (eventType == XmlPullParser.END_TAG && parser.getName().equals(ATOMIC_FORMULA_TAG)) {
break;
}
-
- if (eventType == XmlPullParser.START_TAG) {
- switch (nodeName) {
- case KEY_TAG:
- key = Integer.parseInt(extractValue(parser));
- break;
- case OPERATOR_TAG:
- operator = Integer.parseInt(extractValue(parser));
- break;
- case VALUE_TAG:
- value = extractValue(parser);
- break;
- default:
- throw new RuntimeException(
- String.format("Found unexpected tag: %s", nodeName));
- }
- } else {
- throw new RuntimeException(
- String.format("Found unexpected event type: %d", eventType));
- }
}
return constructAtomicFormulaBasedOnKey(key, operator, value);
}
@@ -231,17 +205,11 @@ public final class RuleXmlParser implements RuleParser {
}
}
- private static String extractValue(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- String value;
- int eventType = parser.next();
- if (eventType == XmlPullParser.TEXT) {
- value = parser.getText();
- eventType = parser.next();
- if (eventType == XmlPullParser.END_TAG) {
- return value;
- }
+ private static String extractAttributeValue(XmlPullParser parser, String attribute) {
+ String attributeValue = parser.getAttributeValue(NAMESPACE, attribute);
+ if (attributeValue == null) {
+ throw new RuntimeException(String.format("Attribute not found: %s", attribute));
}
- throw new RuntimeException(String.format("Found unexpected event type: %d", eventType));
+ return attributeValue;
}
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index b0805fc488cb..1f22afb0e9bf 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -43,11 +43,11 @@ public class RuleXmlSerializer implements RuleSerializer {
private static final String RULE_TAG = "R";
private static final String OPEN_FORMULA_TAG = "OF";
private static final String ATOMIC_FORMULA_TAG = "AF";
- private static final String EFFECT_TAG = "E";
- private static final String KEY_TAG = "K";
- private static final String OPERATOR_TAG = "O";
- private static final String VALUE_TAG = "V";
- private static final String CONNECTOR_TAG = "C";
+ private static final String EFFECT_ATTRIBUTE = "E";
+ private static final String KEY_ATTRIBUTE = "K";
+ private static final String OPERATOR_ATTRIBUTE = "O";
+ private static final String VALUE_ATTRIBUTE = "V";
+ private static final String CONNECTOR_ATTRIBUTE = "C";
@Override
public void serialize(List<Rule> rules, OutputStream outputStream)
@@ -88,8 +88,8 @@ public class RuleXmlSerializer implements RuleSerializer {
return;
}
xmlSerializer.startTag(NAMESPACE, RULE_TAG);
+ serializeAttributeValue(EFFECT_ATTRIBUTE, String.valueOf(rule.getEffect()), xmlSerializer);
serializeFormula(rule.getFormula(), xmlSerializer);
- serializeValue(EFFECT_TAG, String.valueOf(rule.getEffect()), xmlSerializer);
xmlSerializer.endTag(NAMESPACE, RULE_TAG);
}
@@ -110,7 +110,8 @@ public class RuleXmlSerializer implements RuleSerializer {
return;
}
xmlSerializer.startTag(NAMESPACE, OPEN_FORMULA_TAG);
- serializeValue(CONNECTOR_TAG, String.valueOf(openFormula.getConnector()), xmlSerializer);
+ serializeAttributeValue(CONNECTOR_ATTRIBUTE, String.valueOf(openFormula.getConnector()),
+ xmlSerializer);
for (Formula formula : openFormula.getFormulas()) {
serializeFormula(formula, xmlSerializer);
}
@@ -123,19 +124,20 @@ public class RuleXmlSerializer implements RuleSerializer {
return;
}
xmlSerializer.startTag(NAMESPACE, ATOMIC_FORMULA_TAG);
- serializeValue(KEY_TAG, String.valueOf(atomicFormula.getKey()), xmlSerializer);
+ serializeAttributeValue(KEY_ATTRIBUTE, String.valueOf(atomicFormula.getKey()),
+ xmlSerializer);
if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) {
- serializeValue(VALUE_TAG,
+ serializeAttributeValue(VALUE_ATTRIBUTE,
((AtomicFormula.StringAtomicFormula) atomicFormula).getValue(), xmlSerializer);
} else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) {
- serializeValue(OPERATOR_TAG,
+ serializeAttributeValue(OPERATOR_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()),
xmlSerializer);
- serializeValue(VALUE_TAG,
+ serializeAttributeValue(VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()),
xmlSerializer);
} else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) {
- serializeValue(VALUE_TAG,
+ serializeAttributeValue(VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.BooleanAtomicFormula) atomicFormula).getValue()),
xmlSerializer);
} else {
@@ -145,13 +147,12 @@ public class RuleXmlSerializer implements RuleSerializer {
xmlSerializer.endTag(NAMESPACE, ATOMIC_FORMULA_TAG);
}
- private void serializeValue(String tag, String value, XmlSerializer xmlSerializer)
+ private void serializeAttributeValue(String attribute, String value,
+ XmlSerializer xmlSerializer)
throws IOException {
if (value == null) {
return;
}
- xmlSerializer.startTag(NAMESPACE, tag);
- xmlSerializer.text(value);
- xmlSerializer.endTag(NAMESPACE, tag);
+ xmlSerializer.attribute(NAMESPACE, attribute, value);
}
}
diff --git a/services/core/java/com/android/server/location/TEST_MAPPING b/services/core/java/com/android/server/location/TEST_MAPPING
new file mode 100644
index 000000000000..2e21fa67a967
--- /dev/null
+++ b/services/core/java/com/android/server/location/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsLocationCoarseTestCases"
+ },
+ {
+ "name": "CtsLocationNoneTestCases"
+ }
+ ]
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
new file mode 100644
index 000000000000..91c9253269a3
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.media.MediaRoute2Info;
+import android.media.MediaRoute2ProviderInfo;
+
+import java.util.Objects;
+
+abstract class MediaRoute2Provider {
+ final ComponentName mComponentName;
+ final String mUniqueId;
+
+ private Callback mCallback;
+ private MediaRoute2ProviderInfo mProviderInfo;
+
+ MediaRoute2Provider(@NonNull ComponentName componentName) {
+ mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
+ mUniqueId = componentName.flattenToShortString();
+ }
+
+ public void setCallback(MediaRoute2ProviderProxy.Callback callback) {
+ mCallback = callback;
+ }
+
+ public abstract void requestSelectRoute(String packageName, String routeId, int seq);
+ public abstract void unselectRoute(String packageName, String routeId);
+ public abstract void sendControlRequest(MediaRoute2Info route, Intent request);
+ public abstract void requestSetVolume(MediaRoute2Info route, int volume);
+ public abstract void requestUpdateVolume(MediaRoute2Info route, int delta);
+
+ @NonNull
+ public String getUniqueId() {
+ return mUniqueId;
+ }
+
+ @Nullable
+ public MediaRoute2ProviderInfo getProviderInfo() {
+ return mProviderInfo;
+ }
+
+ void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
+ //TODO: check if info is not updated
+ if (info == null) {
+ mProviderInfo = null;
+ } else {
+ mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
+ .setUniqueId(mUniqueId)
+ .build();
+ }
+ if (mCallback != null) {
+ mCallback.onProviderStateChanged(this);
+ }
+ }
+
+ public boolean hasComponentName(String packageName, String className) {
+ return mComponentName.getPackageName().equals(packageName)
+ && mComponentName.getClassName().equals(className);
+ }
+
+ public interface Callback {
+ void onProviderStateChanged(MediaRoute2Provider provider);
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 51a0df33bc65..3b6580ad7357 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -17,7 +17,6 @@
package com.android.server.media;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -42,20 +41,14 @@ import java.util.Objects;
/**
* Maintains a connection to a particular media route provider service.
*/
-final class MediaRoute2ProviderProxy implements ServiceConnection {
+final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements ServiceConnection {
private static final String TAG = "MR2ProviderProxy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final Context mContext;
- private final ComponentName mComponentName;
- private final String mUniqueId;
private final int mUserId;
private final Handler mHandler;
- private Callback mCallback;
-
- private MediaRoute2ProviderInfo mProviderInfo;
-
// Connection state
private boolean mRunning;
private boolean mBound;
@@ -64,9 +57,8 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
MediaRoute2ProviderProxy(@NonNull Context context, @NonNull ComponentName componentName,
int userId) {
+ super(componentName);
mContext = Objects.requireNonNull(context, "Context must not be null.");
- mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
- mUniqueId = componentName.flattenToShortString();
mUserId = userId;
mHandler = new Handler();
}
@@ -80,10 +72,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
}
- public void setCallback(Callback callback) {
- mCallback = callback;
- }
-
+ @Override
public void requestSelectRoute(String packageName, String routeId, int seq) {
if (mConnectionReady) {
mActiveConnection.requestSelectRoute(packageName, routeId, seq);
@@ -91,6 +80,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
}
+ @Override
public void unselectRoute(String packageName, String routeId) {
if (mConnectionReady) {
mActiveConnection.unselectRoute(packageName, routeId);
@@ -98,6 +88,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
}
+ @Override
public void sendControlRequest(MediaRoute2Info route, Intent request) {
if (mConnectionReady) {
mActiveConnection.sendControlRequest(route.getId(), request);
@@ -105,6 +96,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
}
+ @Override
public void requestSetVolume(MediaRoute2Info route, int volume) {
if (mConnectionReady) {
mActiveConnection.requestSetVolume(route.getId(), volume);
@@ -112,6 +104,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
}
+ @Override
public void requestUpdateVolume(MediaRoute2Info route, int delta) {
if (mConnectionReady) {
mActiveConnection.requestUpdateVolume(route.getId(), delta);
@@ -119,16 +112,6 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
}
}
- @NonNull
- public String getUniqueId() {
- return mUniqueId;
- }
-
- @Nullable
- public MediaRoute2ProviderInfo getProviderInfo() {
- return mProviderInfo;
- }
-
public boolean hasComponentName(String packageName, String className) {
return mComponentName.getPackageName().equals(packageName)
&& mComponentName.getClassName().equals(className);
@@ -270,20 +253,6 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
setAndNotifyProviderInfo(info);
}
- private void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
- //TODO: check if info is not updated
- if (info == null) {
- mProviderInfo = null;
- } else {
- mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
- .setUniqueId(mUniqueId)
- .build();
- }
- if (mCallback != null) {
- mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
- }
- }
-
private void disconnect() {
if (mActiveConnection != null) {
mConnectionReady = false;
@@ -298,10 +267,6 @@ final class MediaRoute2ProviderProxy implements ServiceConnection {
return "Service connection " + mComponentName.flattenToShortString();
}
- public interface Callback {
- void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider);
- }
-
private final class Connection implements DeathRecipient {
private final IMediaRoute2Provider mProvider;
private final ProviderClient mClient;
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index adfb9cb0964e..7820cd705193 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -728,14 +728,15 @@ class MediaRouter2ServiceImpl {
static final class UserHandler extends Handler implements
MediaRoute2ProviderWatcher.Callback,
- MediaRoute2ProviderProxy.Callback {
+ MediaRoute2Provider.Callback {
private final WeakReference<MediaRouter2ServiceImpl> mServiceRef;
private final UserRecord mUserRecord;
private final MediaRoute2ProviderWatcher mWatcher;
//TODO: Make this thread-safe.
- private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
+ private final SystemMediaRoute2Provider mSystemProvider;
+ private final ArrayList<MediaRoute2Provider> mMediaProviders =
new ArrayList<>();
private final List<MediaRoute2ProviderInfo> mProviderInfos = new ArrayList<>();
@@ -746,6 +747,8 @@ class MediaRouter2ServiceImpl {
super(Looper.getMainLooper(), null, true);
mServiceRef = new WeakReference<>(service);
mUserRecord = userRecord;
+ mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this);
+ mMediaProviders.add(mSystemProvider);
mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
this, mUserRecord.mUserId);
}
@@ -777,7 +780,7 @@ class MediaRouter2ServiceImpl {
}
@Override
- public void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider) {
+ public void onProviderStateChanged(@NonNull MediaRoute2Provider provider) {
sendMessage(PooledLambda.obtainMessage(UserHandler::updateProvider, this, provider));
}
@@ -790,7 +793,7 @@ class MediaRouter2ServiceImpl {
controlHints, seq));
}
- private void updateProvider(MediaRoute2ProviderProxy provider) {
+ private void updateProvider(MediaRoute2Provider provider) {
int providerIndex = getProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
MediaRoute2ProviderInfo prevInfo =
@@ -954,7 +957,7 @@ class MediaRouter2ServiceImpl {
private void requestSelectRoute(String clientPackageName, MediaRoute2Info route, int seq) {
if (route != null) {
- MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+ MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider == null) {
Slog.w(TAG, "Ignoring to select route of unknown provider " + route);
} else {
@@ -965,7 +968,7 @@ class MediaRouter2ServiceImpl {
private void unselectRoute(String clientPackageName, MediaRoute2Info route) {
if (route != null) {
- MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+ MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider == null) {
Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route);
} else {
@@ -975,21 +978,21 @@ class MediaRouter2ServiceImpl {
}
private void sendControlRequest(MediaRoute2Info route, Intent request) {
- final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+ final MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider != null) {
provider.sendControlRequest(route, request);
}
}
private void requestSetVolume(MediaRoute2Info route, int volume) {
- final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+ final MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider != null) {
provider.requestSetVolume(route, volume);
}
}
private void requestUpdateVolume(MediaRoute2Info route, int delta) {
- final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+ final MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider != null) {
provider.requestUpdateVolume(route, delta);
}
@@ -1153,8 +1156,8 @@ class MediaRouter2ServiceImpl {
}
}
- private MediaRoute2ProviderProxy findProvider(String providerId) {
- for (MediaRoute2ProviderProxy provider : mMediaProviders) {
+ private MediaRoute2Provider findProvider(String providerId) {
+ for (MediaRoute2Provider provider : mMediaProviders) {
if (TextUtils.equals(provider.getUniqueId(), providerId)) {
return provider;
}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
new file mode 100644
index 000000000000..620775e4aaba
--- /dev/null
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.media.MediaRoute2ProviderInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.R;
+
+/**
+ * Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers.
+ */
+class SystemMediaRoute2Provider extends MediaRoute2Provider {
+ private static final String TAG = "MR2SystemProvider";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+ private static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
+
+ // TODO: Move these to a proper place
+ public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+ public static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
+
+ private final AudioManager mAudioManager;
+ private final IAudioService mAudioService;
+ private final Handler mHandler;
+ private final Context mContext;
+
+ private static ComponentName sComponentName = new ComponentName(
+ SystemMediaRoute2Provider.class.getPackageName$(),
+ SystemMediaRoute2Provider.class.getName());
+
+ //TODO: Clean up these when audio manager support multiple bt devices
+ MediaRoute2Info mDefaultRoute;
+ MediaRoute2Info mBluetoothA2dpRoute;
+ final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
+
+ final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
+ @Override
+ public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ updateAudioRoutes(newRoutes);
+ }
+ });
+ }
+ };
+
+ SystemMediaRoute2Provider(Context context, Callback callback) {
+ super(sComponentName);
+ setCallback(callback);
+
+ mContext = context;
+ mHandler = new Handler(Looper.getMainLooper());
+
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mAudioService = IAudioService.Stub.asInterface(
+ ServiceManager.getService(Context.AUDIO_SERVICE));
+
+ initializeRoutes();
+ }
+
+ //TODO: implement method
+ @Override
+ public void requestSelectRoute(@NonNull String packageName, @NonNull String routeId, int seq) {
+ try {
+ mAudioService.setBluetoothA2dpOn(
+ !TextUtils.equals(routeId, mDefaultRoute.getId()));
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Error changing Bluetooth A2DP route");
+ }
+ }
+
+ //TODO: implement method
+ @Override
+ public void unselectRoute(@NonNull String packageName, @NonNull String routeId) {
+ // does nothing..?
+ }
+
+ //TODO: implement method
+ @Override
+ public void sendControlRequest(@NonNull MediaRoute2Info route, @NonNull Intent request) {
+ }
+
+ //TODO: implement method
+ @Override
+ public void requestSetVolume(MediaRoute2Info route, int volume) {
+ }
+
+ //TODO: implement method
+ @Override
+ public void requestUpdateVolume(MediaRoute2Info route, int delta) {
+ }
+
+ void initializeRoutes() {
+ //TODO: adds necessary info
+ mDefaultRoute = new MediaRoute2Info.Builder(
+ DEFAULT_ROUTE_ID,
+ mContext.getResources().getText(R.string.default_audio_route_name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
+ .addSupportedCategory(CATEGORY_LIVE_AUDIO)
+ .addSupportedCategory(CATEGORY_LIVE_VIDEO)
+ .build();
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ }
+ if (newAudioRoutes != null) {
+ // This will select the active BT route if there is one and the current
+ // selected route is the default system route, or if there is no selected
+ // route yet.
+ updateAudioRoutes(newAudioRoutes);
+ }
+
+ publishRoutes();
+ }
+
+ void updateAudioRoutes(AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ mCurAudioRoutesInfo.mainType = newRoutes.mainType;
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
+ || (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ name = com.android.internal.R.string.default_audio_route_name_hdmi;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ name = com.android.internal.R.string.default_audio_route_name_usb;
+ }
+
+ mDefaultRoute = new MediaRoute2Info.Builder(
+ DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
+ .addSupportedCategory(CATEGORY_LIVE_AUDIO)
+ .addSupportedCategory(CATEGORY_LIVE_VIDEO)
+ .build();
+
+ if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
+ mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
+ if (mCurAudioRoutesInfo.bluetoothName != null) {
+ //TODO: mark as bluetooth once MediaRoute2Info has device type
+ mBluetoothA2dpRoute = new MediaRoute2Info.Builder(BLUETOOTH_ROUTE_ID,
+ mCurAudioRoutesInfo.bluetoothName)
+ .setDescription(mContext.getResources().getText(
+ R.string.bluetooth_a2dp_audio_route_name).toString())
+ .addSupportedCategory(CATEGORY_LIVE_AUDIO)
+ .build();
+ } else {
+ mBluetoothA2dpRoute = null;
+ }
+ }
+
+ publishRoutes();
+ }
+ void publishRoutes() {
+ MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder()
+ .addRoute(mDefaultRoute);
+ if (mBluetoothA2dpRoute != null) {
+ builder.addRoute(mBluetoothA2dpRoute);
+ }
+ setAndNotifyProviderInfo(builder.build());
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3351bb1eb35b..2761987e2358 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -131,6 +131,7 @@ import android.app.role.RoleManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.companion.ICompanionDeviceManager;
+import android.compat.annotation.ChangeId;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -216,6 +217,7 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
@@ -236,6 +238,7 @@ import com.android.server.EventLogTags;
import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.UiThread;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.notification.ManagedServices.ManagedServiceInfo;
@@ -355,6 +358,15 @@ public class NotificationManagerService extends SystemService {
private static final int REQUEST_CODE_TIMEOUT = 1;
private static final String SCHEME_TIMEOUT = "timeout";
private static final String EXTRA_KEY = "key";
+
+ /**
+ * Apps targeting R+ that post custom toasts in the background will have those blocked. Apps can
+ * still post toasts created with {@link Toast#makeText(Context, CharSequence, int)} and its
+ * variants while in the background.
+ */
+ @ChangeId
+ private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L;
+
private IActivityManager mAm;
private ActivityManager mActivityManager;
private IPackageManager mPackageManager;
@@ -372,9 +384,11 @@ public class NotificationManagerService extends SystemService {
private UriGrantsManagerInternal mUgmInternal;
private RoleObserver mRoleObserver;
private UserManager mUm;
+ private IPlatformCompat mPlatformCompat;
final IBinder mForegroundToken = new Binder();
private WorkerHandler mHandler;
+ private Handler mUiHandler;
private final HandlerThread mRankingThread = new HandlerThread("ranker",
Process.THREAD_PRIORITY_BACKGROUND);
@@ -1782,8 +1796,11 @@ public class NotificationManagerService extends SystemService {
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mDpm = dpm;
mUm = userManager;
+ mPlatformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mHandler = new WorkerHandler(looper);
+ mUiHandler = new Handler(UiThread.get().getLooper());
String[] extractorNames;
try {
extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors);
@@ -2450,9 +2467,19 @@ public class NotificationManagerService extends SystemService {
// ============================================================================
@Override
+ public void enqueueTextToast(String pkg, ITransientNotification callback, int duration,
+ int displayId) {
+ enqueueToast(pkg, callback, duration, displayId, false);
+ }
+
+ @Override
public void enqueueToast(String pkg, ITransientNotification callback, int duration,
- int displayId)
- {
+ int displayId) {
+ enqueueToast(pkg, callback, duration, displayId, true);
+ }
+
+ private void enqueueToast(String pkg, ITransientNotification callback, int duration,
+ int displayId, boolean isCustomToast) {
if (DBG) {
Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
+ " duration=" + duration + " displayId=" + displayId);
@@ -2464,27 +2491,54 @@ public class NotificationManagerService extends SystemService {
}
final int callingUid = Binder.getCallingUid();
+ final UserHandle callingUser = Binder.getCallingUserHandle();
final boolean isSystemToast = isCallerSystemOrPhone()
|| PackageManagerService.PLATFORM_PACKAGE_NAME.equals(pkg);
final boolean isPackageSuspended = isPackagePaused(pkg);
final boolean notificationsDisabledForPackage = !areNotificationsEnabledForPackage(pkg,
callingUid);
+ final boolean appIsForeground;
long callingIdentity = Binder.clearCallingIdentity();
try {
- final boolean appIsForeground = mActivityManager.getUidImportance(callingUid)
+ appIsForeground = mActivityManager.getUidImportance(callingUid)
== IMPORTANCE_FOREGROUND;
- if (ENABLE_BLOCKED_TOASTS && !isSystemToast && ((notificationsDisabledForPackage
- && !appIsForeground) || isPackageSuspended)) {
- Slog.e(TAG, "Suppressing toast from package " + pkg
- + (isPackageSuspended ? " due to package suspended."
- : " by user request."));
- return;
- }
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
+ if (ENABLE_BLOCKED_TOASTS && !isSystemToast && ((notificationsDisabledForPackage
+ && !appIsForeground) || isPackageSuspended)) {
+ Slog.e(TAG, "Suppressing toast from package " + pkg
+ + (isPackageSuspended ? " due to package suspended."
+ : " by user request."));
+ return;
+ }
+
+ if (isCustomToast && !appIsForeground && !isSystemToast) {
+ boolean block;
+ try {
+ block = mPlatformCompat.isChangeEnabledByPackageName(
+ CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, pkg,
+ callingUser.getIdentifier());
+ } catch (RemoteException e) {
+ // Shouldn't happen have since it's a local local
+ Slog.e(TAG, "Unexpected exception while checking block background custom toasts"
+ + " change", e);
+ block = false;
+ }
+ if (block) {
+ // TODO(b/144152069): Remove informative toast
+ mUiHandler.post(() -> Toast.makeText(getContext(),
+ "Background custom toast blocked for package " + pkg + ".\n"
+ + "See go/r-toast-block.",
+ Toast.LENGTH_SHORT).show());
+ Slog.w(TAG, "Blocking custom toast from package " + pkg
+ + " due to package not in the foreground");
+ return;
+ }
+ }
+
synchronized (mToastQueue) {
int callingPid = Binder.getCallingPid();
long callingId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index b3b0029326d5..26cd42daa9f8 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -354,28 +354,6 @@ public class Installer extends SystemService {
}
}
- public void idmap(String targetApkPath, String overlayApkPath, int uid)
- throws InstallerException {
- if (!checkBeforeRemote()) return;
- BlockGuard.getVmPolicy().onPathAccess(targetApkPath);
- BlockGuard.getVmPolicy().onPathAccess(overlayApkPath);
- try {
- mInstalld.idmap(targetApkPath, overlayApkPath, uid);
- } catch (Exception e) {
- throw InstallerException.from(e);
- }
- }
-
- public void removeIdmap(String overlayApkPath) throws InstallerException {
- if (!checkBeforeRemote()) return;
- BlockGuard.getVmPolicy().onPathAccess(overlayApkPath);
- try {
- mInstalld.removeIdmap(overlayApkPath);
- } catch (Exception e) {
- throw InstallerException.from(e);
- }
- }
-
public void rmdex(String codePath, String instructionSet) throws InstallerException {
assertValidInstructionSet(instructionSet);
if (!checkBeforeRemote()) return;
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 532ff86e9014..00b525742332 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -113,18 +113,17 @@ public class StagingManager {
* Validates the signature used to sign the container of the new apex package
*
* @param newApexPkg The new apex package that is being installed
- * @param installFlags flags related to the session
* @throws PackageManagerException
*/
- private void validateApexSignature(PackageInfo newApexPkg, int installFlags)
+ private void validateApexSignature(PackageInfo newApexPkg)
throws PackageManagerException {
// Get signing details of the new package
final String apexPath = newApexPkg.applicationInfo.sourceDir;
final String packageName = newApexPkg.packageName;
- final SigningDetails signingDetails;
+ final SigningDetails newSigningDetails;
try {
- signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
+ newSigningDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
} catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + apexPath, e);
@@ -149,16 +148,10 @@ public class StagingManager {
}
// Verify signing details for upgrade
- if (signingDetails.checkCapability(existingSigningDetails,
- PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
- return;
- }
-
- // Verify signing details for downgrade
- // Allow downgrading from B to A iff it is possible to upgrade from A to B
- if (existingApexPkg.getLongVersionCode() > newApexPkg.getLongVersionCode()
- && existingSigningDetails.checkCapability(signingDetails,
- PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+ if (newSigningDetails.checkCapability(existingSigningDetails,
+ SigningDetails.CertCapabilities.INSTALLED_DATA)
+ || existingSigningDetails.checkCapability(newSigningDetails,
+ SigningDetails.CertCapabilities.ROLLBACK)) {
return;
}
@@ -896,8 +889,7 @@ public class StagingManager {
final List<PackageInfo> apexPackages =
submitSessionToApexService(session);
for (PackageInfo apexPackage : apexPackages) {
- validateApexSignature(
- apexPackage, session.params.installFlags);
+ validateApexSignature(apexPackage);
}
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8039724edf64..fcdb3b065ae6 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -185,7 +185,6 @@ import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
import static com.android.server.wm.AppWindowTokenProto.NAME;
import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.REMOVED;
import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
@@ -631,9 +630,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Last visibility state we reported to the app token.
boolean reportedVisible;
- // Set to true when the token has been removed from the window mgr.
- boolean removed;
-
boolean mDisablePreviewScreenshots;
// Information about an application starting window if displayed.
@@ -878,9 +874,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
pw.println(")");
}
- if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
+ if (mStartingData != null || firstWindowDrawn || mIsExiting) {
pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
- pw.print(" removed="); pw.print(removed);
pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
pw.print(" mIsExiting="); pw.println(mIsExiting);
}
@@ -1750,12 +1745,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (surface != null) {
boolean abort = false;
synchronized (mWmService.mGlobalLock) {
- // If the window was successfully added, then
- // we need to remove it.
- if (removed || mStartingData == null) {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
- "Aborted starting %s: removed=%b startingData=%s",
- ActivityRecord.this, removed, mStartingData);
+ // If the window was successfully added, then we need to remove it.
+ if (mStartingData == null) {
+ ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
+ ActivityRecord.this, mStartingData);
startingWindow = null;
mStartingData = null;
@@ -1798,7 +1791,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// task snapshot starting window.
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
}
- return snapshot == null ? STARTING_WINDOW_TYPE_NONE
+ return snapshot == null ? STARTING_WINDOW_TYPE_SPLASH_SCREEN
: snapshotOrientationSameAsTask(snapshot) || fromRecents
? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else {
@@ -2010,12 +2003,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
setMainWindowOpaque(occludesParent);
mWmService.mWindowPlacerLocked.requestTraversal();
- if (changed && task != null) {
- if (!occludesParent) {
- getActivityStack().convertActivityToTranslucent(this);
- }
- // Keep track of the number of fullscreen activities in this task.
- task.numFullscreen += occludesParent ? +1 : -1;
+ if (changed && task != null && !occludesParent) {
+ getActivityStack().convertActivityToTranslucent(this);
}
// Always ensure visibility if this activity doesn't occlude parent, so the
// {@link #returningOptions} of the activity under this one can be applied in
@@ -3040,7 +3029,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
removeIfPossible();
}
- removed = true;
stopFreezingScreen(true, true);
final DisplayContent dc = getDisplayContent();
@@ -4134,11 +4122,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
scheduleAnimation();
}
- @Override
- void onAppTransitionDone() {
- sendingToBottom = false;
- }
-
/**
* See {@link Activity#setDisablePreviewScreenshots}.
*/
@@ -6090,10 +6073,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return mOrientation;
}
- // The {@link ActivityRecord} should only specify an orientation when it is not closing or
- // going to the bottom. Allowing closing {@link ActivityRecord} to participate can lead to
- // an Activity in another task being started in the wrong orientation during the transition.
- if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
+ // The {@link ActivityRecord} should only specify an orientation when it is not closing.
+ // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
+ // task being started in the wrong orientation during the transition.
+ if (!getDisplayContent().mClosingApps.contains(this)
&& (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
return mOrientation;
}
@@ -7348,7 +7331,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
proto.write(ALL_DRAWN, allDrawn);
proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
- proto.write(REMOVED, removed);
if (startingWindow != null) {
startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 8385232b72d8..d7e6852cb78f 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2896,7 +2896,7 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
Task task = null;
if (!newTask) {
// If starting in an existing task, find where that is...
- boolean startIt = true;
+ boolean isOccluded = false;
for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
task = getChildAt(taskNdx);
if (task.getTopNonFinishingActivity() == null) {
@@ -2904,10 +2904,10 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
continue;
}
if (task == rTask) {
- // Here it is! Now, if this is not yet visible to the
- // user, then just add it without starting; it will
- // get started when the user navigates back to it.
- if (!startIt) {
+ // Here it is! Now, if this is not yet visible (occluded by another task) to
+ // the user, then just add it without starting; it will get started when the
+ // user navigates back to it.
+ if (isOccluded) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
rTask.positionChildAtTop(r);
@@ -2915,8 +2915,8 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
return;
}
break;
- } else if (task.numFullscreen > 0) {
- startIt = false;
+ } else if (!isOccluded) {
+ isOccluded = task.forAllActivities(ActivityRecord::occludesParent);
}
}
}
@@ -4670,9 +4670,6 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
}
positionChildAt(position, task, includingParents);
task.updateTaskMovement(toTop);
- if (getDisplayContent().mAppTransition.isTransitionSet()) {
- task.setSendingToBottom(!toTop);
- }
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
@@ -5214,9 +5211,6 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
child.updateTaskMovement(true);
final DisplayContent displayContent = getDisplayContent();
- if (displayContent.mAppTransition.isTransitionSet()) {
- child.setSendingToBottom(false);
- }
displayContent.layoutAndAssignWindowLayersIfNeeded();
}
@@ -5238,10 +5232,6 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
}
positionChildAt(POSITION_BOTTOM, child, includingParents);
-
- if (getDisplayContent().mAppTransition.isTransitionSet()) {
- child.setSendingToBottom(true);
- }
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
@@ -5284,9 +5274,6 @@ class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarg
task.updateTaskMovement(isTop);
if (isTop) {
final DisplayContent displayContent = getDisplayContent();
- if (displayContent.mAppTransition.isTransitionSet()) {
- task.setSendingToBottom(false);
- }
displayContent.layoutAndAssignWindowLayersIfNeeded();
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b4dd55de2dba..db41968a6c74 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -19,7 +19,6 @@ package com.android.server.wm;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -601,13 +600,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final ActivityRecord activity = w.mActivityRecord;
- // If this window's application has been removed, just skip it.
- if (activity!= null && (activity.removed || activity.sendingToBottom)) {
- ProtoLog.v(WM_DEBUG_FOCUS, "Skipping %s because %s", activity,
- (activity.removed ? "removed" : "sendingToBottom"));
- return false;
- }
-
if (focusedApp == null) {
ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
"findFocusedWindow: focusedApp=null using new focus @ %s", w);
@@ -865,7 +857,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
- mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
@@ -2045,7 +2037,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void updateSystemGestureExclusionLimit() {
- mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
updateSystemGestureExclusion();
}
@@ -4275,12 +4267,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
int getOrientation() {
- if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
- || isStackVisible(WINDOWING_MODE_FREEFORM)) {
+ if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
// Apps and their containers are not allowed to specify an orientation while the
- // docked or freeform stack is visible...except for the home stack if the docked
- // stack is minimized and it actually set something and the bounds is different from
- // the display.
+ // docked stack is visible...except for the home stack if the docked stack is
+ // minimized and it actually set something and the bounds is different from the
+ // display.
if (mHomeStack != null && mHomeStack.isVisible()
&& mDividerControllerLocked.isMinimizedDock()
&& !(mDividerControllerLocked.isHomeStackResizable()
@@ -5103,7 +5094,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* @return Whether gesture exclusion area should be logged for the given window
*/
static boolean logsGestureExclusionRestrictions(WindowState win) {
- if (win.mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
+ if (win.mWmService.mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
return false;
}
final WindowManager.LayoutParams attrs = win.getAttrs();
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index 8ae740d3101b..29b6bc479f72 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -27,9 +27,9 @@ import android.util.ArraySet;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
+import com.android.server.wm.utils.DeviceConfigInterface;
import java.io.PrintWriter;
-import java.util.concurrent.Executor;
/**
* A Blacklist for packages that should force the display out of high refresh rate.
@@ -41,26 +41,20 @@ class HighRefreshRateBlacklist {
private final String[] mDefaultBlacklist;
private final Object mLock = new Object();
+ private DeviceConfigInterface mDeviceConfig;
+ private OnPropertiesChangedListener mListener = new OnPropertiesChangedListener();
+
static HighRefreshRateBlacklist create(@NonNull Resources r) {
- return new HighRefreshRateBlacklist(r, new DeviceConfigInterface() {
- @Override
- public @Nullable String getProperty(@NonNull String namespace, @NonNull String name) {
- return DeviceConfig.getProperty(namespace, name);
- }
- public void addOnPropertiesChangedListener(@NonNull String namespace,
- @NonNull Executor executor,
- @NonNull DeviceConfig.OnPropertiesChangedListener listener) {
- DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
- }
- });
+ return new HighRefreshRateBlacklist(r, DeviceConfigInterface.REAL);
}
@VisibleForTesting
HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
- deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
- BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
- final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ mDeviceConfig = deviceConfig;
+ mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(), mListener);
+ final String property = mDeviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
KEY_HIGH_REFRESH_RATE_BLACKLIST);
updateBlacklist(property);
}
@@ -101,10 +95,12 @@ class HighRefreshRateBlacklist {
}
}
- interface DeviceConfigInterface {
- @Nullable String getProperty(@NonNull String namespace, @NonNull String name);
- void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
- @NonNull DeviceConfig.OnPropertiesChangedListener listener);
+ /** Used to prevent WmTests leaking issues. */
+ @VisibleForTesting
+ void dispose() {
+ mDeviceConfig.removeOnPropertiesChangedListener(mListener);
+ mDeviceConfig = null;
+ mBlacklistedPackages.clear();
}
private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 96bac88f0984..ba3b8b7d6787 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -252,8 +252,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
// was changed.
- int numFullscreen; // Number of fullscreen activities.
-
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
/** Can enter app pinning with user approval. Can never start over existing lockTask task. */
@@ -1210,9 +1208,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
r.inHistory = true;
- if (r.occludesParent()) {
- numFullscreen++;
- }
// Only set this based on the first activity
if (!hadChild) {
if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
@@ -1256,9 +1251,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
super.removeChild(r);
- if (r.occludesParent()) {
- numFullscreen--;
- }
if (r.isPersistable()) {
mAtmService.notifyTaskPersisterLocked(this, false);
}
@@ -2255,7 +2247,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
// We want to place all non-overlay activities below overlays.
while (maxPosition > 0) {
final ActivityRecord current = mChildren.get(maxPosition - 1);
- if (current.mTaskOverlay && !current.removed) {
+ if (current.mTaskOverlay) {
--maxPosition;
continue;
}
@@ -2266,17 +2258,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
}
- if (suggestedPosition >= maxPosition) {
- return Math.min(maxPosition, suggestedPosition);
- }
-
- for (int pos = 0; pos < maxPosition && pos < suggestedPosition; ++pos) {
- // TODO: Confirm that this is the behavior we want long term.
- if (mChildren.get(pos).removed) {
- // suggestedPosition assumes removed tokens are actually gone.
- ++suggestedPosition;
- }
- }
return Math.min(maxPosition, suggestedPosition);
}
@@ -2339,12 +2320,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
mPreserveNonFloatingState = stack.inPinnedWindowingMode();
}
- void setSendingToBottom(boolean toBottom) {
- for (int appTokenNdx = 0; appTokenNdx < mChildren.size(); appTokenNdx++) {
- mChildren.get(appTokenNdx).sendingToBottom = toBottom;
- }
- }
-
public int setBounds(Rect bounds, boolean forceResize) {
final int boundsChanged = setBounds(bounds);
@@ -2981,10 +2956,9 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
pw.print(prefix); pw.print("mActivityComponent=");
pw.println(realActivity.flattenToShortString());
}
- if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
+ if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
pw.print(" isPersistable="); pw.print(isPersistable);
- pw.print(" numFullscreen="); pw.print(numFullscreen);
pw.print(" activityType="); pw.println(getActivityType());
}
if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 9e55113c7705..d07516a6c86d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -19,11 +19,8 @@ package com.android.server.wm;
import android.annotation.Nullable;
import android.app.ActivityManager.TaskSnapshot;
import android.util.ArrayMap;
-import android.util.LruCache;
import java.io.PrintWriter;
-import java.util.Map;
-import java.util.Map.Entry;
/**
* Caches snapshots. See {@link TaskSnapshotController}.
@@ -42,6 +39,10 @@ class TaskSnapshotCache {
mLoader = loader;
}
+ void clearRunningCache() {
+ mRunningCache.clear();
+ }
+
void putSnapshot(Task task, TaskSnapshot snapshot) {
final CacheEntry entry = mRunningCache.get(task.mTaskId);
if (entry != null) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 35f61a88522b..f83ceb0bfc4e 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -214,6 +214,13 @@ class TaskSnapshotController {
}
/**
+ * @see WindowManagerInternal#clearSnapshotCache
+ */
+ public void clearSnapshotCache() {
+ mCache.clearRunningCache();
+ }
+
+ /**
* Creates a starting surface for {@param token} with {@param snapshot}. DO NOT HOLD THE WINDOW
* MANAGER LOCK WHEN CALLING THIS METHOD!
*/
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
new file mode 100644
index 000000000000..10c8ef0eaee8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
+import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
+
+import android.provider.AndroidDeviceConfig;
+import android.provider.DeviceConfig;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.utils.DeviceConfigInterface;
+
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+
+/**
+ * Settings constants that can modify the window manager's behavior.
+ */
+final class WindowManagerConstants {
+
+ /**
+ * The minimum duration between gesture exclusion logging for a given window in
+ * milliseconds.
+ *
+ * Events that happen in-between will be silently dropped.
+ *
+ * A non-positive value disables logging.
+ *
+ * <p>Note: On Devices running Q, this key is in the "android:window_manager" namespace.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ */
+ static final String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
+ "system_gesture_exclusion_log_debounce_millis";
+
+ private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
+
+ /** @see #KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS */
+ long mSystemGestureExclusionLogDebounceTimeoutMillis;
+ /** @see AndroidDeviceConfig#KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP */
+ int mSystemGestureExclusionLimitDp;
+ /** @see AndroidDeviceConfig#KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE */
+ boolean mSystemGestureExcludedByPreQStickyImmersive;
+
+ private final WindowManagerGlobalLock mGlobalLock;
+ private final Runnable mUpdateSystemGestureExclusionCallback;
+ private final DeviceConfigInterface mDeviceConfig;
+ private final DeviceConfig.OnPropertiesChangedListener mListenerAndroid;
+ private final DeviceConfig.OnPropertiesChangedListener mListenerWindowManager;
+
+ WindowManagerConstants(WindowManagerService service, DeviceConfigInterface deviceConfig) {
+ this(service.mGlobalLock, () -> service.mRoot.forAllDisplays(
+ DisplayContent::updateSystemGestureExclusionLimit), deviceConfig);
+ }
+
+ @VisibleForTesting
+ WindowManagerConstants(WindowManagerGlobalLock globalLock,
+ Runnable updateSystemGestureExclusionCallback,
+ DeviceConfigInterface deviceConfig) {
+ mGlobalLock = globalLock;
+ mUpdateSystemGestureExclusionCallback = updateSystemGestureExclusionCallback;
+ mDeviceConfig = deviceConfig;
+ mListenerAndroid = this::onAndroidPropertiesChanged;
+ mListenerWindowManager = this::onWindowPropertiesChanged;
+ }
+
+ void start(Executor executor) {
+ mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ANDROID, executor,
+ mListenerAndroid);
+ mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ executor, mListenerWindowManager);
+
+ updateSystemGestureExclusionLogDebounceMillis();
+ updateSystemGestureExclusionLimitDp();
+ updateSystemGestureExcludedByPreQStickyImmersive();
+ }
+
+ @VisibleForTesting
+ void dispose() {
+ mDeviceConfig.removeOnPropertiesChangedListener(mListenerAndroid);
+ mDeviceConfig.removeOnPropertiesChangedListener(mListenerWindowManager);
+ }
+
+ private void onAndroidPropertiesChanged(DeviceConfig.Properties properties) {
+ synchronized (mGlobalLock) {
+ boolean updateSystemGestureExclusionLimit = false;
+ for (String name : properties.getKeyset()) {
+ if (name == null) {
+ return;
+ }
+ switch (name) {
+ case KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP:
+ updateSystemGestureExclusionLimitDp();
+ updateSystemGestureExclusionLimit = true;
+ break;
+ case KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE:
+ updateSystemGestureExcludedByPreQStickyImmersive();
+ updateSystemGestureExclusionLimit = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (updateSystemGestureExclusionLimit) {
+ mUpdateSystemGestureExclusionCallback.run();
+ }
+ }
+ }
+
+ private void onWindowPropertiesChanged(DeviceConfig.Properties properties) {
+ synchronized (mGlobalLock) {
+ for (String name : properties.getKeyset()) {
+ if (name == null) {
+ return;
+ }
+ switch (name) {
+ case KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS:
+ updateSystemGestureExclusionLogDebounceMillis();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateSystemGestureExclusionLogDebounceMillis() {
+ mSystemGestureExclusionLogDebounceTimeoutMillis =
+ mDeviceConfig.getLong(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
+ }
+
+ private void updateSystemGestureExclusionLimitDp() {
+ mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ mDeviceConfig.getInt(DeviceConfig.NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ }
+
+ private void updateSystemGestureExcludedByPreQStickyImmersive() {
+ mSystemGestureExcludedByPreQStickyImmersive = mDeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("WINDOW MANAGER CONSTANTS (dumpsys window constants):");
+
+ pw.print(" "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS);
+ pw.print("="); pw.println(mSystemGestureExclusionLogDebounceTimeoutMillis);
+ pw.print(" "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP);
+ pw.print("="); pw.println(mSystemGestureExclusionLimitDp);
+ pw.print(" "); pw.print(KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE);
+ pw.print("="); pw.println(mSystemGestureExcludedByPreQStickyImmersive);
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index d2249724ae6e..46faf3b40f85 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -544,4 +544,10 @@ public abstract class WindowManagerInternal {
*/
public abstract @Nullable KeyInterceptionInfo
getKeyInterceptionInfoFromToken(IBinder inputToken);
+
+ /**
+ * Clears the snapshot cache of running activities so they show the splash-screen
+ * the next time the activities are opened.
+ */
+ public abstract void clearSnapshotCache();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 519cc2165cca..2d6d5f45e5fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -36,9 +36,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
-import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
-import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
@@ -188,7 +185,6 @@ import android.os.SystemService;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -280,6 +276,7 @@ import com.android.server.power.ShutdownThread;
import com.android.server.protolog.ProtoLogImpl;
import com.android.server.protolog.common.ProtoLog;
import com.android.server.utils.PriorityDump;
+import com.android.server.wm.utils.DeviceConfigInterface;
import java.io.BufferedWriter;
import java.io.DataInputStream;
@@ -411,7 +408,8 @@ public class WindowManagerService extends IWindowManager.Stub
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
- private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
+ final WindowManagerConstants mConstants = new WindowManagerConstants(this,
+ DeviceConfigInterface.REAL);
final WindowTracing mWindowTracing;
@@ -938,19 +936,6 @@ public class WindowManagerService extends IWindowManager.Stub
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
boolean mWindowsChanged = false;
- int mSystemGestureExclusionLimitDp;
- boolean mSystemGestureExcludedByPreQStickyImmersive;
-
- /**
- * The minimum duration between gesture exclusion logging for a given window in
- * milliseconds.
- *
- * Events that happen in-between will be silently dropped.
- *
- * A non-positive value disables logging.
- */
- public long mSystemGestureExclusionLogDebounceTimeoutMillis;
-
public interface WindowChangeListener {
public void windowsChanged();
public void focusChanged();
@@ -1054,9 +1039,6 @@ public class WindowManagerService extends IWindowManager.Stub
final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
- @VisibleForTesting
- final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener;
-
interface AppFreezeListener {
void onAppFreezeTimeout();
}
@@ -1261,38 +1243,7 @@ public class WindowManagerService extends IWindowManager.Stub
mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create(context.getResources());
- mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
- mSystemGestureExclusionLogDebounceTimeoutMillis =
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
- mSystemGestureExcludedByPreQStickyImmersive =
- DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
-
- mPropertiesChangedListener = properties -> {
- synchronized (mGlobalLock) {
- final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
- final boolean excludedByPreQSticky = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
- if (mSystemGestureExcludedByPreQStickyImmersive != excludedByPreQSticky
- || mSystemGestureExclusionLimitDp != exclusionLimitDp) {
- mSystemGestureExclusionLimitDp = exclusionLimitDp;
- mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
- mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
- }
-
- mSystemGestureExclusionLogDebounceTimeoutMillis =
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
- }
- };
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- new HandlerExecutor(mH), mPropertiesChangedListener);
+ mConstants.start(new HandlerExecutor(mH));
LocalServices.addService(WindowManagerInternal.class, new LocalService());
mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock);
@@ -1473,7 +1424,7 @@ public class WindowManagerService extends IWindowManager.Stub
ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
+ ".%s Aborting.", token);
return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
- } else if (activity.removed) {
+ } else if (activity.getParent() == null) {
ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
+ ".%s Aborting.", token);
return WindowManagerGlobal.ADD_APP_EXITING;
@@ -6199,6 +6150,9 @@ public class WindowManagerService extends IWindowManager.Stub
} else if ("refresh".equals(cmd)) {
dumpHighRefreshRateBlacklist(pw);
return;
+ } else if ("constants".equals(cmd)) {
+ mConstants.dump(pw);
+ return;
} else {
// Dumping a single name?
if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -6262,6 +6216,10 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println(separator);
}
dumpHighRefreshRateBlacklist(pw);
+ if (dumpAll) {
+ pw.println(separator);
+ }
+ mConstants.dump(pw);
}
}
@@ -6945,6 +6903,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
private final class LocalService extends WindowManagerInternal {
+
+ @Override
+ public void clearSnapshotCache() {
+ synchronized (mGlobalLock) {
+ mTaskSnapshotController.clearSnapshotCache();
+ }
+ }
+
@Override
public void requestTraversalFromDisplayManager() {
synchronized (mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index db0f3bc139bc..d41e70692eba 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -701,7 +701,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
final boolean immersiveSticky =
(mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags;
- return immersiveSticky && mWmService.mSystemGestureExcludedByPreQStickyImmersive
+ return immersiveSticky && mWmService.mConstants.mSystemGestureExcludedByPreQStickyImmersive
&& mActivityRecord != null && mActivityRecord.mTargetSdk < Build.VERSION_CODES.Q;
}
@@ -3040,7 +3040,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private void logExclusionRestrictions(int side) {
if (!logsGestureExclusionRestrictions(this)
|| SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side]
- + mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis) {
+ + mWmService.mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis) {
// Drop the log if we have just logged; this is okay, because what we would have logged
// was true only for a short duration.
return;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 88a1458a783f..057f4931dec1 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -82,10 +82,6 @@ class WindowToken extends WindowContainer<WindowState> {
// will be shown.
boolean waitingToShow;
- // Set to true when this token is in a pending transaction where its
- // windows will be put to the bottom of the list.
- boolean sendingToBottom;
-
/** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
final boolean mOwnerCanManageAppTokens;
@@ -298,9 +294,8 @@ class WindowToken extends WindowContainer<WindowState> {
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
pw.print(" hidden="); pw.print(mHidden);
pw.print(" hasVisible="); pw.println(hasVisible);
- if (waitingToShow || sendingToBottom) {
+ if (waitingToShow) {
pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
- pw.print(" sendingToBottom="); pw.print(sendingToBottom);
}
}
diff --git a/services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java b/services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java
new file mode 100644
index 000000000000..ab7e7f63cafd
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.provider.DeviceConfig;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Abstraction around {@link DeviceConfig} to allow faking device configuration in tests.
+ */
+public interface DeviceConfigInterface {
+ /**
+ * @see DeviceConfig#getProperty
+ */
+ @Nullable
+ String getProperty(@NonNull String namespace, @NonNull String name);
+
+ /**
+ * @see DeviceConfig#getString
+ */
+ @NonNull
+ String getString(@NonNull String namespace, @NonNull String name, @NonNull String defaultValue);
+
+ /**
+ * @see DeviceConfig#getInt
+ */
+ int getInt(@NonNull String namespace, @NonNull String name, int defaultValue);
+
+ /**
+ * @see DeviceConfig#getLong
+ */
+ long getLong(@NonNull String namespace, @NonNull String name, long defaultValue);
+
+ /**
+ * @see DeviceConfig#getBoolean
+ */
+ boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
+
+ /**
+ * @see DeviceConfig#addOnPropertiesChangedListener
+ */
+ void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
+ @NonNull DeviceConfig.OnPropertiesChangedListener listener);
+
+ /**
+ * @see DeviceConfig#removeOnPropertiesChangedListener
+ */
+ void removeOnPropertiesChangedListener(
+ @NonNull DeviceConfig.OnPropertiesChangedListener listener);
+
+ /**
+ * Calls through to the real {@link DeviceConfig}.
+ */
+ DeviceConfigInterface REAL = new DeviceConfigInterface() {
+ @Override
+ public String getProperty(String namespace, String name) {
+ return DeviceConfig.getProperty(namespace, name);
+ }
+
+ @Override
+ public String getString(String namespace, String name, String defaultValue) {
+ return DeviceConfig.getString(namespace, name, defaultValue);
+ }
+
+ @Override
+ public int getInt(String namespace, String name, int defaultValue) {
+ return DeviceConfig.getInt(namespace, name, defaultValue);
+ }
+
+ @Override
+ public long getLong(String namespace, String name, long defaultValue) {
+ return DeviceConfig.getLong(namespace, name, defaultValue);
+ }
+
+ @Override
+ public boolean getBoolean(@NonNull String namespace, @NonNull String name,
+ boolean defaultValue) {
+ return DeviceConfig.getBoolean(namespace, name, defaultValue);
+ }
+
+ @Override
+ public void addOnPropertiesChangedListener(String namespace, Executor executor,
+ DeviceConfig.OnPropertiesChangedListener listener) {
+ DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
+ }
+
+ @Override
+ public void removeOnPropertiesChangedListener(
+ DeviceConfig.OnPropertiesChangedListener listener) {
+ DeviceConfig.removeOnPropertiesChangedListener(listener);
+ }
+ };
+}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 425b4b632971..dd2b27ddeef4 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -141,7 +141,6 @@ cc_defaults {
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
"android.hardware.vibrator@1.3",
- "android.hardware.vibrator@1.4",
"android.hardware.vr@1.0",
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 372622801aa0..746610df11ae 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "VibratorService"
-#include <android/hardware/vibrator/1.4/IVibrator.h>
+#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <binder/IServiceManager.h>
@@ -43,166 +43,41 @@ namespace V1_0 = android::hardware::vibrator::V1_0;
namespace V1_1 = android::hardware::vibrator::V1_1;
namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;
-namespace V1_4 = android::hardware::vibrator::V1_4;
namespace aidl = android::hardware::vibrator;
namespace android {
static jmethodID sMethodIdOnComplete;
-// TODO(b/141828236): remove HIDL 1.4 and re-write all of this code to remove
-// shim
-class VibratorShim : public V1_4::IVibrator {
- public:
- VibratorShim(const sp<aidl::IVibrator>& vib) : mVib(vib) {}
-
- Return<V1_0::Status> on(uint32_t timeoutMs) override {
- return on_1_4(timeoutMs, nullptr);
- }
-
- Return<V1_0::Status> off() override {
- return toHidlStatus(mVib->off());
- }
-
- Return<bool> supportsAmplitudeControl() override {
- int32_t cap = 0;
- if (!mVib->getCapabilities(&cap).isOk()) return false;
- if (mUnderExternalControl) {
- return (cap & aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
- } else {
- return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0;
- }
- }
-
- Return<V1_0::Status> setAmplitude(uint8_t amplitude) override {
- return toHidlStatus(mVib->setAmplitude(amplitude));
- }
-
- Return<void> perform(V1_0::Effect effect, V1_0::EffectStrength strength,
- perform_cb _hidl_cb) override {
- return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
- }
-
- Return<void> perform_1_1(V1_1::Effect_1_1 effect, V1_0::EffectStrength strength,
- perform_1_1_cb _hidl_cb) override {
- return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
- }
-
- Return<void> perform_1_2(V1_2::Effect effect, V1_0::EffectStrength strength,
- perform_1_2_cb _hidl_cb) override {
- return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
- }
-
- Return<bool> supportsExternalControl() override {
- int32_t cap = 0;
- if (!mVib->getCapabilities(&cap).isOk()) return false;
- return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0;
- }
-
- Return<V1_0::Status> setExternalControl(bool enabled) override {
- Return<V1_0::Status> status = toHidlStatus(mVib->setExternalControl(enabled));
- if (status.isOk() && status == V1_0::Status::OK) {
- mUnderExternalControl = enabled;
- }
- return status;
- }
-
- Return<void> perform_1_3(V1_3::Effect effect, V1_0::EffectStrength strength,
- perform_1_3_cb _hidl_cb) override {
- return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
- }
-
- Return<uint32_t> getCapabilities() override {
- static_assert(static_cast<int32_t>(V1_4::Capabilities::ON_COMPLETION_CALLBACK) ==
- static_cast<int32_t>(aidl::IVibrator::CAP_ON_CALLBACK));
- static_assert(static_cast<int32_t>(V1_4::Capabilities::PERFORM_COMPLETION_CALLBACK) ==
- static_cast<int32_t>(aidl::IVibrator::CAP_PERFORM_CALLBACK));
-
- int32_t cap;
- if (!mVib->getCapabilities(&cap).isOk()) return 0;
- return (cap & (aidl::IVibrator::CAP_ON_CALLBACK |
- aidl::IVibrator::CAP_PERFORM_CALLBACK)) > 0;
- }
-
- Return<V1_0::Status> on_1_4(uint32_t timeoutMs,
- const sp<V1_4::IVibratorCallback>& callback) override {
- sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr;
- return toHidlStatus(mVib->on(timeoutMs, cb));
- }
-
- Return<void> perform_1_4(V1_3::Effect effect, V1_0::EffectStrength strength,
- const sp<V1_4::IVibratorCallback>& callback,
- perform_1_4_cb _hidl_cb) override {
- static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
- static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
- static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
- static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
- static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
- static_cast<uint8_t>(aidl::EffectStrength::STRONG));
- static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
- static_cast<uint8_t>(aidl::Effect::CLICK));
- static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
- static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
- static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) ==
- static_cast<uint8_t>(aidl::Effect::TICK));
- static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) ==
- static_cast<uint8_t>(aidl::Effect::THUD));
- static_assert(static_cast<uint8_t>(V1_3::Effect::POP) ==
- static_cast<uint8_t>(aidl::Effect::POP));
- static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
- static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
- static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
- static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
- static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
- static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
- static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
- static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
- static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
- static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
-
- sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr;
- int timeoutMs = 0;
- Return<V1_0::Status> status = toHidlStatus(
- mVib->perform(static_cast<aidl::Effect>(effect),
- static_cast<aidl::EffectStrength>(strength), cb, &timeoutMs));
-
- if (status.isOk()) {
- _hidl_cb(status, timeoutMs);
- return android::hardware::Status::ok();
- } else {
- return android::hardware::details::StatusOf<V1_0::Status, void>(status);
- }
- }
- private:
- sp<aidl::IVibrator> mVib;
- bool mUnderExternalControl = false;
-
- Return<V1_0::Status> toHidlStatus(const android::binder::Status& status) {
- switch(status.exceptionCode()) {
- using android::hardware::Status;
- case Status::EX_NONE: return V1_0::Status::OK;
- case Status::EX_ILLEGAL_ARGUMENT: return V1_0::Status::BAD_VALUE;
- case Status::EX_UNSUPPORTED_OPERATION: return V1_0::Status::UNSUPPORTED_OPERATION;
- case Status::EX_TRANSACTION_FAILED: {
- return Status::fromStatusT(status.transactionError());
- }
- }
- return V1_0::Status::UNKNOWN_ERROR;
- }
-
- class CallbackShim : public aidl::BnVibratorCallback {
- public:
- CallbackShim(const sp<V1_4::IVibratorCallback>& cb) : mCb(cb) {}
- binder::Status onComplete() {
- mCb->onComplete();
- return binder::Status::ok(); // oneway, local call
- }
- private:
- sp<V1_4::IVibratorCallback> mCb;
- };
-};
-
-class VibratorCallback : public V1_4::IVibratorCallback {
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
+ static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
+ static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
+ static_cast<uint8_t>(aidl::EffectStrength::STRONG));
+
+static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) ==
+ static_cast<uint8_t>(aidl::Effect::TICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) ==
+ static_cast<uint8_t>(aidl::Effect::THUD));
+static_assert(static_cast<uint8_t>(V1_3::Effect::POP) ==
+ static_cast<uint8_t>(aidl::Effect::POP));
+static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
+ static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
+
+class VibratorCallback {
public:
VibratorCallback(JNIEnv *env, jobject vibration) :
mVibration(MakeGlobalRefOrDie(env, vibration)) {}
@@ -212,47 +87,92 @@ class VibratorCallback : public V1_4::IVibratorCallback {
env->DeleteGlobalRef(mVibration);
}
- Return<void> onComplete() override {
+ void onComplete() {
auto env = AndroidRuntime::getJNIEnv();
env->CallVoidMethod(mVibration, sMethodIdOnComplete);
- return Void();
}
private:
jobject mVibration;
};
+class AidlVibratorCallback : public aidl::BnVibratorCallback {
+ public:
+ AidlVibratorCallback(JNIEnv *env, jobject vibration) :
+ mCb(env, vibration) {}
+
+ binder::Status onComplete() override {
+ mCb.onComplete();
+ return binder::Status::ok(); // oneway, local call
+ }
+
+ private:
+ VibratorCallback mCb;
+};
+
static constexpr int NUM_TRIES = 2;
+template<class R>
+inline R NoneStatus() {
+ using ::android::hardware::Status;
+ return Status::fromExceptionCode(Status::EX_NONE);
+}
+
+template<>
+inline binder::Status NoneStatus() {
+ using binder::Status;
+ return Status::fromExceptionCode(Status::EX_NONE);
+}
+
// Creates a Return<R> with STATUS::EX_NULL_POINTER.
template<class R>
-inline Return<R> NullptrStatus() {
+inline R NullptrStatus() {
using ::android::hardware::Status;
- return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template<>
+inline binder::Status NullptrStatus() {
+ using binder::Status;
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template <typename I>
+sp<I> getService() {
+ return I::getService();
+}
+
+template <>
+sp<aidl::IVibrator> getService() {
+ return waitForVintfService<aidl::IVibrator>();
+}
+
+template <typename I>
+sp<I> tryGetService() {
+ return I::tryGetService();
+}
+
+template <>
+sp<aidl::IVibrator> tryGetService() {
+ return checkVintfService<aidl::IVibrator>();
}
template <typename I>
class HalWrapper {
public:
static std::unique_ptr<HalWrapper> Create() {
- sp<aidl::IVibrator> aidlVib = waitForVintfService<aidl::IVibrator>();
- if (aidlVib) {
- return std::unique_ptr<HalWrapper>(new HalWrapper(new VibratorShim(aidlVib)));
- }
-
// Assume that if getService returns a nullptr, HAL is not available on the
// device.
- auto hal = I::getService();
+ auto hal = getService<I>();
return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
}
// Helper used to transparently deal with the vibrator HAL becoming unavailable.
template<class R, class... Args0, class... Args1>
- Return<R> call(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
+ R call(R (I::* fn)(Args0...), Args1&&... args1) {
// Return<R> doesn't have a default constructor, so make a Return<R> with
// STATUS::EX_NONE.
- using ::android::hardware::Status;
- Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)};
+ R ret{NoneStatus<R>()};
// Note that ret is guaranteed to be changed after this loop.
for (int i = 0; i < NUM_TRIES; ++i) {
@@ -266,12 +186,7 @@ class HalWrapper {
ALOGE("Failed to issue command to vibrator HAL. Retrying.");
// Restoring connection to the HAL.
- sp<aidl::IVibrator> aidlVib = checkVintfService<aidl::IVibrator>();
- if (aidlVib) {
- mHal = new VibratorShim(aidlVib);
- } else {
- mHal = I::tryGetService();
- }
+ mHal = tryGetService<I>();
}
return ret;
}
@@ -290,7 +205,7 @@ static auto getHal() {
}
template<class R, class I, class... Args0, class... Args1>
-Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
+R halCall(R (I::* fn)(Args0...), Args1&&... args1) {
auto hal = getHal<I>();
return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
}
@@ -307,110 +222,192 @@ bool isValidEffect(jlong effect) {
static void vibratorInit(JNIEnv *env, jclass clazz)
{
- halCall(&V1_0::IVibrator::ping).isOk();
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ // IBinder::pingBinder isn't accessible as a pointer function
+ // but getCapabilities can serve the same purpose
+ int32_t cap;
+ hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
+ } else {
+ halCall(&V1_0::IVibrator::ping).isOk();
+ }
}
static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */)
{
- return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
+ bool ok;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ // IBinder::pingBinder isn't accessible as a pointer function
+ // but getCapabilities can serve the same purpose
+ int32_t cap;
+ ok = hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
+ } else {
+ ok = halCall(&V1_0::IVibrator::ping).isOk();
+ }
+ return ok ? JNI_TRUE : JNI_FALSE;
}
static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms)
{
- Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
- if (retStatus != Status::OK) {
- ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::on, timeout_ms, nullptr);
+ if (!status.isOk()) {
+ ALOGE("vibratorOn command failed: %s", status.toString8().string());
+ }
+ } else {
+ Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
+ if (retStatus != Status::OK) {
+ ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
+ }
}
}
static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */)
{
- Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
- if (retStatus != Status::OK) {
- ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::off);
+ if (!status.isOk()) {
+ ALOGE("vibratorOff command failed: %s", status.toString8().string());
+ }
+ } else {
+ Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
+ if (retStatus != Status::OK) {
+ ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
+ }
}
}
static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) {
- return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ int32_t cap = 0;
+ if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
+ return false;
+ }
+ return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0;
+ } else {
+ return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
+ }
}
static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
- Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
- .withDefault(Status::UNKNOWN_ERROR);
- if (status != Status::OK) {
- ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
- static_cast<uint32_t>(status));
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, amplitude);
+ if (!status.isOk()) {
+ ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string());
+ }
+ } else {
+ Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
+ .withDefault(Status::UNKNOWN_ERROR);
+ if (status != Status::OK) {
+ ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
+ static_cast<uint32_t>(status));
+ }
}
}
static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) {
- return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ int32_t cap = 0;
+ if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
+ return false;
+ }
+ return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0;
+ } else {
+ return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
+ }
}
static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) {
- Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
- .withDefault(Status::UNKNOWN_ERROR);
- if (status != Status::OK) {
- ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
- static_cast<uint32_t>(status));
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::IVibrator::setExternalControl, enabled);
+ if (!status.isOk()) {
+ ALOGE("Failed to set vibrator external control: %s", status.toString8().string());
+ }
+ } else {
+ Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
+ .withDefault(Status::UNKNOWN_ERROR);
+ if (status != Status::OK) {
+ ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
+ static_cast<uint32_t>(status));
+ }
}
}
static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength,
jobject vibration) {
- Status status;
- uint32_t lengthMs;
- auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
- status = retStatus;
- lengthMs = retLengthMs;
- };
- EffectStrength effectStrength(static_cast<EffectStrength>(strength));
-
- Return<void> ret;
- if (auto hal = getHal<V1_4::IVibrator>(); hal && isValidEffect<V1_3::Effect>(effect)) {
- sp<VibratorCallback> effectCallback = new VibratorCallback(env, vibration);
- ret = hal->call(&V1_4::IVibrator::perform_1_4, static_cast<V1_3::Effect>(effect),
- effectStrength, effectCallback, callback);
- } else if (isValidEffect<V1_0::Effect>(effect)) {
- ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
- effectStrength, callback);
- } else if (isValidEffect<Effect_1_1>(effect)) {
- ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
- effectStrength, callback);
- } else if (isValidEffect<V1_2::Effect>(effect)) {
- ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
- effectStrength, callback);
- } else if (isValidEffect<V1_3::Effect>(effect)) {
- ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
- effectStrength, callback);
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ int32_t lengthMs;
+ sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
+ aidl::Effect effectType(static_cast<aidl::Effect>(strength));
+ aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength));
+
+ auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs);
+ if (!status.isOk()) {
+ if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
+ ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
+ ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string());
+ }
+ return -1;
+ }
+ return lengthMs;
} else {
- ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
- static_cast<int32_t>(effect));
- return -1;
- }
+ Status status;
+ uint32_t lengthMs;
+ auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
+ status = retStatus;
+ lengthMs = retLengthMs;
+ };
+ EffectStrength effectStrength(static_cast<EffectStrength>(strength));
+
+ Return<void> ret;
+ if (isValidEffect<V1_0::Effect>(effect)) {
+ ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
+ effectStrength, callback);
+ } else if (isValidEffect<Effect_1_1>(effect)) {
+ ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
+ effectStrength, callback);
+ } else if (isValidEffect<V1_2::Effect>(effect)) {
+ ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
+ effectStrength, callback);
+ } else if (isValidEffect<V1_3::Effect>(effect)) {
+ ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
+ effectStrength, callback);
+ } else {
+ ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
+ static_cast<int32_t>(effect));
+ return -1;
+ }
- if (!ret.isOk()) {
- ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
- return -1;
- }
+ if (!ret.isOk()) {
+ ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
+ return -1;
+ }
- if (status == Status::OK) {
- return lengthMs;
- } else if (status != Status::UNSUPPORTED_OPERATION) {
- // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
- // doesn't have a pre-defined waveform to perform for it, so we should just give the
- // opportunity to fall back to the framework waveforms.
- ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
- ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
- static_cast<int32_t>(strength), static_cast<uint32_t>(status));
+ if (status == Status::OK) {
+ return lengthMs;
+ } else if (status != Status::UNSUPPORTED_OPERATION) {
+ // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
+ // doesn't have a pre-defined waveform to perform for it, so we should just give the
+ // opportunity to fall back to the framework waveforms.
+ ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
+ ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
+ static_cast<int32_t>(strength), static_cast<uint32_t>(status));
+ }
}
return -1;
}
static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
- return halCall(&V1_4::IVibrator::getCapabilities).withDefault(0);
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ int32_t cap = 0;
+ if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
+ return 0;
+ }
+ return cap;
+ }
+
+ return 0;
}
static const JNINativeMethod method_table[] = {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 21bdc43d0d58..3bc28383cf29 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -698,12 +698,6 @@ Return<void> GnssCallback::gnssSvStatusCbImpl(const T& svStatus) {
JNIEnv* env = getJniEnv();
uint32_t listSize = getGnssSvInfoListSize(svStatus);
- if (listSize > static_cast<uint32_t>(
- android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
- ALOGD("Too many satellites %u. Clamps to %u.", listSize,
- static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT));
- listSize = static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT);
- }
jintArray svidWithFlagArray = env->NewIntArray(listSize);
jfloatArray cn0Array = env->NewFloatArray(listSize);
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 69e24063210d..865e3b8cc109 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -103,7 +103,7 @@ public class NetworkStackClient {
// checks here should be kept in sync with PermissionUtil.
if (caller != Process.SYSTEM_UID
&& caller != Process.NETWORK_STACK_UID
- && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+ && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
throw new SecurityException(
"Only the system server should try to bind to the network stack.");
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
index 975689db5264..be6a31fa949e 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
@@ -32,24 +32,28 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@RunWith(JUnit4.class)
public class RuleXmlParserTest {
@Test
public void testXmlStream_validOpenFormula() throws Exception {
+ Map<String, String> atomicFormulaAttrs = new HashMap<>();
+ atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ atomicFormulaAttrs.put("V", "com.app.test");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -65,17 +69,19 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validOpenFormula_notConnector() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -90,22 +96,24 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validOpenFormula_andConnector() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
+ Map<String, String> appCertificateAttrs = new HashMap<>();
+ appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ appCertificateAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ appCertificateAttrs.put("V", "test_cert");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.AND + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<AF>"
- + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>test_cert</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -121,22 +129,24 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validOpenFormula_orConnector() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
+ Map<String, String> appCertificateAttrs = new HashMap<>();
+ appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ appCertificateAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ appCertificateAttrs.put("V", "test_cert");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.OR + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<AF>"
- + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>test_cert</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.OR)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -152,17 +162,19 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validOpenFormula_differentTagOrder() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<C>" + OpenFormula.NOT + "</C>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -177,22 +189,24 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
+ Map<String, String> versionCodeAttrs = new HashMap<>();
+ versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
+ versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ versionCodeAttrs.put("V", "1");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<AF>"
- + "<K>" + AtomicFormula.VERSION_CODE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>1</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -205,17 +219,19 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_invalidOpenFormula_invalidOperator() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", "INVALID_OPERATOR");
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>INVALID_OPERATOR</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -228,17 +244,19 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_invalidOpenFormula_invalidEffect() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", "INVALID_EFFECT"),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>INVALID_EFFECT</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -251,37 +269,41 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_invalidOpenFormula_invalidTags() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlOpenFormula = "<RL>"
- + "<R>"
- + "<OF>"
- + "<InvalidConnector>" + OpenFormula.NOT + "</InvalidConnector>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "InvalidAtomicFormula",
+ packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
- /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidConnector",
+ /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidAtomicFormula",
() -> xmlParser.parse(ruleXmlOpenFormula));
}
@Test
public void testXmlString_validAtomicFormula_stringValue() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -296,14 +318,15 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validAtomicFormula_integerValue() throws Exception {
+ Map<String, String> versionCodeAttrs = new HashMap<>();
+ versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
+ versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ versionCodeAttrs.put("V", "1");
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.VERSION_CODE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>1</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -318,14 +341,15 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_validAtomicFormula_booleanValue() throws Exception {
+ Map<String, String> preInstalledAttrs = new HashMap<>();
+ preInstalledAttrs.put("K", String.valueOf(AtomicFormula.PRE_INSTALLED));
+ preInstalledAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ preInstalledAttrs.put("V", "true");
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.PRE_INSTALLED + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>true</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -339,15 +363,16 @@ public class RuleXmlParserTest {
}
@Test
- public void testXmlString_validAtomicFormula_differentTagOrder() throws Exception {
+ public void testXmlString_validAtomicFormula_differentAttributeOrder() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -361,35 +386,37 @@ public class RuleXmlParserTest {
}
@Test
- public void testXmlString_invalidAtomicFormula_invalidTags() throws Exception {
+ public void testXmlString_invalidAtomicFormula_invalidAttribute() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("BadKey", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<BadKey>" + AtomicFormula.PACKAGE_NAME + "</BadKey>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
- /* expectedExceptionMessageRegex */ "Found unexpected tag: BadKey",
+ /* expectedExceptionMessageRegex */ "Attribute not found: K",
() -> xmlParser.parse(ruleXmlAtomicFormula));
}
@Test
public void testXmlString_invalidAtomicFormula() throws Exception {
+ Map<String, String> packageNameAttrs = new HashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
+ packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ packageNameAttrs.put("V", "com.app.test");
String ruleXmlAtomicFormula = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.VERSION_CODE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -402,16 +429,18 @@ public class RuleXmlParserTest {
@Test
public void testXmlString_withNoRuleList() {
- String ruleXmlWithNoRuleList = "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ Map<String, String> atomicFormulaAttrs = new HashMap<>();
+ atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ atomicFormulaAttrs.put("V", "com.app.test");
+ String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>";
RuleParser xmlParser = new RuleXmlParser();
@@ -423,16 +452,18 @@ public class RuleXmlParserTest {
@Test
public void testXmlStream_withNoRuleList() {
- String ruleXmlWithNoRuleList = "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ Map<String, String> atomicFormulaAttrs = new HashMap<>();
+ atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ atomicFormulaAttrs.put("V", "com.app.test");
+ String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>";
InputStream inputStream = new ByteArrayInputStream(ruleXmlWithNoRuleList.getBytes());
RuleParser xmlParser = new RuleXmlParser();
@@ -442,4 +473,19 @@ public class RuleXmlParserTest {
/* expectedExceptionMessageRegex */ "Rules must start with RuleList <RL> tag",
() -> xmlParser.parse(inputStream));
}
+
+ private String generateTagWithAttribute(String tag, Map<String, String> attributeValues,
+ boolean closed) {
+ StringBuilder res = new StringBuilder("<");
+ res.append(tag);
+ for (String attribute : attributeValues.keySet()) {
+ res.append(" ");
+ res.append(attribute);
+ res.append("=\"");
+ res.append(attributeValues.get(attribute));
+ res.append("\"");
+ }
+ res.append(closed ? " />" : ">");
+ return res.toString();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index 082fda82499a..a25627155950 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -36,6 +36,8 @@ import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
@RunWith(JUnit4.class)
public class RuleXmlSerializerTest {
@@ -58,13 +60,14 @@ public class RuleXmlSerializerTest {
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"),
Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
String expectedRules = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
@@ -81,16 +84,18 @@ public class RuleXmlSerializerTest {
"com.app.test"))), Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
OutputStream outputStream = new ByteArrayOutputStream();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
String expectedRules = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
@@ -107,16 +112,18 @@ public class RuleXmlSerializerTest {
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
"com.app.test"))), Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
String expectedRules = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.NOT + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
@@ -133,20 +140,22 @@ public class RuleXmlSerializerTest {
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE,
"test_cert"))), Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
+ Map<String, String> appCertificateAttrs = new LinkedHashMap<>();
+ appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ appCertificateAttrs.put("V", "test_cert");
String expectedRules = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.AND + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<AF>"
- + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
- + "<V>test_cert</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
@@ -163,20 +172,22 @@ public class RuleXmlSerializerTest {
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE,
"test_cert"))), Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
+ Map<String, String> appCertificateAttrs = new LinkedHashMap<>();
+ appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ appCertificateAttrs.put("V", "test_cert");
String expectedRules = "<RL>"
- + "<R>"
- + "<OF>"
- + "<C>" + OpenFormula.OR + "</C>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<AF>"
- + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
- + "<V>test_cert</V>"
- + "</AF>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(OpenFormula.OR)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
- + "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
@@ -191,13 +202,14 @@ public class RuleXmlSerializerTest {
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"),
Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", "com.app.test");
String expectedRules = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
- + "<V>com.app.test</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
@@ -212,14 +224,15 @@ public class RuleXmlSerializerTest {
new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> versionCodeAttrs = new LinkedHashMap<>();
+ versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
+ versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ));
+ versionCodeAttrs.put("V", "1");
String expectedRules = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.VERSION_CODE + "</K>"
- + "<O>" + AtomicFormula.EQ + "</O>"
- + "<V>1</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
@@ -234,13 +247,14 @@ public class RuleXmlSerializerTest {
new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
+ Map<String, String> preInstalledAttrs = new LinkedHashMap<>();
+ preInstalledAttrs.put("K", String.valueOf(AtomicFormula.PRE_INSTALLED));
+ preInstalledAttrs.put("V", "true");
String expectedRules = "<RL>"
- + "<R>"
- + "<AF>"
- + "<K>" + AtomicFormula.PRE_INSTALLED + "</K>"
- + "<V>true</V>"
- + "</AF>"
- + "<E>" + Rule.DENY + "</E>"
+ + generateTagWithAttribute(/* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(/* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
@@ -261,6 +275,21 @@ public class RuleXmlSerializerTest {
() -> xmlSerializer.serialize(Collections.singletonList(rule)));
}
+ private String generateTagWithAttribute(String tag, Map<String, String> attributeValues,
+ boolean closed) {
+ StringBuilder res = new StringBuilder("<");
+ res.append(tag);
+ for (String attribute : attributeValues.keySet()) {
+ res.append(" ");
+ res.append(attribute);
+ res.append("=\"");
+ res.append(attributeValues.get(attribute));
+ res.append("\"");
+ }
+ res.append(closed ? " />" : ">");
+ return res.toString();
+ }
+
private Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
new file mode 100644
index 000000000000..03c10f3a86f8
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 20019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.IUiModeManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.wm.WindowManagerInternal;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static android.app.UiModeManager.MODE_NIGHT_AUTO;
+import static android.app.UiModeManager.MODE_NIGHT_NO;
+import static android.app.UiModeManager.MODE_NIGHT_YES;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class UiModeManagerServiceTest extends UiServiceTestCase {
+ private UiModeManagerService mUiManagerService;
+ private IUiModeManager mService;
+ @Mock
+ private ContentResolver mContentResolver;
+ @Mock
+ private WindowManagerInternal mWindowManager;
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ TwilightManager mTwilightManager;
+ @Mock
+ PowerManager.WakeLock mWakeLock;
+ private Set<BroadcastReceiver> mScreenOffRecievers;
+
+ @Before
+ public void setUp() {
+ mUiManagerService = new UiModeManagerService(mContext, mWindowManager, mWakeLock,
+ mTwilightManager, true);
+ mScreenOffRecievers = new HashSet<>();
+ mService = mUiManagerService.getService();
+ when(mContext.checkCallingOrSelfPermission(anyString()))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.registerReceiver(any(), any())).then(inv -> {
+ mScreenOffRecievers.add(inv.getArgument(0));
+ return null;
+ });
+ }
+
+ @Test
+ public void setAutoMode_screenOffRegistered() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_NO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ mService.setNightMode(MODE_NIGHT_AUTO);
+ verify(mContext).registerReceiver(any(BroadcastReceiver.class), any());
+ }
+
+ @Test
+ public void setAutoMode_screenOffUnRegistered() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_AUTO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ try {
+ mService.setNightMode(MODE_NIGHT_NO);
+ } catch (SecurityException e) { /*we should ignore this update config exception*/ }
+ given(mContext.registerReceiver(any(), any())).willThrow(SecurityException.class);
+ verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
+ }
+
+ @Test
+ public void setAutoMode_clearCache() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_AUTO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ try {
+ mService.setNightMode(MODE_NIGHT_NO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ verify(mWindowManager).clearSnapshotCache();
+ }
+
+ @Test
+ public void setNightModeActive_fromNightModeYesToNoWhenFalse() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_YES);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ try {
+ mService.setNightModeActivated(false);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ assertEquals(MODE_NIGHT_NO, mService.getNightMode());
+ }
+
+ @Test
+ public void setNightModeActive_fromNightModeNoToYesWhenTrue() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_NO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ try {
+ mService.setNightModeActivated(true);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ assertEquals(MODE_NIGHT_YES, mService.getNightMode());
+ }
+
+ @Test
+ public void setNightModeActive_autoNightModeNoChanges() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_AUTO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ try {
+ mService.setNightModeActivated(true);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ assertEquals(MODE_NIGHT_AUTO, mService.getNightMode());
+ }
+
+ @Test
+ public void isNightModeActive_nightModeYes() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_YES);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ assertTrue(isNightModeActivated());
+ }
+
+ @Test
+ public void isNightModeActive_nightModeNo() throws RemoteException {
+ try {
+ mService.setNightMode(MODE_NIGHT_NO);
+ } catch (SecurityException e) { /* we should ignore this update config exception*/ }
+ assertFalse(isNightModeActivated());
+ }
+
+ private boolean isNightModeActivated() {
+ return (mUiManagerService.getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_YES) != 0;
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index bd336ad2494f..1c150969144a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -262,7 +262,6 @@ public class AppWindowTokenTests extends WindowTestsBase {
mActivity.setOccludesParent(true);
mActivity.setHidden(true);
- mActivity.sendingToBottom = true;
// Can not specify orientation if app isn't visible even though it occludes parent.
assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
// Can specify orientation if the current orientation candidate is orientation behind.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 571f214564a0..466dc9bd0088 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -700,6 +701,37 @@ public class DisplayContentTests extends WindowTestsBase {
}
@Test
+ public void testAllowsTopmostFullscreenOrientation() {
+ final DisplayContent dc = createNewDisplay();
+ dc.getDisplayRotation().setFixedToUserRotation(
+ DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED);
+
+ final ActivityStack stack =
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ .setDisplay(dc.mActivityDisplay)
+ .build();
+ doReturn(true).when(stack).isVisible();
+
+ final ActivityStack freeformStack =
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ .setDisplay(dc.mActivityDisplay)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
+ .build();
+ doReturn(true).when(freeformStack).isVisible();
+ freeformStack.getTopChild().setBounds(100, 100, 300, 400);
+
+ assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
+
+ freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
+
+ stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
+ }
+
+ @Test
public void testOnDescendantOrientationRequestChanged() {
final DisplayContent dc = createNewDisplay();
dc.getDisplayRotation().setFixedToUserRotation(
@@ -872,7 +904,7 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testCalculateSystemGestureExclusion_immersiveStickyLegacyWindow() throws Exception {
- mWm.mSystemGestureExcludedByPreQStickyImmersive = true;
+ mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
final DisplayContent dc = createNewDisplay();
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index fa83f85345f0..5fb6f45b400e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -20,28 +20,23 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFR
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
-import android.util.Pair;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
-import com.android.server.wm.HighRefreshRateBlacklist.DeviceConfigInterface;
+import com.android.internal.util.Preconditions;
+import com.android.server.wm.utils.FakeDeviceConfigInterface;
+import org.junit.After;
import org.junit.Test;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
/**
* Build/Install/Run:
@@ -50,67 +45,79 @@ import java.util.concurrent.TimeUnit;
@SmallTest
@Presubmit
public class HighRefreshRateBlacklistTest {
+ private static final String APP1 = "com.android.sample1";
+ private static final String APP2 = "com.android.sample2";
+ private static final String APP3 = "com.android.sample3";
+
+ private HighRefreshRateBlacklist mBlacklist;
+
+ @After
+ public void tearDown() {
+ mBlacklist.dispose();
+ }
@Test
public void testDefaultBlacklist() {
- final Resources r = createResources("com.android.sample1", "com.android.sample2");
- HighRefreshRateBlacklist blacklist =
- new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
- assertTrue(blacklist.isBlacklisted("com.android.sample1"));
- assertTrue(blacklist.isBlacklisted("com.android.sample2"));
- assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+ final Resources r = createResources(APP1, APP2);
+ mBlacklist = new HighRefreshRateBlacklist(r, new FakeDeviceConfig());
+
+ assertTrue(mBlacklist.isBlacklisted(APP1));
+ assertTrue(mBlacklist.isBlacklisted(APP2));
+ assertFalse(mBlacklist.isBlacklisted(APP3));
}
@Test
public void testNoDefaultBlacklist() {
final Resources r = createResources();
- HighRefreshRateBlacklist blacklist =
- new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
- assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ mBlacklist = new HighRefreshRateBlacklist(r, new FakeDeviceConfig());
+
+ assertFalse(mBlacklist.isBlacklisted(APP1));
}
@Test
public void testDefaultBlacklistIsOverriddenByDeviceConfig() {
- final Resources r = createResources("com.android.sample1");
- final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
- config.setBlacklist("com.android.sample2,com.android.sample3");
- HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
- assertFalse(blacklist.isBlacklisted("com.android.sample1"));
- assertTrue(blacklist.isBlacklisted("com.android.sample2"));
- assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+ final Resources r = createResources(APP1);
+ final FakeDeviceConfig config = new FakeDeviceConfig();
+ config.setBlacklist(APP2 + "," + APP3);
+ mBlacklist = new HighRefreshRateBlacklist(r, config);
+
+ assertFalse(mBlacklist.isBlacklisted(APP1));
+ assertTrue(mBlacklist.isBlacklisted(APP2));
+ assertTrue(mBlacklist.isBlacklisted(APP3));
}
@Test
public void testDefaultBlacklistIsOverriddenByEmptyDeviceConfig() {
- final Resources r = createResources("com.android.sample1");
- final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+ final Resources r = createResources(APP1);
+ final FakeDeviceConfig config = new FakeDeviceConfig();
config.setBlacklist("");
- HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
- assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ mBlacklist = new HighRefreshRateBlacklist(r, config);
+
+ assertFalse(mBlacklist.isBlacklisted(APP1));
}
@Test
public void testDefaultBlacklistIsOverriddenByDeviceConfigUpdate() {
- final Resources r = createResources("com.android.sample1");
- final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
- HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+ final Resources r = createResources(APP1);
+ final FakeDeviceConfig config = new FakeDeviceConfig();
+ mBlacklist = new HighRefreshRateBlacklist(r, config);
// First check that the default blacklist is in effect
- assertTrue(blacklist.isBlacklisted("com.android.sample1"));
- assertFalse(blacklist.isBlacklisted("com.android.sample2"));
- assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+ assertTrue(mBlacklist.isBlacklisted(APP1));
+ assertFalse(mBlacklist.isBlacklisted(APP2));
+ assertFalse(mBlacklist.isBlacklisted(APP3));
// Then confirm that the DeviceConfig list has propagated and taken effect.
- config.setBlacklist("com.android.sample2,com.android.sample3");
- assertFalse(blacklist.isBlacklisted("com.android.sample1"));
- assertTrue(blacklist.isBlacklisted("com.android.sample2"));
- assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+ config.setBlacklist(APP2 + "," + APP3);
+ assertFalse(mBlacklist.isBlacklisted(APP1));
+ assertTrue(mBlacklist.isBlacklisted(APP2));
+ assertTrue(mBlacklist.isBlacklisted(APP3));
// Finally make sure we go back to the default list if the DeviceConfig gets deleted.
config.setBlacklist(null);
- assertTrue(blacklist.isBlacklisted("com.android.sample1"));
- assertFalse(blacklist.isBlacklisted("com.android.sample2"));
- assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+ assertTrue(mBlacklist.isBlacklisted(APP1));
+ assertFalse(mBlacklist.isBlacklisted(APP2));
+ assertFalse(mBlacklist.isBlacklisted(APP3));
}
private Resources createResources(String... defaultBlacklist) {
@@ -120,64 +127,25 @@ public class HighRefreshRateBlacklistTest {
return r;
}
-
- class FakeDeviceConfigInterface implements DeviceConfigInterface {
- private List<Pair<DeviceConfig.OnPropertiesChangedListener, Executor>> mListeners =
- new ArrayList<>();
- private String mBlacklist;
+ private static class FakeDeviceConfig extends FakeDeviceConfigInterface {
@Override
public String getProperty(String namespace, String name) {
- if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)
- || !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
- throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
- + "supported.");
- }
- return mBlacklist;
+ Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
+ Preconditions.checkArgument(KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name));
+ return super.getProperty(namespace, name);
}
@Override
public void addOnPropertiesChangedListener(String namespace, Executor executor,
DeviceConfig.OnPropertiesChangedListener listener) {
-
- if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)) {
- throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
- + "supported.");
- }
- mListeners.add(new Pair<>(listener, executor));
+ Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
+ super.addOnPropertiesChangedListener(namespace, executor, listener);
}
void setBlacklist(String blacklist) {
- mBlacklist = blacklist;
- CountDownLatch latch = new CountDownLatch(mListeners.size());
- for (Pair<DeviceConfig.OnPropertiesChangedListener, Executor> listenerInfo :
- mListeners) {
- final Executor executor = listenerInfo.second;
- final DeviceConfig.OnPropertiesChangedListener listener = listenerInfo.first;
- DeviceConfig.Properties properties = createBlacklistProperties(blacklist);
- executor.execute(() -> {
- listener.onPropertiesChanged(properties);
- latch.countDown();
- });
- }
- try {
- latch.await(10, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- throw new RuntimeException("Failed to notify all blacklist listeners in time.", e);
- }
- }
-
- private DeviceConfig.Properties createBlacklistProperties(final String blacklist) {
- DeviceConfig.Properties properties = mock(DeviceConfig.Properties.class);
- when(properties.getString(anyString(), any())).thenAnswer(invocation -> {
- final Object[] args = invocation.getArguments();
- if (KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(args[0])) {
- return blacklist;
- } else {
- return args[1];
- }
- });
- return properties;
+ putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ KEY_HIGH_REFRESH_RATE_BLACKLIST, blacklist);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 562775c2025f..2c34f331e965 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -56,7 +56,6 @@ import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.StrictMode;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.view.InputChannel;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -299,10 +298,11 @@ public class SystemServicesTestRule implements TestRule {
// Unregister display listener from root to avoid issues with subsequent tests.
mContext.getSystemService(DisplayManager.class)
.unregisterDisplayListener(mAtmService.mRootActivityContainer);
- // ProptertiesChangesListener is registered in the constructor of WindowManagerService to
- // a static object, so we need to clean it up in tearDown(), even though we didn't set up
- // in tests.
- DeviceConfig.removeOnPropertiesChangedListener(mWmService.mPropertiesChangedListener);
+ // The constructor of WindowManagerService registers WindowManagerConstants and
+ // HighRefreshRateBlacklist with DeviceConfig. We need to undo that here to avoid
+ // leaking mWmService.
+ mWmService.mConstants.dispose();
+ mWmService.mHighRefreshRateBlacklist.dispose();
waitUntilWindowManagerHandlersIdle();
// Needs to explicitly dispose current static threads because there could be messages
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index bebb3ba52bff..f595e0525cc2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -20,11 +20,17 @@ import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static junit.framework.Assert.assertEquals;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import android.app.ActivityManager.TaskSnapshot;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
import org.junit.Before;
import org.junit.Test;
@@ -39,12 +45,14 @@ import org.junit.Test;
public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
private TaskSnapshotCache mCache;
+ @Mock
+ TaskSnapshot mSnapshot;
@Override
@Before
public void setUp() {
super.setUp();
-
+ MockitoAnnotations.initMocks(this);
mCache = new TaskSnapshotCache(mWm, mLoader);
}
@@ -110,4 +118,13 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
true /* restoreFromDisk */, false /* reducedResolution */));
}
+
+ @Test
+ public void testClearCache() {
+ final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ mCache.putSnapshot(window.getTask(), mSnapshot);
+ assertEquals(mSnapshot, mCache.getSnapshot(window.getTask().mTaskId, 0, false, false));
+ mCache.clearRunningCache();
+ assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0, false, false));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 58770418413c..f5e65b1385dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -102,10 +102,7 @@ public class TaskStackTests extends WindowTestsBase {
WindowTestUtils.createTestActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
-
assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
- task2.setSendingToBottom(true);
- assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java
new file mode 100644
index 000000000000..52100116df53
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
+import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
+import static android.provider.DeviceConfig.NAMESPACE_ANDROID;
+import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
+
+import static com.android.server.wm.WindowManagerConstants.KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.utils.FakeDeviceConfigInterface;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Presubmit
+@SmallTest
+public class WindowManagerConstantsTest {
+
+ ExecutorService mExecutor;
+ WindowManagerConstants mConstants;
+ FakeDeviceConfigInterface mDeviceConfig;
+ Runnable mUpdateSystemGestureExclusionCallback;
+
+ @Before
+ public void setUp() throws Exception {
+ mExecutor = Executors.newSingleThreadExecutor();
+ mDeviceConfig = new FakeDeviceConfigInterface();
+ mUpdateSystemGestureExclusionCallback = mock(Runnable.class);
+ mConstants = new WindowManagerConstants(new WindowManagerGlobalLock(),
+ mUpdateSystemGestureExclusionCallback, mDeviceConfig);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mExecutor.shutdown();
+ }
+
+ @Test
+ public void test_constantsAreLoaded_initially() {
+ mDeviceConfig.putProperty(NAMESPACE_ANDROID, KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, "400");
+ mDeviceConfig.putProperty(NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, "true");
+ mDeviceConfig.putProperty(NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, "10000");
+
+ mConstants.start(mExecutor);
+
+ assertEquals(400, mConstants.mSystemGestureExclusionLimitDp);
+ assertTrue(mConstants.mSystemGestureExcludedByPreQStickyImmersive);
+ assertEquals(10000, mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis);
+ }
+
+ @Test
+ public void test_constantsAreLoaded_afterChange() {
+ mConstants.start(mExecutor);
+
+ mDeviceConfig.putPropertyAndNotify(
+ NAMESPACE_ANDROID, KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, "400");
+ mDeviceConfig.putPropertyAndNotify(NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, "true");
+ mDeviceConfig.putPropertyAndNotify(NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, "10000");
+
+ assertEquals(400, mConstants.mSystemGestureExclusionLimitDp);
+ assertTrue(mConstants.mSystemGestureExcludedByPreQStickyImmersive);
+ assertEquals(10000, mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis);
+ }
+
+ @Test
+ public void test_changedGestureExclusionLimit_invokesCallback() {
+ mConstants.start(mExecutor);
+
+ mDeviceConfig.putPropertyAndNotify(
+ NAMESPACE_ANDROID, KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, "400");
+
+ verify(mUpdateSystemGestureExclusionCallback).run();
+ }
+
+ @Test
+ public void test_changedPreQStickyImmersive_invokesCallback() {
+ mConstants.start(mExecutor);
+
+ mDeviceConfig.putPropertyAndNotify(NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, "true");
+
+ verify(mUpdateSystemGestureExclusionCallback).run();
+ }
+
+ @Test
+ public void test_minimumExclusionLimitIs_200dp() {
+ mDeviceConfig.putProperty(NAMESPACE_ANDROID, KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, "20");
+
+ mConstants.start(mExecutor);
+ assertEquals(200, mConstants.mSystemGestureExclusionLimitDp);
+
+ mDeviceConfig.putPropertyAndNotify(NAMESPACE_ANDROID,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, "21");
+ assertEquals(200, mConstants.mSystemGestureExclusionLimitDp);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java b/services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java
new file mode 100644
index 000000000000..2904a5b73646
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.utils;
+
+import android.annotation.NonNull;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+import android.util.Pair;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+public class FakeDeviceConfigInterface implements DeviceConfigInterface {
+
+ private Map<String, String> mProperties = new HashMap<>();
+ private ArrayMap<DeviceConfig.OnPropertiesChangedListener, Pair<String, Executor>> mListeners =
+ new ArrayMap<>();
+
+ public void clearProperties() {
+ mProperties.clear();
+ }
+
+ public void putProperty(String namespace, String key, String value) {
+ mProperties.put(createCompositeName(namespace, key), value);
+ }
+
+ public void putPropertyAndNotify(String namespace, String key, String value) {
+ putProperty(namespace, key, value);
+ DeviceConfig.Properties properties = makeProperties(namespace, key, value);
+ CountDownLatch latch = new CountDownLatch(mListeners.size());
+ for (int i = 0; i < mListeners.size(); i++) {
+ if (namespace.equals(mListeners.valueAt(i).first)) {
+ final int j = i;
+ mListeners.valueAt(i).second.execute(
+ () -> {
+ mListeners.keyAt(j).onPropertiesChanged(properties);
+ latch.countDown();
+ });
+ } else {
+ latch.countDown();
+ }
+ }
+ boolean success;
+ try {
+ success = latch.await(10, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ success = false;
+ }
+ if (!success) {
+ throw new RuntimeException("Failed to notify all listeners in time.");
+ }
+ }
+
+ private DeviceConfig.Properties makeProperties(String namespace, String key, String value) {
+ try {
+ final Constructor<DeviceConfig.Properties> ctor =
+ DeviceConfig.Properties.class.getDeclaredConstructor(String.class, Map.class);
+ ctor.setAccessible(true);
+ final HashMap<String, String> keyValueMap = new HashMap<>();
+ keyValueMap.put(key, value);
+ return ctor.newInstance(namespace, keyValueMap);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getProperty(String namespace, String name) {
+ return mProperties.get(createCompositeName(namespace, name));
+ }
+
+ @Override
+ public String getString(String namespace, String name, String defaultValue) {
+ String value = getProperty(namespace, name);
+ return value != null ? value : defaultValue;
+ }
+
+ @Override
+ public int getInt(String namespace, String name, int defaultValue) {
+ String value = getProperty(namespace, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public long getLong(String namespace, String name, long defaultValue) {
+ String value = getProperty(namespace, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public boolean getBoolean(String namespace, String name, boolean defaultValue) {
+ String value = getProperty(namespace, name);
+ return value != null ? Boolean.parseBoolean(value) : defaultValue;
+ }
+
+ @Override
+ public void addOnPropertiesChangedListener(String namespace, Executor executor,
+ DeviceConfig.OnPropertiesChangedListener listener) {
+ Pair<String, Executor> oldNamespace = mListeners.get(listener);
+ if (oldNamespace == null) {
+ // Brand new listener, add it to the list.
+ mListeners.put(listener, new Pair<>(namespace, executor));
+ } else if (namespace.equals(oldNamespace.first)) {
+ // Listener is already registered for this namespace, update executor just in case.
+ mListeners.put(listener, new Pair<>(namespace, executor));
+ } else {
+ // DeviceConfig allows re-registering listeners for different namespaces, but that
+ // silently unregisters the prior namespace. This likely isn't something the caller
+ // intended.
+ throw new IllegalStateException("Listener " + listener + " already registered. This"
+ + "is technically allowed by DeviceConfig, but likely indicates a logic "
+ + "error.");
+ }
+ }
+
+ @Override
+ public void removeOnPropertiesChangedListener(
+ DeviceConfig.OnPropertiesChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
+ private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
+ Preconditions.checkNotNull(namespace);
+ Preconditions.checkNotNull(name);
+ return namespace + "/" + name;
+ }
+}
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 5fb4e90b9666..5fb4e90b9666 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/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 46c89d26ad03..8be84a61db76 100755
--- 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
@@ -3567,6 +3578,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/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/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fe1028b1bd46..60a2cd043887 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7853,8 +7853,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()));
}
/**
@@ -7864,11 +7864,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/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 e96a0787c9af..e895baecab73 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -849,7 +849,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/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/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/cmds/idmap/Android.bp b/tools/processors/unsupportedappusage/test/Android.bp
index ae5d74a47000..49ea3d4bbc96 100644
--- a/cmds/idmap/Android.bp
+++ b/tools/processors/unsupportedappusage/test/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 The Android Open Source Project
+// 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.
@@ -12,27 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_binary {
- name: "idmap",
+java_test_host {
+ name: "unsupportedappusage-processor-test",
- srcs: [
- "idmap.cpp",
- "create.cpp",
- "scan.cpp",
- "inspect.cpp",
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libandroidfw",
- "libcutils",
- ],
+ srcs: ["src/**/*.java"],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
+ 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");
+ }
+
+
+}