summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt43
-rw-r--r--api/system-current.txt9
-rw-r--r--api/test-current.txt5
-rw-r--r--cmds/statsd/src/atoms.proto74
-rw-r--r--config/preloaded-classes2
-rw-r--r--config/preloaded-classes-blacklist2
-rw-r--r--core/java/android/accounts/Account.java6
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityThread.java27
-rw-r--r--core/java/android/app/ClientTransactionHandler.java3
-rw-r--r--core/java/android/app/LocalActivityManager.java2
-rw-r--r--core/java/android/app/servertransaction/NewIntentItem.java21
-rw-r--r--core/java/android/content/Intent.java12
-rw-r--r--core/java/android/content/om/OverlayInfo.java2
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java8
-rw-r--r--core/java/android/os/Environment.java4
-rw-r--r--core/java/android/os/image/DynamicSystemClient.java6
-rw-r--r--core/java/android/os/storage/StorageManager.java36
-rw-r--r--core/java/android/provider/SearchIndexablesContract.java2
-rw-r--r--core/java/android/provider/SearchIndexablesProvider.java2
-rw-r--r--core/java/android/provider/Settings.java56
-rw-r--r--core/java/android/service/autofill/AutofillService.java4
-rw-r--r--core/java/android/service/autofill/IFillCallback.aidl2
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java3
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java5
-rw-r--r--core/java/android/util/FeatureFlagUtils.java3
-rw-r--r--core/java/android/util/StatsLog.java8
-rw-r--r--core/java/android/view/IRecentsAnimationController.aidl4
-rw-r--r--core/java/android/view/InsetsSourceConsumer.java1
-rw-r--r--core/java/android/view/SurfaceControl.java16
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java122
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java78
-rw-r--r--core/java/com/android/internal/app/ResolverListController.java13
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessState.java2
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp11
-rw-r--r--core/jni/fd_utils.cpp2
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/strings.xml12
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java6
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java2
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java4
-rw-r--r--libs/hwui/renderthread/VulkanSurface.cpp77
-rw-r--r--native/android/system_fonts.cpp3
-rw-r--r--packages/DynamicSystemInstallationService/res/values/strings.xml12
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java8
-rw-r--r--packages/NetworkStack/src/android/net/ip/IpClient.java46
-rw-r--r--packages/NetworkStack/src/android/net/util/DataStallUtils.java72
-rw-r--r--packages/NetworkStack/src/android/net/util/NetworkStackUtils.java21
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java80
-rw-r--r--packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java22
-rw-r--r--packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java24
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java11
-rw-r--r--packages/SettingsLib/res/values/strings.xml4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java72
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java25
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/drawable/ic_sysbar_back.xml1
-rw-r--r--packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml1
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java123
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java161
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java230
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml (renamed from packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_perm_group_sms.xml)0
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml (renamed from packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml)0
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml25
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml (renamed from packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_perm_group_sms.xml)0
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml (renamed from packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml)0
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml25
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml (renamed from packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_perm_group_sms.xml)0
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml (renamed from packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml)0
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml25
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml5
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml8
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java15
-rw-r--r--services/core/java/com/android/server/IpSecService.java3
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java4
-rw-r--r--services/core/java/com/android/server/SystemServerInitThreadPool.java58
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java6
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java9
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java226
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java11
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java5
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java17
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java1
-rw-r--r--services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java51
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java826
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java7
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerSettings.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java20
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java66
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java1
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java17
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java5
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java93
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationTarget.java6
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java28
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java17
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java53
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimationSpec.java19
-rw-r--r--services/net/java/android/net/ip/IIpClient.aidl1
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java504
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java505
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java119
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java121
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java19
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java12
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java7
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java20
-rw-r--r--telephony/java/android/telephony/CellIdentityGsm.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityLte.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityTdscdma.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityWcdma.java2
-rw-r--r--telephony/java/android/telephony/CellInfoCdma.java12
-rw-r--r--telephony/java/android/telephony/CellInfoGsm.java12
-rw-r--r--telephony/java/android/telephony/CellInfoLte.java12
-rw-r--r--telephony/java/android/telephony/CellInfoNr.java6
-rw-r--r--telephony/java/android/telephony/CellInfoTdscdma.java6
-rw-r--r--telephony/java/android/telephony/CellInfoWcdma.java7
-rw-r--r--telephony/java/android/telephony/CellSignalStrength.java20
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthCdma.java9
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthGsm.java39
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthLte.java9
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthNr.java6
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthTdscdma.java53
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthWcdma.java19
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java4
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java5
-rw-r--r--tests/net/Android.bp1
-rw-r--r--tests/net/common/Android.bp29
-rw-r--r--tests/net/common/java/android/net/IpPrefixTest.java (renamed from tests/net/java/android/net/IpPrefixTest.java)80
-rw-r--r--tests/net/java/android/net/netlink/InetDiagSocketTest.java2
-rw-r--r--tests/net/java/com/android/server/IpSecServiceTest.java34
-rw-r--r--tools/aapt2/link/TableMerger.cpp32
-rw-r--r--tools/aapt2/link/TableMerger_test.cpp64
153 files changed, 3801 insertions, 1371 deletions
diff --git a/api/current.txt b/api/current.txt
index 5997043cdd4a..535fbbcf1d73 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10307,6 +10307,7 @@ package android.content {
field public static final String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
field public static final String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
field public static final String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+ field public static final String CATEGORY_APP_FILES = "android.intent.category.APP_FILES";
field public static final String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
field public static final String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
field public static final String CATEGORY_APP_MARKET = "android.intent.category.APP_MARKET";
@@ -44380,9 +44381,9 @@ package android.telephony {
method public int getCid();
method public int getLac();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method @Deprecated public int getPsc();
method public void writeToParcel(android.os.Parcel, int);
@@ -44394,9 +44395,9 @@ package android.telephony {
method public int getCi();
method public int getEarfcn();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getPci();
method public int getTac();
@@ -44419,8 +44420,8 @@ package android.telephony {
method public int getCid();
method public int getCpid();
method public int getLac();
- method public String getMccString();
- method public String getMncString();
+ method @Nullable public String getMccString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getUarfcn();
method public void writeToParcel(android.os.Parcel, int);
@@ -44431,9 +44432,9 @@ package android.telephony {
method public int getCid();
method public int getLac();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getPsc();
method public int getUarfcn();
@@ -44456,22 +44457,22 @@ package android.telephony {
}
public final class CellInfoCdma extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityCdma getCellIdentity();
- method public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityCdma getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoCdma> CREATOR;
}
public final class CellInfoGsm extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityGsm getCellIdentity();
- method public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityGsm getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoGsm> CREATOR;
}
public final class CellInfoLte extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityLte getCellIdentity();
- method public android.telephony.CellSignalStrengthLte getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityLte getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthLte getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoLte> CREATOR;
}
@@ -44507,7 +44508,7 @@ package android.telephony {
method public abstract boolean equals(Object);
method public abstract int getAsuLevel();
method public abstract int getDbm();
- method public abstract int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public abstract int getLevel();
method public abstract int hashCode();
field public static final int SIGNAL_STRENGTH_GOOD = 3; // 0x3
field public static final int SIGNAL_STRENGTH_GREAT = 4; // 0x4
@@ -44527,7 +44528,7 @@ package android.telephony {
method public int getEvdoEcio();
method public int getEvdoLevel();
method public int getEvdoSnr();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthCdma> CREATOR;
}
@@ -44537,7 +44538,7 @@ package android.telephony {
method public int getAsuLevel();
method public int getBitErrorRate();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getTimingAdvance();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthGsm> CREATOR;
@@ -44548,7 +44549,7 @@ package android.telephony {
method public int getAsuLevel();
method public int getCqi();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getRsrp();
method public int getRsrq();
method public int getRssi();
@@ -44565,7 +44566,7 @@ package android.telephony {
method public int getCsiRsrq();
method public int getCsiSinr();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getSsRsrp();
method public int getSsRsrq();
method public int getSsSinr();
@@ -44577,7 +44578,7 @@ package android.telephony {
method public int describeContents();
method public int getAsuLevel();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=0, to=4) public int getLevel();
method public int getRscp();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthTdscdma> CREATOR;
@@ -44587,7 +44588,7 @@ package android.telephony {
method public int describeContents();
method public int getAsuLevel();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 3ee6a49c1b44..76b8f6610590 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5980,7 +5980,7 @@ package android.provider {
field public static final String NON_INDEXABLES_KEYS_PATH = "settings/non_indexables_key";
field public static final String PROVIDER_INTERFACE = "android.content.action.SEARCH_INDEXABLES_PROVIDER";
field public static final String SLICE_URI_PAIRS = "slice_uri_pairs";
- field public static final String[] SLICE_URI_PAIRS_COLUMNS;
+ field @NonNull public static final String[] SLICE_URI_PAIRS_COLUMNS;
field public static final String SLICE_URI_PAIRS_PATH = "settings/slice_uri_pairs";
}
@@ -6028,7 +6028,7 @@ package android.provider {
method public android.database.Cursor query(android.net.Uri, String[], String, String[], String);
method public abstract android.database.Cursor queryNonIndexableKeys(String[]);
method public abstract android.database.Cursor queryRawData(String[]);
- method public android.database.Cursor querySliceUriPairs();
+ method @Nullable public android.database.Cursor querySliceUriPairs();
method public abstract android.database.Cursor queryXmlResources(String[]);
method public final int update(android.net.Uri, android.content.ContentValues, String, String[]);
}
@@ -6062,11 +6062,6 @@ package android.provider {
field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
field public static final String CARRIER_APP_NAMES = "carrier_app_names";
field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
- field public static final String DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = "data_stall_consecutive_dns_timeout_threshold";
- field public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
- field public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1; // 0x1
- field public static final String DATA_STALL_MIN_EVALUATE_INTERVAL = "data_stall_min_evaluate_interval";
- field public static final String DATA_STALL_VALID_DNS_TIME_THRESHOLD = "data_stall_valid_dns_time_threshold";
field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
field public static final String DEVICE_DEMO_MODE = "device_demo_mode";
field public static final String DEVICE_PROVISIONING_MOBILE_DATA_ENABLED = "device_provisioning_mobile_data";
diff --git a/api/test-current.txt b/api/test-current.txt
index b35b90f70749..f76881d19e93 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2160,11 +2160,6 @@ package android.provider {
field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
- field public static final String DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = "data_stall_consecutive_dns_timeout_threshold";
- field public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
- field public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1; // 0x1
- field public static final String DATA_STALL_MIN_EVALUATE_INTERVAL = "data_stall_min_evaluate_interval";
- field public static final String DATA_STALL_VALID_DNS_TIME_THRESHOLD = "data_stall_valid_dns_time_threshold";
field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 146cf0cd2da9..f7608f5320e8 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -159,7 +159,7 @@ message Atom {
BiometricAcquired biometric_acquired = 87;
BiometricAuthenticated biometric_authenticated = 88;
BiometricErrorOccurred biometric_error_occurred = 89;
- Notification notification = 90;
+ // Atom number 90 is available for use.
BatteryHealthSnapshot battery_health_snapshot = 91;
SlowIo slow_io = 92;
BatteryCausedShutdown battery_caused_shutdown = 93;
@@ -3199,76 +3199,6 @@ message BiometricEnrolled {
optional bool success = 4;
}
-message Notification {
-
- // Type of notification event.
- enum Type {
- TYPE_UNKNOWN = 0;
- // Notification became visible to the user.
- TYPE_OPEN = 1;
- // Notification became hidden.
- TYPE_CLOSE = 2;
- // Notification switched to detail mode.
- TYPE_DETAIL = 3;
- // Notification was clicked.
- TYPE_ACTION = 4;
- // Notification was dismissed.
- TYPE_DISMISS = 5;
- // Notification switched to summary mode. The enum value of 14 is to
- // match that of metrics_constants.
- TYPE_COLLAPSE = 14;
- }
- optional Type type = 1;
-
- // Package name associated with the notification.
- optional string package_name = 2;
-
- // Tag associated with notification.
- optional string tag = 3;
-
- // Application-supplied ID associated with the notification.
- optional int32 id = 4;
-
- // Index of notification in the notification panel.
- optional int32 shade_index = 5;
-
- // The number of notifications in the notification panel.
- optional int32 shade_count = 6;
-
- // Importance for the notification.
- optional int32 importance = 7;
-
- // ID for the notification channel.
- optional string channel_id = 8;
-
- // Importance for the notification channel.
- optional int32 channel_importance = 9;
-
- // Application-supplied ID associated with the notifications group.
- optional string group_id = 10;
-
- // Whether notification was a group summary.
- optional bool group_summary = 11;
-
- // Reason for dismissal of a notification. This field is only meaningful for
- // TYPE_DISMISS events.
- optional int32 dismiss_reason = 12;
-
- // The first post time of notification, stable across updates.
- optional int64 creation_millis = 13;
-
- // The most recent interruption time, or the creation time if no updates.
- // Differs from update_millis because updates are filtered based on whether
- // they actually interrupted the user.
- optional int64 interruption_millis = 14;
-
- // The most recent update time, or the creation time if no updates.
- optional int64 update_millis = 15;
-
- // The most recent visibility event.
- optional int64 visible_millis = 16;
-}
-
/*
* Logs when a flag flip update occurrs. Used for mainline modules that update via flag flips.
*/
@@ -4989,6 +4919,8 @@ message AppCompacted {
UNKNOWN = 0;
SOME = 1;
FULL = 2;
+ PERSISTENT = 3;
+ BFGS = 4;
}
optional Action action = 3;
diff --git a/config/preloaded-classes b/config/preloaded-classes
index abdbab2a29eb..5910c284608d 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -756,7 +756,6 @@ android.content.ActivityNotFoundException
android.content.AsyncQueryHandler$WorkerArgs
android.content.AsyncQueryHandler$WorkerHandler
android.content.AsyncQueryHandler
-android.content.AsyncTaskLoader$LoadTask
android.content.AsyncTaskLoader
android.content.BroadcastReceiver$PendingResult$1
android.content.BroadcastReceiver$PendingResult
@@ -3186,7 +3185,6 @@ android.speech.tts.ITextToSpeechCallback
android.speech.tts.ITextToSpeechService$Stub$Proxy
android.speech.tts.ITextToSpeechService
android.speech.tts.TextToSpeech$Action
-android.speech.tts.TextToSpeech$Connection$SetupConnectionAsyncTask
android.speech.tts.TextToSpeech$Connection
android.speech.tts.TextToSpeech$OnInitListener
android.speech.tts.TextToSpeech
diff --git a/config/preloaded-classes-blacklist b/config/preloaded-classes-blacklist
index 59f605d8e490..cd5a1205d122 100644
--- a/config/preloaded-classes-blacklist
+++ b/config/preloaded-classes-blacklist
@@ -1,6 +1,8 @@
+android.content.AsyncTaskLoader$LoadTask
android.net.ConnectivityThread$Singleton
android.os.AsyncTask
android.os.FileObserver
+android.speech.tts.TextToSpeech$Connection$SetupConnectionAsyncTask
android.widget.Magnifier
sun.nio.fs.UnixChannelFactory
com.android.server.SystemConfig$PermissionEntry
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 26377642f2f9..c822d20445ec 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -93,6 +93,12 @@ public class Account implements Parcelable {
public Account(Parcel in) {
this.name = in.readString();
this.type = in.readString();
+ if (TextUtils.isEmpty(name)) {
+ throw new android.os.BadParcelableException("the name must not be empty: " + name);
+ }
+ if (TextUtils.isEmpty(type)) {
+ throw new android.os.BadParcelableException("the type must not be empty: " + type);
+ }
this.accessId = in.readString();
if (accessId != null) {
synchronized (sAccessedAccounts) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 883bcb896841..54fe65db499c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -820,8 +820,6 @@ public class Activity extends ContextThemeWrapper
/** {@code true} if the activity lifecycle is in a state which supports picture-in-picture.
* This only affects the client-side exception, the actual state check still happens in AMS. */
private boolean mCanEnterPictureInPicture = false;
- /** true if the activity is going through a transient pause */
- /*package*/ boolean mTemporaryPause = false;
/** true if the activity is being destroyed in order to recreate it with a new configuration */
/*package*/ boolean mChangingConfigurations = false;
@UnsupportedAppUsage
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38006dc5b943..b37d117238af 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -615,7 +615,6 @@ public final class ActivityThread extends ClientTransactionHandler {
sb.append(", finished=").append(activity.isFinishing());
sb.append(", destroyed=").append(activity.isDestroyed());
sb.append(", startedActivity=").append(activity.mStartedActivity);
- sb.append(", temporaryPause=").append(activity.mTemporaryPause);
sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
sb.append("}");
}
@@ -3319,35 +3318,15 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- @UnsupportedAppUsage
- void performNewIntents(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
+ @Override
+ public void handleNewIntent(IBinder token, List<ReferrerIntent> intents) {
final ActivityClientRecord r = mActivities.get(token);
if (r == null) {
return;
}
- final boolean resumed = !r.paused;
- if (resumed) {
- r.activity.mTemporaryPause = true;
- performPauseActivityIfNeeded(r, "performNewIntents");
- }
checkAndBlockForNetworkAccess();
deliverNewIntents(r, intents);
- if (resumed) {
- performResumeActivity(token, false, "performNewIntents");
- r.activity.mTemporaryPause = false;
- } else if (andPause) {
- // In this case the activity was in the paused state when we delivered the intent,
- // to guarantee onResume gets called after onNewIntent we temporarily resume the
- // activity and pause again as the caller wanted.
- performResumeActivity(token, false, "performNewIntents");
- performPauseActivityIfNeeded(r, "performNewIntents");
- }
- }
-
- @Override
- public void handleNewIntent(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
- performNewIntents(token, intents, andPause);
}
public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
@@ -4662,7 +4641,6 @@ public final class ActivityThread extends ClientTransactionHandler {
try {
// Now we are idle.
r.activity.mCalled = false;
- r.activity.mTemporaryPause = true;
mInstrumentation.callActivityOnPause(r.activity);
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
@@ -4684,7 +4662,6 @@ public final class ActivityThread extends ClientTransactionHandler {
deliverResults(r, results, reason);
if (resumed) {
r.activity.performResume(false, reason);
- r.activity.mTemporaryPause = false;
}
}
}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 70badfae4a20..9dc8b45a71dc 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -150,8 +150,7 @@ public abstract class ClientTransactionHandler {
Configuration overrideConfig);
/** Deliver new intent. */
- public abstract void handleNewIntent(IBinder token, List<ReferrerIntent> intents,
- boolean andPause);
+ public abstract void handleNewIntent(IBinder token, List<ReferrerIntent> intents);
/** Deliver picture-in-picture mode change notification. */
public abstract void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index a52fb1a07b84..94b1d7770307 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -339,7 +339,7 @@ public class LocalActivityManager {
ArrayList<ReferrerIntent> intents = new ArrayList<>(1);
intents.add(new ReferrerIntent(intent, mParent.getPackageName()));
if (localLOGV) Log.v(TAG, r.id + ": new intent");
- mActivityThread.performNewIntents(r, intents, false /* andPause */);
+ mActivityThread.handleNewIntent(r, intents);
r.intent = intent;
moveToState(r, mCurState);
if (mSingleMode) {
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index 4c7f56d4b076..2d1883836d02 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -16,6 +16,8 @@
package android.app.servertransaction;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
+
import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
@@ -36,19 +38,17 @@ public class NewIntentItem extends ClientTransactionItem {
@UnsupportedAppUsage
private List<ReferrerIntent> mIntents;
- private boolean mPause;
- // TODO(lifecycler): Switch new intent handling to this scheme.
- /*@Override
+ @Override
public int getPostExecutionState() {
return ON_RESUME;
- }*/
+ }
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
- client.handleNewIntent(token, mIntents, mPause);
+ client.handleNewIntent(token, mIntents);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -58,13 +58,12 @@ public class NewIntentItem extends ClientTransactionItem {
private NewIntentItem() {}
/** Obtain an instance initialized with provided params. */
- public static NewIntentItem obtain(List<ReferrerIntent> intents, boolean pause) {
+ public static NewIntentItem obtain(List<ReferrerIntent> intents) {
NewIntentItem instance = ObjectPool.obtain(NewIntentItem.class);
if (instance == null) {
instance = new NewIntentItem();
}
instance.mIntents = intents;
- instance.mPause = pause;
return instance;
}
@@ -72,7 +71,6 @@ public class NewIntentItem extends ClientTransactionItem {
@Override
public void recycle() {
mIntents = null;
- mPause = false;
ObjectPool.recycle(this);
}
@@ -82,13 +80,11 @@ public class NewIntentItem extends ClientTransactionItem {
/** Write to Parcel. */
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeBoolean(mPause);
dest.writeTypedList(mIntents, flags);
}
/** Read from Parcel. */
private NewIntentItem(Parcel in) {
- mPause = in.readBoolean();
mIntents = in.createTypedArrayList(ReferrerIntent.CREATOR);
}
@@ -112,19 +108,18 @@ public class NewIntentItem extends ClientTransactionItem {
return false;
}
final NewIntentItem other = (NewIntentItem) o;
- return mPause == other.mPause && Objects.equals(mIntents, other.mIntents);
+ return Objects.equals(mIntents, other.mIntents);
}
@Override
public int hashCode() {
int result = 17;
- result = 31 * result + (mPause ? 1 : 0);
result = 31 * result + mIntents.hashCode();
return result;
}
@Override
public String toString() {
- return "NewIntentItem{pause=" + mPause + ",intents=" + mIntents + "}";
+ return "NewIntentItem{intents=" + mIntents + "}";
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d87171e39595..8628d32123bc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4731,6 +4731,18 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
+ /**
+ * Used with {@link #ACTION_MAIN} to launch the files application.
+ * The activity should be able to browse and manage files stored on the device.
+ * <p>NOTE: This should not be used as the primary key of an Intent,
+ * since it will not result in the app launching with the correct
+ * action and category. Instead, use this with
+ * {@link #makeMainSelectorActivity(String, String)} to generate a main
+ * Intent with this category in the selector.</p>
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_APP_FILES = "android.intent.category.APP_FILES";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard extra data keys.
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index fc79a425e861..639335e53ae5 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -451,7 +451,7 @@ public final class OverlayInfo implements Parcelable {
public String toString() {
return "OverlayInfo { overlay=" + packageName + ", targetPackage=" + targetPackageName
+ ((targetOverlayableName == null) ? ""
- : ", targetOverlyabale=" + targetOverlayableName)
+ : ", targetOverlayable=" + targetOverlayableName)
+ ", state=" + state + " (" + stateToString(state) + "), userId=" + userId + " }";
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 8231985970aa..c9551378c190 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -25,6 +25,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
+import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
/**
@@ -64,13 +65,12 @@ public abstract class DisplayManagerInternal {
public abstract boolean isProximitySensorAvailable();
/**
- * Take a screenshot of the specified display into the provided {@link Surface}.
+ * Take a screenshot of the specified display and return a buffer.
*
* @param displayId The display id to take the screenshot of.
- * @param outSurface The {@link Surface} to take the screenshot into.
- * @return True if the screenshot is taken.
+ * @return The buffer or null if we have failed.
*/
- public abstract boolean screenshot(int displayId, Surface outSurface);
+ public abstract SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId);
/**
* Returns information about the specified logical display.
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 9e9e68dbf3fe..ed5c1b1e2277 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -1148,9 +1148,9 @@ public class Environment {
final Context context = AppGlobals.getInitialApplication();
final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
- final boolean hasLegacy = appOps.noteOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
+ final boolean hasLegacy = appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
context.getApplicationInfo().uid,
- context.getPackageName()) == AppOpsManager.MODE_ALLOWED;
+ context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED;
// STOPSHIP: only use app-op once permission model has fully landed
final boolean requestedLegacy = !AppGlobals.getInitialApplication().getApplicationInfo()
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 8f68723e1b7d..f1f24fb4dd89 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -211,7 +211,7 @@ public class DynamicSystemClient {
* Intent Keys
*/
/**
- * Intent key: Size of system image, in bytes.
+ * Intent key: Size of the system image, in bytes.
* @hide
*/
public static final String KEY_SYSTEM_SIZE = "KEY_SYSTEM_SIZE";
@@ -365,7 +365,7 @@ public class DynamicSystemClient {
*
* This function doesn't require prior calling {@link #bind}.
*
- * @param systemUrl A network URL or a file URL to system image.
+ * @param systemUrl a network Uri, a file Uri or a content Uri pointing to a system image file.
* @param systemSize size of system image.
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
@@ -381,7 +381,7 @@ public class DynamicSystemClient {
*
* This function doesn't require prior calling {@link #bind}.
*
- * @param systemUrl A network URL or a file URL to system image.
+ * @param systemUrl a network Uri, a file Uri or a content Uri pointing to a system image file.
* @param systemSize size of system image.
* @param userdataSize bytes reserved for userdata.
*/
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c57bf9141248..075b650ed8f4 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1652,6 +1652,26 @@ public class StorageManager {
*/
public static boolean checkPermissionAndAppOp(Context context, boolean enforce,
int pid, int uid, String packageName, String permission, int op) {
+ return checkPermissionAndAppOp(context, enforce, pid, uid, packageName, permission, op,
+ true);
+ }
+
+ /**
+ * Check that given app holds both permission and appop but do not noteOp.
+ * @hide
+ */
+ public static boolean checkPermissionAndCheckOp(Context context, boolean enforce,
+ int pid, int uid, String packageName, String permission, int op) {
+ return checkPermissionAndAppOp(context, enforce, pid, uid, packageName, permission, op,
+ false);
+ }
+
+ /**
+ * Check that given app holds both permission and appop.
+ * @hide
+ */
+ private static boolean checkPermissionAndAppOp(Context context, boolean enforce,
+ int pid, int uid, String packageName, String permission, int op, boolean note) {
if (context.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) {
if (enforce) {
throw new SecurityException(
@@ -1662,7 +1682,21 @@ public class StorageManager {
}
AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
- final int mode = appOps.noteOpNoThrow(op, uid, packageName);
+ final int mode;
+ if (note) {
+ mode = appOps.noteOpNoThrow(op, uid, packageName);
+ } else {
+ try {
+ appOps.checkPackage(uid, packageName);
+ } catch (SecurityException e) {
+ if (enforce) {
+ throw e;
+ } else {
+ return false;
+ }
+ }
+ mode = appOps.checkOpNoThrow(op, uid, packageName);
+ }
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
return true;
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 42c2d5ced806..5f8266d2b579 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -16,6 +16,7 @@
package android.provider;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.ContentResolver;
@@ -210,6 +211,7 @@ public class SearchIndexablesContract {
/**
* Cursor schema for SliceUriPairs.
*/
+ @NonNull
public static final String[] SLICE_URI_PAIRS_COLUMNS = new String[]{
SliceUriPairColumns.KEY,
SliceUriPairColumns.SLICE_URI
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index d505f02468d0..da29e2e5e39f 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -16,6 +16,7 @@
package android.provider;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.slice.Slice;
import android.content.ContentProvider;
@@ -184,6 +185,7 @@ public abstract class SearchIndexablesProvider extends ContentProvider {
* Returns a {@link Cursor} linking {@link Slice} {@link Uri Uris} to the
* corresponding Settings key.
*/
+ @Nullable
public Cursor querySliceUriPairs() {
// By default no-op;
return null;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3db6b2bcaa89..6e897975963f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11199,62 +11199,6 @@ public final class Settings {
public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
/**
- * The threshold value for the number of consecutive dns timeout events received to be a
- * signal of data stall. The number of consecutive timeouts needs to be {@code >=} this
- * threshold to be considered a data stall. Set the value to {@code <= 0} to disable. Note
- * that the value should be {@code > 0} if the DNS data stall detection is enabled.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final String DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD =
- "data_stall_consecutive_dns_timeout_threshold";
-
- /**
- * The minimal time interval in milliseconds for data stall reevaluation.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final String DATA_STALL_MIN_EVALUATE_INTERVAL =
- "data_stall_min_evaluate_interval";
-
- /**
- * DNS timeouts older than this timeout (in milliseconds) are not considered for detecting
- * a data stall.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final String DATA_STALL_VALID_DNS_TIME_THRESHOLD =
- "data_stall_valid_dns_time_threshold";
-
- /**
- * Which data stall detection signal to use. This is a bitmask constructed by bitwise-or-ing
- * (i.e. {@code |}) the DATA_STALL_EVALUATION_TYPE_* values.
- *
- * Type: int
- * Valid values:
- * {@link #DATA_STALL_EVALUATION_TYPE_DNS} : Use dns as a signal.
- * @hide
- */
- @SystemApi
- @TestApi
- public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
-
- /**
- * Use dns timeout counts to detect data stall.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
-
- /**
* Whether to try cellular data recovery when a bad network is reported.
*
* @hide
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index f39ef9afdb3c..5a918023fdc3 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -674,6 +674,8 @@ public abstract class AutofillService extends Service {
* Called when the Android system disconnects from the service.
*
* <p> At this point this service may no longer be an active {@link AutofillService}.
+ * It should not make calls on {@link AutofillManager} that requires the caller to be
+ * the current service.
*/
public void onDisconnected() {
}
@@ -695,6 +697,8 @@ public abstract class AutofillService extends Service {
* finishing the {@link FillCallback}.
*
* @return The history or {@code null} if there are no events.
+ *
+ * @throws RuntimeException if the event history could not be retrieved.
*/
@Nullable public final FillEventHistory getFillEventHistory() {
final AutofillManager afm = getSystemService(AutofillManager.class);
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 1bad1d7f474a..32cf712b5fd4 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -25,7 +25,7 @@ import android.service.autofill.FillResponse;
*
* @hide
*/
-interface IFillCallback {
+oneway interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
void onSuccess(in FillResponse response);
void onFailure(int requestId, CharSequence message);
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 96b861b46dd4..b00eb8a0a2e1 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -41,6 +41,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAugmentedAutofillManagerClient;
import android.view.autofill.IAutofillWindowPresenter;
@@ -183,6 +184,8 @@ public abstract class AugmentedAutofillService extends Service {
* Called when the Android system disconnects from the service.
*
* <p> At this point this service may no longer be an active {@link AugmentedAutofillService}.
+ * It should not make calls on {@link AutofillManager} that requires the caller to be
+ * the current service.
*/
public void onDisconnected() {
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index dc57a1591913..5be73b92fbc0 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -37,7 +37,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
-import android.service.autofill.AutofillService;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -350,7 +349,9 @@ public abstract class ContentCaptureService extends Service {
/**
* Called when the Android system disconnects from the service.
*
- * <p> At this point this service may no longer be an active {@link AutofillService}.
+ * <p> At this point this service may no longer be an active {@link ContentCaptureService}.
+ * It should not make calls on {@link ContentCaptureManager} that requires the caller to be
+ * the current service.
*/
public void onDisconnected() {
Slog.i(TAG, "unbinding from " + getClass().getName());
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 04046fe066e7..feff9db1a63e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,6 +42,8 @@ public class FeatureFlagUtils {
"settings_global_actions_force_grid_enabled";
public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
"settings_global_actions_panel_enabled";
+ public static final String PIXEL_WALLPAPER_CATEGORY_SWITCH =
+ "settings_pixel_wallpaper_category_switch";
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -60,6 +62,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
+ DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "true");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
}
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 30d3d7d069b5..dd22a26d61af 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -136,7 +136,13 @@ public final class StatsLog extends StatsLogInternal {
* @param trainName name of install train.
* @param trainVersionCode version code of the train.
* @param options optional flags about this install.
- * @param state current install state.
+ * The last 3 bits indicate options:
+ * 0x01: FLAG_REQUIRE_STAGING
+ * 0x02: FLAG_ROLLBACK_ENABLED
+ * 0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR
+ * @param state current install state. Defined as State enums in
+ * BinaryPushStateChanged atom in
+ * frameworks/base/cmds/statsd/src/atoms.proto
* @param experimentIds experiment ids.
* @return True if the log request was sent to statsd.
*/
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 597b34bf8554..956161acd762 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -41,9 +41,11 @@ interface IRecentsAnimationController {
* with remote animation targets should be relinquished. If {@param moveHomeToTop} is true, then
* the home activity should be moved to the top. Otherwise, the home activity is hidden and the
* user is returned to the app.
+ * @param sendUserLeaveHint If set to true, {@link Activity#onUserLeaving} will be sent to the
+ * top resumed app, false otherwise.
*/
@UnsupportedAppUsage
- void finish(boolean moveHomeToTop);
+ void finish(boolean moveHomeToTop, boolean sendUserLeaveHint);
/**
* Called by the handler to indicate that the recents animation input consumer should be
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 1383463ef72f..a7801583f643 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -153,6 +153,7 @@ public class InsetsSourceConsumer {
return;
}
mVisible = visible;
+ applyHiddenToControl();
applyLocalVisibilityOverride();
mController.notifyVisibilityChanged();
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ec62e190d0b4..79363edb0955 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -439,10 +439,13 @@ public final class SurfaceControl implements Parcelable {
public static class ScreenshotGraphicBuffer {
private final GraphicBuffer mGraphicBuffer;
private final ColorSpace mColorSpace;
+ private final boolean mContainsSecureLayers;
- public ScreenshotGraphicBuffer(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
+ public ScreenshotGraphicBuffer(GraphicBuffer graphicBuffer, ColorSpace colorSpace,
+ boolean containsSecureLayers) {
mGraphicBuffer = graphicBuffer;
mColorSpace = colorSpace;
+ mContainsSecureLayers = containsSecureLayers;
}
/**
@@ -453,13 +456,16 @@ public final class SurfaceControl implements Parcelable {
* @param usage Hint indicating how the buffer will be used
* @param unwrappedNativeObject The native object of GraphicBuffer
* @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
+ * @param containsSecureLayer Indicates whether this graphic buffer contains captured contents
+ * of secure layers, in which case the screenshot should not be persisted.
*/
private static ScreenshotGraphicBuffer createFromNative(int width, int height, int format,
- int usage, long unwrappedNativeObject, int namedColorSpace) {
+ int usage, long unwrappedNativeObject, int namedColorSpace,
+ boolean containsSecureLayers) {
GraphicBuffer graphicBuffer = GraphicBuffer.createFromExisting(width, height, format,
usage, unwrappedNativeObject);
ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]);
- return new ScreenshotGraphicBuffer(graphicBuffer, colorSpace);
+ return new ScreenshotGraphicBuffer(graphicBuffer, colorSpace, containsSecureLayers);
}
public ColorSpace getColorSpace() {
@@ -469,6 +475,10 @@ public final class SurfaceControl implements Parcelable {
public GraphicBuffer getGraphicBuffer() {
return mGraphicBuffer;
}
+
+ public boolean containsSecureLayers() {
+ return mContainsSecureLayers;
+ }
}
/**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 94be25f00e4c..988fad2fb28e 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -43,6 +43,7 @@ import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
@@ -117,12 +118,18 @@ import com.google.android.collect.Lists;
import java.io.IOException;
import java.lang.annotation.Retention;
+import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+/**
+ * The Chooser Activity handles intent resolution specifically for sharing intents -
+ * for example, those generated by @see android.content.Intent#createChooser(Intent, CharSequence).
+ *
+ */
public class ChooserActivity extends ResolverActivity {
private static final String TAG = "ChooserActivity";
@@ -200,6 +207,8 @@ public class ChooserActivity extends ResolverActivity {
/** {@link ChooserActivity#getBaseScore} */
private static final float SHORTCUT_TARGET_SCORE_BOOST = 10.f;
private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
+ // TODO: Update to handle landscape instead of using static value
+ private static final int MAX_RANKED_TARGETS = 4;
private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
@@ -216,6 +225,7 @@ public class ChooserActivity extends ResolverActivity {
private boolean mListViewDataChanged = false;
+
@Retention(SOURCE)
@IntDef({CONTENT_PREVIEW_FILE, CONTENT_PREVIEW_IMAGE, CONTENT_PREVIEW_TEXT})
private @interface ContentPreviewType {
@@ -228,6 +238,9 @@ public class ChooserActivity extends ResolverActivity {
private static final int CONTENT_PREVIEW_TEXT = 3;
protected MetricsLogger mMetricsLogger;
+ // Sorted list of DisplayResolveInfos for the alphabetical app section.
+ private List<ResolverActivity.DisplayResolveInfo> mSortedList = new ArrayList<>();
+
private final Handler mChooserHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -935,8 +948,11 @@ public class ChooserActivity extends ResolverActivity {
// Note that this is only safe because the Intent handled by the ChooserActivity is
// guaranteed to contain no extras unknown to the local ClassLoader. That is why this
// method can not be replaced in the ResolverActivity whole hog.
- return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE,
- super.shouldAutoLaunchSingleChoice(target));
+ if (!super.shouldAutoLaunchSingleChoice(target)) {
+ return false;
+ }
+
+ return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE, true);
}
@Override
@@ -961,10 +977,6 @@ public class ChooserActivity extends ResolverActivity {
@Override
protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
- if (target instanceof NotSelectableTargetInfo) {
- return false;
- }
-
if (mRefinementIntentSender != null) {
final Intent fillIn = new Intent();
final List<Intent> sourceIntents = target.getAllSourceIntents();
@@ -997,6 +1009,11 @@ public class ChooserActivity extends ResolverActivity {
@Override
public void startSelected(int which, boolean always, boolean filtered) {
+ TargetInfo targetInfo = mChooserListAdapter.targetInfoForPosition(which, filtered);
+ if (targetInfo != null && targetInfo instanceof NotSelectableTargetInfo) {
+ return;
+ }
+
final long selectionCost = System.currentTimeMillis() - mChooserShownTime;
super.startSelected(which, always, filtered);
@@ -1405,6 +1422,30 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ private void updateAlphabeticalList() {
+ if (getDisplayList().size() > MAX_RANKED_TARGETS) {
+ mSortedList.clear();
+ mSortedList.addAll(getDisplayList());
+ Collections.sort(mSortedList, new AzInfoComparator(ChooserActivity.this));
+ }
+ }
+
+ /**
+ * Sort intents alphabetically based on display label.
+ */
+ class AzInfoComparator implements Comparator<ResolverActivity.DisplayResolveInfo> {
+ Collator mCollator;
+ AzInfoComparator(Context context) {
+ mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
+ }
+
+ @Override
+ public int compare(ResolverActivity.DisplayResolveInfo lhsp,
+ ResolverActivity.DisplayResolveInfo rhsp) {
+ return mCollator.compare(lhsp.getDisplayLabel(), rhsp.getDisplayLabel());
+ }
+ }
+
protected MetricsLogger getMetricsLogger() {
if (mMetricsLogger == null) {
mMetricsLogger = new MetricsLogger();
@@ -1451,7 +1492,8 @@ public class ChooserActivity extends ResolverActivity {
mPm,
getTargetIntent(),
getReferrerPackageName(),
- mLaunchedFromUid);
+ mLaunchedFromUid
+ );
}
@VisibleForTesting
@@ -1527,6 +1569,10 @@ public class ChooserActivity extends ResolverActivity {
public ChooserTarget getChooserTarget() {
return null;
}
+
+ public boolean isSuspended() {
+ return false;
+ }
}
final class PlaceHolderTargetInfo extends NotSelectableTargetInfo {
@@ -1552,6 +1598,7 @@ public class ChooserActivity extends ResolverActivity {
private final Intent mFillInIntent;
private final int mFillInFlags;
private final float mModifiedScore;
+ private boolean mIsSuspended;
SelectableTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget,
float modifiedScore) {
@@ -1580,6 +1627,8 @@ public class ChooserActivity extends ResolverActivity {
mFillInIntent = null;
mFillInFlags = 0;
+ ApplicationInfo ai = sourceInfo.getResolveInfo().activityInfo.applicationInfo;
+ mIsSuspended = (ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
}
private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) {
@@ -1594,6 +1643,10 @@ public class ChooserActivity extends ResolverActivity {
mModifiedScore = other.mModifiedScore;
}
+ public boolean isSuspended() {
+ return mIsSuspended;
+ }
+
/**
* Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip
* the call to LauncherApps#getShortcuts(ShortcutQuery).
@@ -1974,6 +2027,7 @@ public class ChooserActivity extends ResolverActivity {
queryTargetServices(this);
}
+ updateAlphabeticalList();
}
@Override
@@ -1983,13 +2037,17 @@ public class ChooserActivity extends ResolverActivity {
@Override
public int getCount() {
- return super.getCount() + getSelectableServiceTargetCount() + getCallerTargetCount();
+ return getStandardTargetCount() + getAlphaTargetCount()
+ + getSelectableServiceTargetCount() + getCallerTargetCount();
}
@Override
public int getUnfilteredCount() {
- return super.getUnfilteredCount() + getSelectableServiceTargetCount()
- + getCallerTargetCount();
+ int appTargets = super.getUnfilteredCount();
+ if (appTargets > MAX_RANKED_TARGETS) {
+ appTargets = appTargets + MAX_RANKED_TARGETS;
+ }
+ return appTargets + getSelectableServiceTargetCount() + getCallerTargetCount();
}
public int getCallerTargetCount() {
@@ -2018,7 +2076,13 @@ public class ChooserActivity extends ResolverActivity {
}
public int getStandardTargetCount() {
- return super.getCount();
+ int standardCount = super.getCount();
+ return standardCount > MAX_RANKED_TARGETS ? MAX_RANKED_TARGETS : standardCount;
+ }
+
+ int getAlphaTargetCount() {
+ int standardCount = super.getCount();
+ return standardCount > MAX_RANKED_TARGETS ? standardCount : 0;
}
public int getPositionTargetType(int position) {
@@ -2036,7 +2100,7 @@ public class ChooserActivity extends ResolverActivity {
}
offset += callerTargetCount;
- final int standardTargetCount = super.getCount();
+ final int standardTargetCount = getStandardTargetCount();
if (position - offset < standardTargetCount) {
return TARGET_STANDARD;
}
@@ -2049,10 +2113,17 @@ public class ChooserActivity extends ResolverActivity {
return targetInfoForPosition(position, true);
}
+
+ /**
+ * Find target info for a given position.
+ * Since ChooserActivity displays several sections of content, determine which
+ * section provides this item.
+ */
@Override
public TargetInfo targetInfoForPosition(int position, boolean filtered) {
int offset = 0;
+ // Direct share targets
final int serviceTargetCount = filtered ? getServiceTargetCount() :
getSelectableServiceTargetCount();
if (position < serviceTargetCount) {
@@ -2060,16 +2131,32 @@ public class ChooserActivity extends ResolverActivity {
}
offset += serviceTargetCount;
+ // Targets provided by calling app
final int callerTargetCount = getCallerTargetCount();
if (position - offset < callerTargetCount) {
return mCallerTargets.get(position - offset);
}
offset += callerTargetCount;
- return filtered ? super.getItem(position - offset)
- : getDisplayResolveInfo(position - offset);
+ // Ranked app targets
+ if (position - offset < MAX_RANKED_TARGETS) {
+ return filtered ? super.getItem(position - offset)
+ : getDisplayResolveInfo(position - offset);
+ }
+ offset += MAX_RANKED_TARGETS;
+
+ // Alphabetical complete app target list.
+ Log.e(TAG, mSortedList.toString());
+ if (position - offset < mSortedList.size()) {
+ return mSortedList.get(position - offset);
+ }
+
+ return null;
+
}
+
+
/**
* Evaluate targets for inclusion in the direct share area. May not be included
* if score is too low.
@@ -2100,6 +2187,9 @@ public class ChooserActivity extends ResolverActivity {
final float baseScore = getBaseScore(origTarget, isShortcutResult);
Collections.sort(targets, mBaseTargetComparator);
+
+
+
float lastScore = 0;
boolean shouldNotify = false;
for (int i = 0, N = Math.min(targets.size(), MAX_TARGETS_PER_SERVICE); i < N; i++) {
@@ -2204,6 +2294,7 @@ public class ChooserActivity extends ResolverActivity {
}
}
+
private boolean isSendAction(Intent targetIntent) {
if (targetIntent == null) {
return false;
@@ -2299,6 +2390,9 @@ public class ChooserActivity extends ResolverActivity {
+ Math.ceil(
(float) mChooserListAdapter.getStandardTargetCount()
/ getMaxTargetsPerRow())
+ + Math.ceil(
+ (float) mChooserListAdapter.getAlphaTargetCount()
+ / getMaxTargetsPerRow())
);
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index f671a753493e..ad1e767f011a 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -44,6 +44,8 @@ import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -132,6 +134,8 @@ public class ResolverActivity extends Activity {
private boolean mRegistered;
+ private ColorMatrixColorFilter mSuspendedMatrixColorFilter;
+
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
@@ -350,6 +354,8 @@ public class ResolverActivity extends Activity {
bindProfileView();
}
+ initSuspendedColorMatrix();
+
if (isVoiceInteraction()) {
onSetupVoiceInteraction();
}
@@ -367,6 +373,25 @@ public class ResolverActivity extends Activity {
mAdapter.handlePackagesChanged();
}
+ private void initSuspendedColorMatrix() {
+ int grayValue = 127;
+ float scale = 0.5f; // half bright
+
+ ColorMatrix tempBrightnessMatrix = new ColorMatrix();
+ float[] mat = tempBrightnessMatrix.getArray();
+ mat[0] = scale;
+ mat[6] = scale;
+ mat[12] = scale;
+ mat[4] = grayValue;
+ mat[9] = grayValue;
+ mat[14] = grayValue;
+
+ ColorMatrix matrix = new ColorMatrix();
+ matrix.setSaturation(0.0f);
+ matrix.preConcat(tempBrightnessMatrix);
+ mSuspendedMatrixColorFilter = new ColorMatrixColorFilter(matrix);
+ }
+
/**
* Perform any initialization needed for voice interaction.
*/
@@ -1019,7 +1044,14 @@ public class ResolverActivity extends Activity {
if (target != null) {
safelyStartActivity(target);
+
+ // Rely on the ActivityManager to pop up a dialog regarding app suspension
+ // and return false
+ if (target.isSuspended()) {
+ return false;
+ }
}
+
return true;
}
@@ -1106,7 +1138,7 @@ public class ResolverActivity extends Activity {
}
public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
- return true;
+ return !target.isSuspended();
}
public void showTargetDetails(ResolveInfo ri) {
@@ -1326,6 +1358,7 @@ public class ResolverActivity extends Activity {
private final CharSequence mExtendedInfo;
private final Intent mResolvedIntent;
private final List<Intent> mSourceIntents = new ArrayList<>();
+ private boolean mIsSuspended;
public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
CharSequence pInfo, Intent pOrigIntent) {
@@ -1341,6 +1374,8 @@ public class ResolverActivity extends Activity {
final ActivityInfo ai = mResolveInfo.activityInfo;
intent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name));
+ mIsSuspended = (ai.applicationInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
+
mResolvedIntent = intent;
}
@@ -1410,7 +1445,6 @@ public class ResolverActivity extends Activity {
@Override
public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
-
if (mEnableChooserDelegate) {
return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
} else {
@@ -1424,6 +1458,14 @@ public class ResolverActivity extends Activity {
activity.startActivityAsUser(mResolvedIntent, options, user);
return false;
}
+
+ public boolean isSuspended() {
+ return mIsSuspended;
+ }
+ }
+
+ List<DisplayResolveInfo> getDisplayList() {
+ return mAdapter.mDisplayList;
}
/**
@@ -1515,6 +1557,11 @@ public class ResolverActivity extends Activity {
* @return the list of supported source intents deduped against this single target
*/
List<Intent> getAllSourceIntents();
+
+ /**
+ * @return true if this target can be selected by the user
+ */
+ boolean isSuspended();
}
public class ResolveListAdapter extends BaseAdapter {
@@ -1523,12 +1570,12 @@ public class ResolverActivity extends Activity {
private final List<ResolveInfo> mBaseResolveList;
protected ResolveInfo mLastChosen;
private DisplayResolveInfo mOtherProfile;
- private boolean mHasExtendedInfo;
private ResolverListController mResolverListController;
private int mPlaceholderCount;
protected final LayoutInflater mInflater;
+ // This one is the list that the Adapter will actually present.
List<DisplayResolveInfo> mDisplayList;
List<ResolvedComponentInfo> mUnfilteredResolveList;
@@ -1709,6 +1756,7 @@ public class ResolverActivity extends Activity {
}
}
+
private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
int N;
if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
@@ -1746,6 +1794,7 @@ public class ResolverActivity extends Activity {
}
}
+
for (ResolvedComponentInfo rci : sortedComponents) {
final ResolveInfo ri = rci.getResolveInfoAt(0);
if (ri != null) {
@@ -1755,9 +1804,12 @@ public class ResolverActivity extends Activity {
}
}
+
postListReadyRunnable();
}
+
+
/**
* Some necessary methods for creating the list are initiated in onCreate and will also
* determine the layout known. We therefore can't update the UI inline and post to the
@@ -1891,19 +1943,6 @@ public class ResolverActivity extends Activity {
return position;
}
- public boolean hasExtendedInfo() {
- return mHasExtendedInfo;
- }
-
- public boolean hasResolvedTarget(ResolveInfo info) {
- for (int i = 0, N = mDisplayList.size(); i < N; i++) {
- if (resolveInfoMatch(info, mDisplayList.get(i).getResolveInfo())) {
- return true;
- }
- }
- return false;
- }
-
public int getDisplayResolveInfoCount() {
return mDisplayList.size();
}
@@ -1960,6 +1999,12 @@ public class ResolverActivity extends Activity {
holder.text2.setText(subLabel);
}
+ if (info.isSuspended()) {
+ holder.icon.setColorFilter(mSuspendedMatrixColorFilter);
+ } else {
+ holder.icon.setColorFilter(null);
+ }
+
if (info instanceof DisplayResolveInfo
&& !((DisplayResolveInfo) info).hasDisplayIcon()) {
new LoadIconTask((DisplayResolveInfo) info, holder.icon).execute();
@@ -1969,6 +2014,7 @@ public class ResolverActivity extends Activity {
}
}
+
@VisibleForTesting
public static final class ResolvedComponentInfo {
public final ComponentName name;
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 156baf03f563..a3cfa8786d59 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -25,7 +25,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
@@ -153,11 +152,6 @@ public class ResolverListController {
}
// Filter out any activities that the launched uid does not have permission for.
- //
- // Also filter out those that are suspended because they couldn't be started. We don't do this
- // when we have an explicit list of resolved activities, because that only happens when
- // we are being subclassed, so we can safely launch whatever they gave us.
- //
// To preserve the inputList, optionally will return the original list if any modification has
// been made.
@VisibleForTesting
@@ -171,9 +165,8 @@ public class ResolverListController {
int granted = ActivityManager.checkComponentPermission(
ai.permission, mLaunchedFromUid,
ai.applicationInfo.uid, ai.exported);
- boolean suspended = (ai.applicationInfo.flags
- & ApplicationInfo.FLAG_SUSPENDED) != 0;
- if (granted != PackageManager.PERMISSION_GRANTED || suspended
+
+ if (granted != PackageManager.PERMISSION_GRANTED
|| isComponentFiltered(ai.getComponentName())) {
// Access not allowed! We're about to filter an item,
// so modify the unfiltered version if it hasn't already been modified.
@@ -253,6 +246,7 @@ public class ResolverListController {
isComputed = true;
}
Collections.sort(inputList, mResolverComparator);
+
long afterRank = System.currentTimeMillis();
if (DEBUG) {
Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
@@ -262,6 +256,7 @@ public class ResolverListController {
}
}
+
private static boolean isSameResolvedComponent(ResolveInfo a,
ResolverActivity.ResolvedComponentInfo b) {
final ActivityInfo ai = a.activityInfo;
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index b26efc0dbd10..2f9136a2577e 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -78,8 +78,8 @@ public final class ProcessState {
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
+ STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 1155854efd55..ef5178aca40a 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -449,13 +449,13 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
return;
}
mBinding = false;
- mService = getServiceInterface(service);
try {
service.linkToDeath(AbstractRemoteService.this, 0);
} catch (RemoteException re) {
handleBinderDied();
return;
}
+ mService = getServiceInterface(service);
handleOnConnectedStateChangedInternal(true);
mServiceDied = false;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c254266961cf..3135c62c9c61 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -250,10 +250,11 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
Rect sourceCrop = rectFromObj(env, sourceCropObj);
sp<GraphicBuffer> buffer;
+ bool capturedSecureLayers = false;
status_t res = ScreenshotClient::capture(displayToken, dataspace,
ui::PixelFormat::RGBA_8888,
sourceCrop, width, height,
- useIdentityTransform, rotation, captureSecureLayers, &buffer);
+ useIdentityTransform, rotation, captureSecureLayers, &buffer, capturedSecureLayers);
if (res != NO_ERROR) {
return NULL;
}
@@ -266,7 +267,8 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
buffer->getPixelFormat(),
(jint)buffer->getUsage(),
(jlong)buffer.get(),
- namedColorSpace);
+ namedColorSpace,
+ capturedSecureLayers);
}
static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
@@ -315,7 +317,8 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandl
buffer->getPixelFormat(),
(jint)buffer->getUsage(),
(jlong)buffer.get(),
- namedColorSpace);
+ namedColorSpace,
+ false /* capturedSecureLayers */);
}
static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) {
@@ -1455,7 +1458,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
MakeGlobalRefOrDie(env, screenshotGraphicsBufferClazz);
gScreenshotGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env,
screenshotGraphicsBufferClazz,
- "createFromNative", "(IIIIJI)Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;");
+ "createFromNative", "(IIIIJIZ)Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;");
jclass displayedContentSampleClazz = FindClassOrDie(env,
"android/hardware/display/DisplayedContentSample");
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 099635246f05..77ebd0290d33 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -462,7 +462,6 @@ FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_
}
if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
- LOG(INFO) << "Ignoring open file descriptor " << fd;
continue;
}
@@ -496,7 +495,6 @@ void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_
}
if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
- LOG(INFO) << "Ignoring open file descriptor " << fd;
continue;
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e8cc96cbd848..0163fc0e20ce 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3345,6 +3345,9 @@
<!-- True if the device supports system decorations on secondary displays. -->
<bool name="config_supportsSystemDecorsOnSecondaryDisplays">true</bool>
+ <!-- True if the device supports insecure lock screen. -->
+ <bool name="config_supportsInsecureLockScreen">true</bool>
+
<!-- True if the device requires AppWidgetService even if it does not have
the PackageManager.FEATURE_APP_WIDGETS feature -->
<bool name="config_enableAppWidgetService">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6f3adfd11a48..f8a2ac9f3e18 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -525,7 +525,7 @@
<!-- label for screenshot item in power menu -->
<string name="global_action_screenshot">Screenshot</string>
- <!-- Take bug report menu title [CHAR LIMIT=20] -->
+ <!-- Take bug report menu title [CHAR LIMIT=30] -->
<string name="bugreport_title">Bug report</string>
<!-- Message in bugreport dialog describing what it does [CHAR LIMIT=NONE] -->
<!-- TODO: remove if not used anymore -->
@@ -1551,25 +1551,25 @@
<string-array name="face_acquired_vendor">
</string-array>
- <!-- Error message shown when the face hardware can't be accessed. [CHAR LIMIT=50] -->
+ <!-- Error message shown when the face hardware can't be accessed. [CHAR LIMIT=69] -->
<string name="face_error_hw_not_available">Can\u2019t verify face. Hardware not available.</string>
<!-- Error message shown when the face hardware timer has expired and the user needs to restart the operation. [CHAR LIMIT=50] -->
<string name="face_error_timeout">Face timeout reached. Try again.</string>
- <!-- Error message shown when the face hardware has run out of room for storing faces. [CHAR LIMIT=60] -->
+ <!-- Error message shown when the face hardware has run out of room for storing faces. [CHAR LIMIT=69] -->
<string name="face_error_no_space">Can\u2019t store new face data. Delete an old one first.</string>
<!-- Generic error message shown when the face operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user. [CHAR LIMIT=50] -->
<string name="face_error_canceled">Face operation canceled</string>
- <!-- Generic error message shown when the face authentication operation is canceled due to user input. Generally not shown to the user [CHAR LIMIT=50] -->
+ <!-- Generic error message shown when the face authentication operation is canceled due to user input. Generally not shown to the user [CHAR LIMIT=54] -->
<string name="face_error_user_canceled">Face authentication canceled by user</string>
<!-- Generic error message shown when the face operation fails because too many attempts have been made. [CHAR LIMIT=50] -->
<string name="face_error_lockout">Too many attempts. Try again later.</string>
- <!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=60] -->
+ <!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=71] -->
<string name="face_error_lockout_permanent">Too many attempts. Face authentication disabled.</string>
<!-- Generic error message shown when the face hardware can't recognize the face. [CHAR LIMIT=50] -->
<string name="face_error_unable_to_process">Can\u2019t verify face. Try again.</string>
<!-- Generic error message shown when the user has no enrolled face. [CHAR LIMIT=52] -->
<string name="face_error_not_enrolled">You haven\u2019t set up face authentication</string>
- <!-- Generic error message shown when the app requests face authentication on a device without a sensor. [CHAR LIMIT=60] -->
+ <!-- Generic error message shown when the app requests face authentication on a device without a sensor. [CHAR LIMIT=61] -->
<string name="face_error_hw_not_present">Face authentication is not supported on this device</string>
<!-- Template to be used to name enrolled faces by default. [CHAR LIMIT=10] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 664059afd6bc..b87381364b1a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -391,6 +391,7 @@
<java-symbol type="bool" name="config_supportsMultiDisplay" />
<java-symbol type="bool" name="config_noHomeScreen" />
<java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
+ <java-symbol type="bool" name="config_supportsInsecureLockScreen" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
<java-symbol type="bool" name="config_localDisplaysPrivate" />
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 447f28e06d7e..5c8bced25108 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -212,15 +212,15 @@ public class ObjectPoolTests {
@Test
public void testRecycleNewIntentItem() {
- NewIntentItem emptyItem = NewIntentItem.obtain(null, false);
- NewIntentItem item = NewIntentItem.obtain(referrerIntentList(), true);
+ NewIntentItem emptyItem = NewIntentItem.obtain(null);
+ NewIntentItem item = NewIntentItem.obtain(referrerIntentList());
assertNotSame(item, emptyItem);
assertFalse(item.equals(emptyItem));
item.recycle();
assertEquals(item, emptyItem);
- NewIntentItem item2 = NewIntentItem.obtain(referrerIntentList(), true);
+ NewIntentItem item2 = NewIntentItem.obtain(referrerIntentList());
assertSame(item, item2);
assertFalse(item2.equals(emptyItem));
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index d117b4096ca0..bffeb2a6c90e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -128,7 +128,7 @@ public class TransactionParcelTests {
@Test
public void testNewIntent() {
// Write to parcel
- NewIntentItem item = NewIntentItem.obtain(referrerIntentList(), true /* pause */);
+ NewIntentItem item = NewIntentItem.obtain(referrerIntentList());
writeAndPrepareForReading(item);
// Read from parcel and assert
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8cc6e37db48a..655070722c9a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -203,11 +203,7 @@ public class SettingsBackupTest {
Settings.Global.DATA_ROAMING,
Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
- Settings.Global.DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD,
- Settings.Global.DATA_STALL_EVALUATION_TYPE,
- Settings.Global.DATA_STALL_MIN_EVALUATE_INTERVAL,
Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK,
- Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD,
Settings.Global.DEBUG_APP,
Settings.Global.DEBUG_VIEW_ATTRIBUTES,
Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 36f540c47973..be78b694f53a 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -266,47 +266,46 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
vkPixelFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
}
- if (nullptr != vkManager.mGetPhysicalDeviceImageFormatProperties2) {
- VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
- externalImageFormatInfo.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
- externalImageFormatInfo.pNext = nullptr;
- externalImageFormatInfo.handleType =
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
-
- VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
- imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
- imageFormatInfo.pNext = &externalImageFormatInfo;
- imageFormatInfo.format = vkPixelFormat;
- imageFormatInfo.type = VK_IMAGE_TYPE_2D;
- imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageFormatInfo.usage = usageFlags;
- imageFormatInfo.flags = 0;
-
- VkAndroidHardwareBufferUsageANDROID hwbUsage;
- hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
- hwbUsage.pNext = nullptr;
-
- VkImageFormatProperties2 imgFormProps;
- imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
- imgFormProps.pNext = &hwbUsage;
-
- res = vkManager.mGetPhysicalDeviceImageFormatProperties2(vkManager.mPhysicalDevice,
- &imageFormatInfo, &imgFormProps);
- if (VK_SUCCESS != res) {
- ALOGE("Failed to query GetPhysicalDeviceImageFormatProperties2");
- return nullptr;
- }
+ LOG_ALWAYS_FATAL_IF(nullptr == vkManager.mGetPhysicalDeviceImageFormatProperties2,
+ "vkGetPhysicalDeviceImageFormatProperties2 is missing");
+ VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
+ externalImageFormatInfo.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
+ externalImageFormatInfo.pNext = nullptr;
+ externalImageFormatInfo.handleType =
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+
+ VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
+ imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
+ imageFormatInfo.pNext = &externalImageFormatInfo;
+ imageFormatInfo.format = vkPixelFormat;
+ imageFormatInfo.type = VK_IMAGE_TYPE_2D;
+ imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageFormatInfo.usage = usageFlags;
+ imageFormatInfo.flags = 0;
+
+ VkAndroidHardwareBufferUsageANDROID hwbUsage;
+ hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
+ hwbUsage.pNext = nullptr;
+
+ VkImageFormatProperties2 imgFormProps;
+ imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
+ imgFormProps.pNext = &hwbUsage;
+
+ res = vkManager.mGetPhysicalDeviceImageFormatProperties2(vkManager.mPhysicalDevice,
+ &imageFormatInfo, &imgFormProps);
+ if (VK_SUCCESS != res) {
+ ALOGE("Failed to query GetPhysicalDeviceImageFormatProperties2");
+ return nullptr;
+ }
- windowInfo.windowUsageFlags = hwbUsage.androidHardwareBufferUsage;
- if (vkManager.isQualcomm()) {
- windowInfo.windowUsageFlags =
- windowInfo.windowUsageFlags | AHARDWAREBUFFER_USAGE_VENDOR_0;
- }
+ uint64_t consumerUsage;
+ native_window_get_consumer_usage(window, &consumerUsage);
+ windowInfo.windowUsageFlags = consumerUsage | hwbUsage.androidHardwareBufferUsage;
- } else {
- ALOGE("VulkanSurface::Create() vkmGetPhysicalDeviceImageFormatProperties2 is missing");
- return nullptr;
+ if (vkManager.isQualcomm()) {
+ windowInfo.windowUsageFlags =
+ windowInfo.windowUsageFlags | AHARDWAREBUFFER_USAGE_VENDOR_0;
}
/*
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 302cbd11da4b..9791da63359b 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -250,7 +250,8 @@ AFont* _Nonnull AFontMatcher_match(
minikin::U16StringPiece(text, textLength),
matcher->mFontStyle,
matcher->mLocaleListId,
- static_cast<minikin::FamilyVariant>(matcher->mFamilyVariant));
+ static_cast<minikin::FamilyVariant>(matcher->mFamilyVariant),
+ 1 /* maxRun */);
const minikin::Font* font = runs[0].fakedFont.font;
std::unique_ptr<AFont> result = std::make_unique<AFont>();
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index a72e4e2c1b74..2a66db124d10 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -13,11 +13,11 @@
<string name="keyguard_description">Please enter your password and continue to AndroidOnTap installation</string>
<!-- Displayed on notification: AndroidOnTap installation is completed [CHAR LIMIT=128] -->
- <string name="notification_install_completed">New system is ready, you can reboot into it or discard it.</string>
+ <string name="notification_install_completed">System update is ready. To finish installing, restart your device.</string>
<!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] -->
- <string name="notification_install_inprogress">Installation is in progress.</string>
+ <string name="notification_install_inprogress">Install in progress</string>
<!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] -->
- <string name="notification_install_failed">Installation Failed.</string>
+ <string name="notification_install_failed">Install Failed</string>
<!-- Displayed on notification: We are running in AndroidOnTap [CHAR LIMIT=128] -->
<string name="notification_dynsystem_in_use">We are running in AndroidOnTap.</string>
@@ -27,12 +27,12 @@
<string name="notification_action_discard">Discard</string>
<!-- Action on notification: Uninstall AndroidOnTap [CHAR LIMIT=16] -->
<string name="notification_action_uninstall">Uninstall</string>
- <!-- Action on notification: Reboot to AndroidOnTap [CHAR LIMIT=16] -->
- <string name="notification_action_reboot_to_dynsystem">Reboot</string>
+ <!-- Action on notification: Restart to AndroidOnTap [CHAR LIMIT=16] -->
+ <string name="notification_action_reboot_to_dynsystem">Restart</string>
<!-- Toast when installed AndroidOnTap is discarded [CHAR LIMIT=64] -->
<string name="toast_dynsystem_discarded">Installed AndroidOnTap is discarded.</string>
<!-- Toast when we fail to launch into AndroidOnTap [CHAR LIMIT=64] -->
- <string name="toast_failed_to_reboot_to_dynsystem">Failed to reboot into AndroidOnTap.</string>
+ <string name="toast_failed_to_reboot_to_dynsystem">Failed to restart to AndroidOnTap.</string>
</resources>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
index 5c6885a801e8..fcbda1d5c63b 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
@@ -380,13 +380,13 @@ public class DynamicSystemInstallationService extends Service
builder.setContentText(getString(R.string.notification_install_completed));
builder.addAction(new Notification.Action.Builder(
- null, getString(R.string.notification_action_reboot_to_dynsystem),
- createPendingIntent(ACTION_REBOOT_TO_DYN_SYSTEM)).build());
-
- builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_discard),
createPendingIntent(ACTION_DISCARD_INSTALL)).build());
+ builder.addAction(new Notification.Action.Builder(
+ null, getString(R.string.notification_action_reboot_to_dynsystem),
+ createPendingIntent(ACTION_REBOOT_TO_DYN_SYSTEM)).build());
+
break;
case STATUS_IN_USE:
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index c1f178a7f5f1..80d139cb6153 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -51,6 +51,7 @@ import android.os.SystemClock;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -298,6 +299,7 @@ public class IpClient extends StateMachine {
private static final int EVENT_READ_PACKET_FILTER_COMPLETE = 12;
private static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = 13;
private static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = 14;
+ private static final int CMD_UPDATE_L2KEY_GROUPHINT = 15;
// Internal commands to use instead of trying to call transitionTo() inside
// a given State's enter() method. Calling transitionTo() from enter/exit
@@ -364,6 +366,8 @@ public class IpClient extends StateMachine {
private String mTcpBufferSizes;
private ProxyInfo mHttpProxy;
private ApfFilter mApfFilter;
+ private String mL2Key; // The L2 key for this network, for writing into the memory store
+ private String mGroupHint; // The group hint for this network, for writing into the memory store
private boolean mMulticastFiltering;
private long mStartTimeMillis;
@@ -524,6 +528,11 @@ public class IpClient extends StateMachine {
IpClient.this.stop();
}
@Override
+ public void setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ checkNetworkStackCallingPermission();
+ IpClient.this.setL2KeyAndGroupHint(l2Key, groupHint);
+ }
+ @Override
public void setTcpBufferSizes(String tcpBufferSizes) {
checkNetworkStackCallingPermission();
IpClient.this.setTcpBufferSizes(tcpBufferSizes);
@@ -652,6 +661,13 @@ public class IpClient extends StateMachine {
}
/**
+ * Set the L2 key and group hint for storing info into the memory store.
+ */
+ public void setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ sendMessage(CMD_UPDATE_L2KEY_GROUPHINT, new Pair<>(l2Key, groupHint));
+ }
+
+ /**
* Set the HTTP Proxy configuration to use.
*
* This may be called, repeatedly, at any time before or after a call to
@@ -1068,6 +1084,10 @@ public class IpClient extends StateMachine {
return true;
}
final int delta = setLinkProperties(newLp);
+ // Most of the attributes stored in the memory store are deduced from
+ // the link properties, therefore when the properties update the memory
+ // store record should be updated too.
+ maybeSaveNetworkToIpMemoryStore();
if (sendCallbacks) {
dispatchCallback(delta, newLp);
}
@@ -1083,6 +1103,7 @@ public class IpClient extends StateMachine {
Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
}
mCallback.onNewDhcpResults(dhcpResults);
+ maybeSaveNetworkToIpMemoryStore();
dispatchCallback(delta, newLp);
}
@@ -1213,6 +1234,10 @@ public class IpClient extends StateMachine {
mInterfaceCtrl.clearAllAddresses();
}
+ private void maybeSaveNetworkToIpMemoryStore() {
+ // TODO : implement this
+ }
+
class StoppedState extends State {
@Override
public void enter() {
@@ -1258,6 +1283,13 @@ public class IpClient extends StateMachine {
handleLinkPropertiesUpdate(NO_CALLBACKS);
break;
+ case CMD_UPDATE_L2KEY_GROUPHINT: {
+ final Pair<String, String> args = (Pair<String, String>) msg.obj;
+ mL2Key = args.first;
+ mGroupHint = args.second;
+ break;
+ }
+
case CMD_SET_MULTICAST_FILTER:
mMulticastFiltering = (boolean) msg.obj;
break;
@@ -1357,6 +1389,20 @@ public class IpClient extends StateMachine {
}
break;
+ case CMD_UPDATE_L2KEY_GROUPHINT: {
+ final Pair<String, String> args = (Pair<String, String>) msg.obj;
+ mL2Key = args.first;
+ mGroupHint = args.second;
+ // TODO : attributes should be saved to the memory store with
+ // these new values if they differ from the previous ones.
+ // If the state machine is in pure StartedState, then the values to input
+ // are not known yet and should be updated when the LinkProperties are updated.
+ // If the state machine is in RunningState (which is a child of StartedState)
+ // then the next NUD check should be used to store the new values to avoid
+ // inputting current values for what may be a different L3 network.
+ break;
+ }
+
case EVENT_PROVISIONING_TIMEOUT:
handleProvisioningFailure();
break;
diff --git a/packages/NetworkStack/src/android/net/util/DataStallUtils.java b/packages/NetworkStack/src/android/net/util/DataStallUtils.java
new file mode 100644
index 000000000000..b6dbeb19ad1d
--- /dev/null
+++ b/packages/NetworkStack/src/android/net/util/DataStallUtils.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+/**
+ * Collection of utilities for data stall.
+ */
+public class DataStallUtils {
+ /**
+ * Detect data stall via using dns timeout counts.
+ */
+ public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
+ // Default configuration values for data stall detection.
+ public static final int DEFAULT_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = 5;
+ public static final int DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS = 60 * 1000;
+ public static final int DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS = 30 * 60 * 1000;
+ /**
+ * The threshold value for the number of consecutive dns timeout events received to be a
+ * signal of data stall. The number of consecutive timeouts needs to be {@code >=} this
+ * threshold to be considered a data stall. Set the value to {@code <= 0} to disable. Note
+ * that the value should be {@code > 0} if the DNS data stall detection is enabled.
+ *
+ */
+ public static final String CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD =
+ "data_stall_consecutive_dns_timeout_threshold";
+
+ /**
+ * The minimal time interval in milliseconds for data stall reevaluation.
+ *
+ */
+ public static final String CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL =
+ "data_stall_min_evaluate_interval";
+
+ /**
+ * DNS timeouts older than this timeout (in milliseconds) are not considered for detecting
+ * a data stall.
+ *
+ */
+ public static final String CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD =
+ "data_stall_valid_dns_time_threshold";
+
+ /**
+ * Which data stall detection signal to use. This is a bitmask constructed by bitwise-or-ing
+ * (i.e. {@code |}) the DATA_STALL_EVALUATION_TYPE_* values.
+ *
+ * Type: int
+ * Valid values:
+ * {@link #DATA_STALL_EVALUATION_TYPE_DNS} : Use dns as a signal.
+ */
+ public static final String CONFIG_DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
+ public static final int DEFAULT_DATA_STALL_EVALUATION_TYPES = DATA_STALL_EVALUATION_TYPE_DNS;
+ // The default number of DNS events kept of the log kept for dns signal evaluation. Each event
+ // is represented by a {@link com.android.server.connectivity.NetworkMonitor#DnsResult} objects.
+ // It's also the size of array of {@link com.android.server.connectivity.nano.DnsEvent} kept in
+ // metrics. Note that increasing the size may cause statsd log buffer bust. Need to check the
+ // design in statsd when you try to increase the size.
+ public static final int DEFAULT_DNS_LOG_SIZE = 20;
+}
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index dada61ce9618..e7a607b1f921 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -32,6 +32,9 @@ import java.util.function.Predicate;
* Collection of utilities for the network stack.
*/
public class NetworkStackUtils {
+ // TODO: Refer to DeviceConfig definition.
+ public static final String NAMESPACE_CONNECTIVITY = "connectivity";
+
static {
System.loadLibrary("networkstackutilsjni");
}
@@ -104,6 +107,24 @@ public class NetworkStackUtils {
}
/**
+ * Look up the value of a property for a particular namespace from {@link DeviceConfig}.
+ * @param namespace The namespace containing the property to look up.
+ * @param name The name of the property to look up.
+ * @param defaultValue The value to return if the property does not exist or has no non-null
+ * value.
+ * @return the corresponding value, or defaultValue if none exists.
+ */
+ public static int getDeviceConfigPropertyInt(@NonNull String namespace, @NonNull String name,
+ int defaultValue) {
+ String value = getDeviceConfigProperty(namespace, name, null /* defaultValue */);
+ try {
+ return (value != null) ? Integer.parseInt(value) : defaultValue;
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
* Attaches a socket filter that accepts DHCP packets to the given socket.
*/
public static native void attachDhcpFilter(FileDescriptor fd) throws SocketException;
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 8f7d98876e4c..7b77d66ca01f 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -32,8 +32,18 @@ import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
import static android.net.metrics.ValidationProbeEvent.PROBE_PRIVDNS;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_EVALUATION_TYPE;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD;
+import static android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS;
+import static android.net.util.DataStallUtils.DEFAULT_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD;
+import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_EVALUATION_TYPES;
+import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS;
+import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS;
+import static android.net.util.DataStallUtils.DEFAULT_DNS_LOG_SIZE;
+import static android.net.util.NetworkStackUtils.NAMESPACE_CONNECTIVITY;
import static android.net.util.NetworkStackUtils.isEmpty;
-import static android.provider.Settings.Global.DATA_STALL_EVALUATION_TYPE_DNS;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -60,6 +70,7 @@ import android.net.metrics.NetworkEvent;
import android.net.metrics.ValidationProbeEvent;
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
import android.net.util.Stopwatch;
import android.net.wifi.WifiInfo;
@@ -126,18 +137,6 @@ public class NetworkMonitor extends StateMachine {
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
-
- // Default configuration values for data stall detection.
- private static final int DEFAULT_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = 5;
- private static final int DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS = 60 * 1000;
- private static final int DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS = 30 * 60 * 1000;
-
- private static final int DEFAULT_DATA_STALL_EVALUATION_TYPES =
- DATA_STALL_EVALUATION_TYPE_DNS;
- // Reevaluate it as intending to increase the number. Larger log size may cause statsd
- // log buffer bust and have stats log lost.
- private static final int DEFAULT_DNS_LOG_SIZE = 20;
-
enum EvaluationResult {
VALIDATED(true),
CAPTIVE_PORTAL(false);
@@ -388,7 +387,7 @@ public class NetworkMonitor extends StateMachine {
mDnsStallDetector = new DnsStallDetector(mConsecutiveDnsTimeoutThreshold);
mDataStallMinEvaluateTime = getDataStallMinEvaluateTime();
mDataStallValidDnsTimeThreshold = getDataStallValidDnsTimeThreshold();
- mDataStallEvaluationType = getDataStallEvalutionType();
+ mDataStallEvaluationType = getDataStallEvaluationType();
// Provide empty LinkProperties and NetworkCapabilities to make sure they are never null,
// even before notifyNetworkConnected.
@@ -542,10 +541,6 @@ public class NetworkMonitor extends StateMachine {
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
logNetworkEvent(NetworkEvent.NETWORK_DISCONNECTED);
- if (mLaunchCaptivePortalAppBroadcastReceiver != null) {
- mContext.unregisterReceiver(mLaunchCaptivePortalAppBroadcastReceiver);
- mLaunchCaptivePortalAppBroadcastReceiver = null;
- }
quit();
return HANDLED;
case CMD_FORCE_REEVALUATION:
@@ -779,7 +774,10 @@ public class NetworkMonitor extends StateMachine {
@Override
public void exit() {
- mLaunchCaptivePortalAppBroadcastReceiver = null;
+ if (mLaunchCaptivePortalAppBroadcastReceiver != null) {
+ mContext.unregisterReceiver(mLaunchCaptivePortalAppBroadcastReceiver);
+ mLaunchCaptivePortalAppBroadcastReceiver = null;
+ }
hideProvisioningNotification();
}
}
@@ -1185,25 +1183,26 @@ public class NetworkMonitor extends StateMachine {
}
private int getConsecutiveDnsTimeoutThreshold() {
- return mDependencies.getSetting(mContext,
- Settings.Global.DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD,
+ return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+ CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD,
DEFAULT_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD);
}
private int getDataStallMinEvaluateTime() {
- return mDependencies.getSetting(mContext,
- Settings.Global.DATA_STALL_MIN_EVALUATE_INTERVAL,
+ return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+ CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL,
DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS);
}
private int getDataStallValidDnsTimeThreshold() {
- return mDependencies.getSetting(mContext,
- Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD,
+ return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+ CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD,
DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS);
}
- private int getDataStallEvalutionType() {
- return mDependencies.getSetting(mContext, Settings.Global.DATA_STALL_EVALUATION_TYPE,
+ private int getDataStallEvaluationType() {
+ return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+ CONFIG_DATA_STALL_EVALUATION_TYPE,
DEFAULT_DATA_STALL_EVALUATION_TYPES);
}
@@ -1726,6 +1725,33 @@ public class NetworkMonitor extends StateMachine {
return value != null ? value : defaultValue;
}
+ /**
+ * Look up the value of a property in DeviceConfig.
+ * @param namespace The namespace containing the property to look up.
+ * @param name The name of the property to look up.
+ * @param defaultValue The value to return if the property does not exist or has no non-null
+ * value.
+ * @return the corresponding value, or defaultValue if none exists.
+ */
+ @Nullable
+ public String getDeviceConfigProperty(@NonNull String namespace, @NonNull String name,
+ @Nullable String defaultValue) {
+ return NetworkStackUtils.getDeviceConfigProperty(namespace, name, defaultValue);
+ }
+
+ /**
+ * Look up the value of a property in DeviceConfig.
+ * @param namespace The namespace containing the property to look up.
+ * @param name The name of the property to look up.
+ * @param defaultValue The value to return if the property does not exist or has no non-null
+ * value.
+ * @return the corresponding value, or defaultValue if none exists.
+ */
+ public int getDeviceConfigPropertyInt(@NonNull String namespace, @NonNull String name,
+ int defaultValue) {
+ return NetworkStackUtils.getDeviceConfigPropertyInt(namespace, name, defaultValue);
+ }
+
public static final Dependencies DEFAULT = new Dependencies();
}
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index eee12d6f8c7c..5f8000634ffa 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
@@ -40,7 +41,9 @@ import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
+import android.net.NetworkStackIpMemoryStore;
import android.net.RouteInfo;
+import android.net.ipmemorystore.NetworkAttributes;
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
@@ -81,6 +84,8 @@ public class IpClientTest {
// See RFC 7042#section-2.1.2 for EUI-48 documentation values.
private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
private static final int TEST_TIMEOUT_MS = 400;
+ private static final String TEST_L2KEY = "some l2key";
+ private static final String TEST_GROUPHINT = "some grouphint";
@Mock private Context mContext;
@Mock private ConnectivityManager mCm;
@@ -92,6 +97,7 @@ public class IpClientTest {
@Mock private IpClient.Dependencies mDependencies;
@Mock private ContentResolver mContentResolver;
@Mock private NetworkStackService.NetworkStackServiceManager mNetworkStackServiceManager;
+ @Mock private NetworkStackIpMemoryStore mIpMemoryStore;
private NetworkObserver mObserver;
private InterfaceParams mIfParams;
@@ -141,6 +147,12 @@ public class IpClientTest {
return empty;
}
+ private void verifyNetworkAttributesStored(final String l2Key,
+ final NetworkAttributes attributes) {
+ // TODO : when storing is implemented, turn this on
+ // verify(mIpMemoryStore).storeNetworkAttributes(eq(l2Key), eq(attributes), any());
+ }
+
@Test
public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
setTestInterfaceParams(null);
@@ -173,6 +185,7 @@ public class IpClientTest {
setTestInterfaceParams(TEST_IFNAME);
final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry,
mNetworkStackServiceManager, mDependencies);
+ verifyNoMoreInteractions(mIpMemoryStore);
ipc.shutdown();
}
@@ -183,6 +196,7 @@ public class IpClientTest {
mNetworkStackServiceManager, mDependencies);
ipc.startProvisioning(new ProvisioningConfiguration());
verify(mCb, times(1)).onProvisioningFailure(any());
+ verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any());
ipc.shutdown();
}
@@ -202,6 +216,7 @@ public class IpClientTest {
verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
verify(mCb, never()).onProvisioningFailure(any());
+ verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any());
ipc.shutdown();
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
@@ -214,6 +229,8 @@ public class IpClientTest {
public void testProvisioningWithInitialConfiguration() throws Exception {
final String iface = TEST_IFNAME;
final IpClient ipc = makeIpClient(iface);
+ final String l2Key = TEST_L2KEY;
+ final String groupHint = TEST_GROUPHINT;
String[] addresses = {
"fe80::a4be:f92:e1f7:22d1/64",
@@ -232,6 +249,7 @@ public class IpClientTest {
verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
verify(mCb, never()).onProvisioningFailure(any());
+ ipc.setL2KeyAndGroupHint(l2Key, groupHint);
for (String addr : addresses) {
String[] parts = addr.split("/");
@@ -253,12 +271,16 @@ public class IpClientTest {
LinkProperties want = linkproperties(links(addresses), routes(prefixes));
want.setInterfaceName(iface);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want);
+ verifyNetworkAttributesStored(l2Key, new NetworkAttributes.Builder()
+ .setGroupHint(groupHint)
+ .build());
ipc.shutdown();
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
.onLinkPropertiesChange(makeEmptyLinkProperties(iface));
+ verifyNoMoreInteractions(mIpMemoryStore);
}
@Test
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 6665aae65d90..9f6c7f89d71a 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -21,7 +21,11 @@ import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.provider.Settings.Global.DATA_STALL_EVALUATION_TYPE_DNS;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_EVALUATION_TYPE;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL;
+import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD;
+import static android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -114,7 +118,6 @@ public class NetworkMonitorTest {
private @Captor ArgumentCaptor<String> mNetworkTestedRedirectUrlCaptor;
private static final int TEST_NETID = 4242;
-
private static final String TEST_HTTP_URL = "http://www.google.com/gen_204";
private static final String TEST_HTTPS_URL = "https://www.google.com/gen_204";
private static final String TEST_FALLBACK_URL = "http://fallback.google.com/gen_204";
@@ -593,24 +596,23 @@ public class NetworkMonitorTest {
}
private void setDataStallEvaluationType(int type) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
+ when(mDependencies.getDeviceConfigPropertyInt(any(),
+ eq(CONFIG_DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
}
private void setMinDataStallEvaluateInterval(int time) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.DATA_STALL_MIN_EVALUATE_INTERVAL), anyInt())).thenReturn(time);
+ when(mDependencies.getDeviceConfigPropertyInt(any(),
+ eq(CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL), anyInt())).thenReturn(time);
}
private void setValidDataStallDnsTimeThreshold(int time) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD), anyInt())).thenReturn(time);
+ when(mDependencies.getDeviceConfigPropertyInt(any(),
+ eq(CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD), anyInt())).thenReturn(time);
}
private void setConsecutiveDnsTimeoutThreshold(int num) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD), anyInt()))
- .thenReturn(num);
+ when(mDependencies.getDeviceConfigPropertyInt(any(),
+ eq(CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD), anyInt())).thenReturn(num);
}
private void setFallbackUrl(String url) {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index bde1b25b914f..55ff591e3a1f 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -43,7 +43,6 @@ import android.content.pm.PackageUserState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
-import android.os.RemoteException;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
@@ -472,16 +471,6 @@ public class PackageInstallerActivity extends AlertActivity {
mOriginatingUid, mOriginatingPackage);
switch (appOpMode) {
case AppOpsManager.MODE_DEFAULT:
- try {
- int result = mIpm.checkUidPermission(
- Manifest.permission.REQUEST_INSTALL_PACKAGES, mOriginatingUid);
- if (result == PackageManager.PERMISSION_GRANTED) {
- initiateInstall();
- break;
- }
- } catch (RemoteException exc) {
- Log.e(TAG, "Unable to talk to package manager");
- }
mAppOpsManager.setMode(appOpCode, mOriginatingUid,
mOriginatingPackage, AppOpsManager.MODE_ERRORED);
// fall through
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index c6a995cb25f7..8a39b82c0bd9 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -34,6 +34,8 @@
<string name="wifi_security_short_eap" translatable="false">802.1x</string>
<!-- Do not translate. Concise terminology for wifi with WPA3 security -->
<string name="wifi_security_short_sae" translatable="false">WPA3</string>
+ <!-- Do not translate. Concise terminology for wifi with WPA2/WPA3 transition security -->
+ <string name="wifi_security_short_psk_sae" translatable="false">WPA2/WPA3</string>
<!-- Do not translate. Concise terminology for wifi with OWE security -->
<string name="wifi_security_short_owe" translatable="false">OWE</string>
<!-- Do not translate. Concise terminology for wifi with 802.1x EAP Suite-B security -->
@@ -58,6 +60,8 @@
<string name="wifi_security_passpoint" translatable="false">Passpoint</string>
<!-- Do not translate. Terminology for wifi with WPA3 security -->
<string name="wifi_security_sae" translatable="false">WPA3-Personal</string>
+ <!-- Do not translate. Terminology for wifi with WPA2/WPA3 Transition mode security -->
+ <string name="wifi_security_psk_sae" translatable="false">WPA2/WPA3-Personal</string>
<!-- Do not translate. Terminology for wifi with OWE security -->
<string name="wifi_security_owe" translatable="false">Enhanced Open</string>
<!-- Do not translate. Concise terminology for wifi with 802.1x EAP Suite-B security -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index d4d0519fcc5f..e02709e10e83 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -83,17 +83,18 @@ import java.util.regex.Pattern;
* as needed.
*/
public class ApplicationsState {
- static final String TAG = "ApplicationsState";
- static final boolean DEBUG = false;
- static final boolean DEBUG_LOCKING = false;
+ private static final String TAG = "ApplicationsState";
public static final int SIZE_UNKNOWN = -1;
public static final int SIZE_INVALID = -2;
- static final Pattern REMOVE_DIACRITICALS_PATTERN
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_LOCKING = false;
+ private static final Object sLock = new Object();
+ private static final Pattern REMOVE_DIACRITICALS_PATTERN
= Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
- static final Object sLock = new Object();
+ @VisibleForTesting
static ApplicationsState sInstance;
public static ApplicationsState getInstance(Application app) {
@@ -126,13 +127,12 @@ public class ApplicationsState {
// Information about all applications. Synchronize on mEntriesMap
// to protect access to these.
- final ArrayList<Session> mSessions = new ArrayList<Session>();
- final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>();
+ final ArrayList<Session> mSessions = new ArrayList<>();
+ final ArrayList<Session> mRebuildingSessions = new ArrayList<>();
private InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();
// Map: userid => (Map: package name => AppEntry)
- final SparseArray<HashMap<String, AppEntry>> mEntriesMap =
- new SparseArray<HashMap<String, AppEntry>>();
- final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
+ final SparseArray<HashMap<String, AppEntry>> mEntriesMap = new SparseArray<>();
+ final ArrayList<AppEntry> mAppEntries = new ArrayList<>();
List<ApplicationInfo> mApplications = new ArrayList<>();
long mCurId = 1;
UUID mCurComputingSizeUuid;
@@ -182,9 +182,10 @@ public class ApplicationsState {
mInterestingConfigChanges = interestingConfigChanges;
}
- public static final @SessionFlags int DEFAULT_SESSION_FLAGS =
+ @SessionFlags
+ public static final int DEFAULT_SESSION_FLAGS =
FLAG_SESSION_REQUEST_HOME_APP | FLAG_SESSION_REQUEST_ICONS |
- FLAG_SESSION_REQUEST_SIZES | FLAG_SESSION_REQUEST_LAUNCHER;
+ FLAG_SESSION_REQUEST_SIZES | FLAG_SESSION_REQUEST_LAUNCHER;
private ApplicationsState(Application app, IPackageManager iPackageManager) {
mContext = app;
@@ -194,7 +195,7 @@ public class ApplicationsState {
mUm = mContext.getSystemService(UserManager.class);
mStats = mContext.getSystemService(StorageStatsManager.class);
for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) {
- mEntriesMap.put(userId, new HashMap<String, AppEntry>());
+ mEntriesMap.put(userId, new HashMap<>());
}
mThread = new HandlerThread("ApplicationsState.Loader",
@@ -683,9 +684,16 @@ public class ApplicationsState {
private AppEntry getEntryLocked(ApplicationInfo info) {
int userId = UserHandle.getUserId(info.uid);
AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
- if (DEBUG) Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
+ if (DEBUG) {
+ Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
+ }
if (entry == null) {
- if (DEBUG) Log.i(TAG, "Creating AppEntry for " + info.packageName);
+ if (mHiddenModules.contains(info.packageName)) {
+ return null;
+ }
+ if (DEBUG) {
+ Log.i(TAG, "Creating AppEntry for " + info.packageName);
+ }
entry = new AppEntry(mContext, info, mCurId++);
mEntriesMap.get(userId).put(info.packageName, entry);
mAppEntries.add(entry);
@@ -759,7 +767,8 @@ public class ApplicationsState {
boolean mRebuildForeground;
private final boolean mHasLifecycle;
- @SessionFlags private int mFlags = DEFAULT_SESSION_FLAGS;
+ @SessionFlags
+ private int mFlags = DEFAULT_SESSION_FLAGS;
Session(Callbacks callbacks, Lifecycle lifecycle) {
mCallbacks = callbacks;
@@ -771,7 +780,8 @@ public class ApplicationsState {
}
}
- public @SessionFlags int getSessionFlags() {
+ @SessionFlags
+ public int getSessionFlags() {
return mFlags;
}
@@ -863,25 +873,32 @@ public class ApplicationsState {
filter.init(mContext);
}
- List<AppEntry> apps;
+ final List<AppEntry> apps;
synchronized (mEntriesMap) {
apps = new ArrayList<>(mAppEntries);
}
- ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>();
- if (DEBUG) Log.i(TAG, "Rebuilding...");
- for (int i = 0; i < apps.size(); i++) {
- AppEntry entry = apps.get(i);
+ ArrayList<AppEntry> filteredApps = new ArrayList<>();
+ if (DEBUG) {
+ Log.i(TAG, "Rebuilding...");
+ }
+ for (AppEntry entry : apps) {
if (entry != null && (filter == null || filter.filterApp(entry))) {
synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
+ if (DEBUG_LOCKING) {
+ Log.v(TAG, "rebuild acquired lock");
+ }
if (comparator != null) {
// Only need the label if we are going to be sorting.
entry.ensureLabel(mContext);
}
- if (DEBUG) Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
+ if (DEBUG) {
+ Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
+ }
filteredApps.add(entry);
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
+ if (DEBUG_LOCKING) {
+ Log.v(TAG, "rebuild releasing lock");
+ }
}
}
}
@@ -1290,7 +1307,8 @@ public class ApplicationsState {
}
}
- private @SessionFlags int getCombinedSessionFlags(List<Session> sessions) {
+ @SessionFlags
+ private int getCombinedSessionFlags(List<Session> sessions) {
synchronized (mEntriesMap) {
int flags = 0;
for (Session session : sessions) {
@@ -1601,7 +1619,7 @@ public class ApplicationsState {
}
if (object1.info != null && object2.info != null) {
compareResult =
- sCollator.compare(object1.info.packageName, object2.info.packageName);
+ sCollator.compare(object1.info.packageName, object2.info.packageName);
if (compareResult != 0) {
return compareResult;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 2711e3175957..3a53d29f7618 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import android.util.Pair;
+import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -47,7 +48,9 @@ public class BluetoothMediaDevice extends MediaDevice {
@Override
public String getSummary() {
- return mCachedDevice.getConnectionSummary();
+ return isConnected() || mCachedDevice.isBusy()
+ ? mCachedDevice.getConnectionSummary()
+ : mContext.getString(R.string.bluetooth_disconnected);
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 8a88a4c64d0a..1976ec45bf45 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -184,6 +184,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
private static final int PSK_WPA = 1;
private static final int PSK_WPA2 = 2;
private static final int PSK_WPA_WPA2 = 3;
+ private static final int PSK_SAE = 4;
/**
* The number of distinct wifi levels.
@@ -764,7 +765,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
ssid = bestResult.SSID;
bssid = bestResult.BSSID;
security = getSecurity(bestResult);
- if (security == SECURITY_PSK) {
+ if (security == SECURITY_PSK || security == SECURITY_SAE) {
pskType = getPskType(bestResult);
}
mIsCarrierAp = bestResult.isCarrierAp;
@@ -826,8 +827,13 @@ public class AccessPoint implements Comparable<AccessPoint> {
return concise ? context.getString(R.string.wifi_security_short_wep) :
context.getString(R.string.wifi_security_wep);
case SECURITY_SAE:
- return concise ? context.getString(R.string.wifi_security_short_sae) :
- context.getString(R.string.wifi_security_sae);
+ if (pskType == PSK_SAE) {
+ return concise ? context.getString(R.string.wifi_security_short_psk_sae) :
+ context.getString(R.string.wifi_security_psk_sae);
+ } else {
+ return concise ? context.getString(R.string.wifi_security_short_sae) :
+ context.getString(R.string.wifi_security_sae);
+ }
case SECURITY_OWE:
return concise ? context.getString(R.string.wifi_security_short_owe) :
context.getString(R.string.wifi_security_owe);
@@ -1460,15 +1466,22 @@ public class AccessPoint implements Comparable<AccessPoint> {
private static int getPskType(ScanResult result) {
boolean wpa = result.capabilities.contains("WPA-PSK");
- boolean wpa2 = result.capabilities.contains("WPA2-PSK");
- if (wpa2 && wpa) {
+ boolean wpa2 = result.capabilities.contains("RSN-PSK");
+ boolean wpa3TransitionMode = result.capabilities.contains("PSK+SAE");
+ boolean wpa3 = result.capabilities.contains("RSN-SAE");
+ if (wpa3TransitionMode) {
+ return PSK_SAE;
+ } else if (wpa2 && wpa) {
return PSK_WPA_WPA2;
} else if (wpa2) {
return PSK_WPA2;
} else if (wpa) {
return PSK_WPA;
} else {
- Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
+ if (!wpa3) {
+ // Suppress warning for WPA3 only networks
+ Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
+ }
return PSK_UNKNOWN;
}
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d1b7c7572361..3a9a99385c28 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -194,6 +194,9 @@
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
+ <!-- Permission required to test ContentResolver caching. -->
+ <uses-permission android:name="android.permission.CACHE_CONTENT" />
+
<application android:label="@string/app_label"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back.xml b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
index 144884349c52..ee402622d52b 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_back.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
+ android:autoMirrored="true"
android:viewportWidth="28"
android:viewportHeight="28">
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
index 93b2f9c85bd1..442fafcebb84 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
+ android:autoMirrored="true"
android:viewportWidth="28"
android:viewportHeight="28">
<path
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index ce04638a51e5..a067cd202247 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -316,6 +316,7 @@
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
<item>com.android.systemui.SizeCompatModeActivityController</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
+ <item>com.android.systemui.theme.ThemeOverlayController</item>
</string-array>
<!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
@@ -486,4 +487,7 @@
<integer name="ongoing_appops_dialog_max_apps">5</integer>
+ <!-- Launcher package name for overlaying icons. -->
+ <string name="launcher_overlayable_package" translatable="false">com.android.launcher3</string>
+
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 1d9105c35ac5..d2fe5cd9ef64 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -77,9 +77,15 @@ public class RecentsAnimationControllerCompat {
}
}
- public void finish(boolean toHome) {
+ /**
+ * Finish the current recents animation.
+ * @param toHome Going to home or back to the previous app.
+ * @param sendUserLeaveHint determines whether userLeaveHint will be set true to the previous
+ * app.
+ */
+ public void finish(boolean toHome, boolean sendUserLeaveHint) {
try {
- mAnimationController.finish(toHome);
+ mAnimationController.finish(toHome, sendUserLeaveHint);
} catch (RemoteException e) {
Log.e(TAG, "Failed to finish recents animation", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 34f3c606be62..33a2acfe9521 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -64,6 +64,7 @@ import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.io.PrintWriter;
@@ -339,7 +340,7 @@ public class RecentsOnboarding {
}
public void onConnectedToLauncher() {
- if (!ONBOARDING_ENABLED) {
+ if (!ONBOARDING_ENABLED || QuickStepContract.isGesturalMode(mContext)) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index 351627980c08..23e2d277034d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -197,7 +197,7 @@ public class StatusBarWifiView extends FrameLayout implements DarkReceiver,
private boolean updateState(WifiIconState state) {
setContentDescription(state.contentDescription);
if (mState.resId != state.resId && state.resId >= 0) {
- mWifiIcon.setImageDrawable(mContext.getDrawable(mState.resId));
+ mWifiIcon.setImageDrawable(mContext.getDrawable(state.resId));
}
mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index d11eab7bb895..562e535eb42a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -401,7 +401,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void getOutline(View view, Outline outline) {
if (mAmbientState.isDarkAtAll() || !mShowDarkShelf) {
- outline.setRoundRect(mBackgroundAnimationRect, mCornerRadius);
+ float xProgress = mDarkXInterpolator.getInterpolation(
+ (1 - mLinearDarkAmount) * mBackgroundXFactor);
+ outline.setRoundRect(mBackgroundAnimationRect,
+ MathUtils.lerp(mCornerRadius / 2.0f, mCornerRadius,
+ xProgress));
} else {
ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 212666f24b36..3a6756bb677f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -204,6 +204,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
if (!mIsEnabled) {
WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
+ mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -215,6 +216,8 @@ public class EdgeBackGestureHandler implements DisplayListener {
} else {
updateDisplaySize();
+ mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
+ mContext.getMainThreadHandler());
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
@@ -344,7 +347,8 @@ public class EdgeBackGestureHandler implements DisplayListener {
private void updateDisplaySize() {
mContext.getSystemService(DisplayManager.class)
- .getDisplay(mDisplayId).getRealSize(mDisplaySize);
+ .getDisplay(mDisplayId)
+ .getRealSize(mDisplaySize);
}
private void sendEvent(int action, int code) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 1d87a8b439e8..443cc4397bd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -98,8 +98,10 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
// Short-circuiting from UserManager. Needs to be extracted because of SystemUI boolean flag
// qs_show_user_switcher_for_single_user
+ // The default in UserManager is to show the switcher. We want to not show it unless the
+ // user explicitly requests it in Settings
final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.USER_SWITCHER_ENABLED, 1) != 0;
+ Settings.Global.USER_SWITCHER_ENABLED, 0) != 0;
if (!UserManager.supportsMultipleUsers()
|| mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 3d716a18c50a..835db6f532db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -465,9 +465,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
final boolean useAltBack =
(mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- float degrees = useAltBack
- ? (isRtl ? 270 : -90)
- : (isRtl ? 180 : 0);
+ float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 03c89c60360f..dd0c3443f2ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -37,6 +37,7 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.view.ContextThemeWrapper;
+import android.view.View;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -79,9 +80,10 @@ public class KeyButtonDrawable extends Drawable {
private final ShadowDrawableState mState;
private AnimatedVectorDrawable mAnimatedDrawable;
- public KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor) {
+ public KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor,
+ boolean horizontalFlip) {
this(d, new ShadowDrawableState(lightColor, darkColor,
- d instanceof AnimatedVectorDrawable));
+ d instanceof AnimatedVectorDrawable, horizontalFlip));
}
private KeyButtonDrawable(Drawable d, ShadowDrawableState state) {
@@ -282,7 +284,12 @@ public class KeyButtonDrawable extends Drawable {
// Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
final Drawable d = mState.mChildState.newDrawable().mutate();
setDrawableBounds(d);
+ canvas.save();
+ if (mState.mHorizontalFlip) {
+ canvas.scale(-1f, 1f, width * 0.5f, height * 0.5f);
+ }
d.draw(canvas);
+ canvas.restore();
if (mState.mIsHardwareBitmap) {
bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
@@ -305,7 +312,12 @@ public class KeyButtonDrawable extends Drawable {
// Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
final Drawable d = mState.mChildState.newDrawable().mutate();
setDrawableBounds(d);
+ canvas.save();
+ if (mState.mHorizontalFlip) {
+ canvas.scale(-1f, 1f, width * 0.5f, height * 0.5f);
+ }
d.draw(canvas);
+ canvas.restore();
// Draws the shadow from original drawable
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
@@ -357,6 +369,7 @@ public class KeyButtonDrawable extends Drawable {
int mShadowColor;
float mDarkIntensity;
int mAlpha;
+ boolean mHorizontalFlip;
boolean mIsHardwareBitmap;
Bitmap mLastDrawnIcon;
@@ -368,11 +381,12 @@ public class KeyButtonDrawable extends Drawable {
final boolean mSupportsAnimation;
public ShadowDrawableState(@ColorInt int lightColor, @ColorInt int darkColor,
- boolean animated) {
+ boolean animated, boolean horizontalFlip) {
mLightColor = lightColor;
mDarkColor = darkColor;
mSupportsAnimation = animated;
mAlpha = 255;
+ mHorizontalFlip = horizontalFlip;
}
@Override
@@ -400,7 +414,7 @@ public class KeyButtonDrawable extends Drawable {
* @return KeyButtonDrawable
*/
public static KeyButtonDrawable create(@NonNull Context ctx, @DrawableRes int icon,
- boolean hasShadow) {
+ boolean hasShadow) {
final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
@@ -409,7 +423,7 @@ public class KeyButtonDrawable extends Drawable {
}
public static KeyButtonDrawable create(Context lightContext, Context darkContext,
- @DrawableRes int iconResId, boolean hasShadow) {
+ @DrawableRes int iconResId, boolean hasShadow) {
return create(lightContext,
Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor),
Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor),
@@ -418,10 +432,12 @@ public class KeyButtonDrawable extends Drawable {
public static KeyButtonDrawable create(Context context, @ColorInt int lightColor,
@ColorInt int darkColor, @DrawableRes int iconResId, boolean hasShadow) {
- final KeyButtonDrawable drawable = new KeyButtonDrawable(context.getDrawable(iconResId),
- lightColor, darkColor);
+ final Resources res = context.getResources();
+ boolean isRtl = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ Drawable d = context.getDrawable(iconResId);
+ final KeyButtonDrawable drawable = new KeyButtonDrawable(d, lightColor, darkColor,
+ isRtl && d.isAutoMirrored());
if (hasShadow) {
- final Resources res = context.getResources();
int offsetX = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_x);
int offsetY = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_y);
int radius = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_radius);
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
new file mode 100644
index 000000000000..f318f8f94e50
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -0,0 +1,123 @@
+/*
+ * 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.systemui.theme;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.om.OverlayManager;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+
+import com.google.android.collect.Sets;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Controls the application of theme overlays across the system for all users.
+ * This service is responsible for:
+ * - Observing changes to Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES and applying the
+ * corresponding overlays across the system
+ * - Observing user switches, applying the overlays for the current user to user 0 (for systemui)
+ * - Observing work profile changes and applying overlays from the primary user to their
+ * associated work profiles
+ */
+public class ThemeOverlayController extends SystemUI {
+ private static final String TAG = "ThemeOverlayController";
+ private static final boolean DEBUG = false;
+
+ private ThemeOverlayManager mThemeManager;
+ private UserManager mUserManager;
+
+ @Override
+ public void start() {
+ if (DEBUG) Log.d(TAG, "Start");
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mThemeManager = new ThemeOverlayManager(
+ mContext.getSystemService(OverlayManager.class),
+ mContext.getString(R.string.launcher_overlayable_package));
+ final Handler bgHandler = Dependency.get(Dependency.BG_HANDLER);
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
+ updateThemeOverlays();
+ }
+ }, UserHandle.ALL, filter, null, bgHandler);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
+ false,
+ new ContentObserver(bgHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId);
+ if (ActivityManager.getCurrentUser() == userId) {
+ updateThemeOverlays();
+ }
+ }
+ },
+ UserHandle.USER_ALL);
+ }
+
+ private void updateThemeOverlays() {
+ final int currentUser = ActivityManager.getCurrentUser();
+ final String overlayPackageJson = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
+ currentUser);
+ if (DEBUG) Log.d(TAG, "updateThemeOverlays: " + overlayPackageJson);
+ final Map<String, String> categoryToPackage = new ArrayMap<>();
+ if (!TextUtils.isEmpty(overlayPackageJson)) {
+ try {
+ JSONObject object = new JSONObject(overlayPackageJson);
+ for (String category : ThemeOverlayManager.THEME_CATEGORIES) {
+ if (object.has(category)) {
+ categoryToPackage.put(category, object.getString(category));
+ }
+ }
+ } catch (JSONException e) {
+ Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
+ }
+ }
+ Set<UserHandle> userHandles = Sets.newHashSet(UserHandle.of(currentUser));
+ for (UserInfo userInfo : mUserManager.getEnabledProfiles(currentUser)) {
+ if (userInfo.isManagedProfile()) {
+ userHandles.add(userInfo.getUserHandle());
+ }
+ }
+ mThemeManager.applyCurrentUserOverlays(categoryToPackage, userHandles);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
new file mode 100644
index 000000000000..1a9fd5315c32
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.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.systemui.theme;
+
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.google.android.collect.Sets;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+class ThemeOverlayManager {
+ private static final String TAG = "ThemeOverlayManager";
+ private static final boolean DEBUG = false;
+
+ @VisibleForTesting
+ static final String ANDROID_PACKAGE = "android";
+ @VisibleForTesting
+ static final String SETTINGS_PACKAGE = "com.android.settings";
+ @VisibleForTesting
+ static final String SYSUI_PACKAGE = "com.android.systemui";
+
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_COLOR = "android.theme.customization.accent_color";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_FONT = "android.theme.customization.font";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_SHAPE =
+ "android.theme.customization.adaptive_icon_shape";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_ICON_ANDROID =
+ "android.theme.customization.icon_pack.android";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_ICON_SYSUI =
+ "android.theme.customization.icon_pack.systemui";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_ICON_SETTINGS =
+ "android.theme.customization.icon_pack.settings";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_ICON_LAUNCHER =
+ "android.theme.customization.icon_pack.launcher";
+
+ /* All theme customization categories used by the system. */
+ static final Set<String> THEME_CATEGORIES = Sets.newHashSet(
+ OVERLAY_CATEGORY_COLOR,
+ OVERLAY_CATEGORY_FONT,
+ OVERLAY_CATEGORY_SHAPE,
+ OVERLAY_CATEGORY_ICON_ANDROID,
+ OVERLAY_CATEGORY_ICON_SYSUI,
+ OVERLAY_CATEGORY_ICON_SETTINGS,
+ OVERLAY_CATEGORY_ICON_LAUNCHER);
+
+ /* Categories that need to applied to the current user as well as the system user. */
+ @VisibleForTesting
+ static final Set<String> SYSTEM_USER_CATEGORIES = Sets.newHashSet(
+ OVERLAY_CATEGORY_COLOR,
+ OVERLAY_CATEGORY_FONT,
+ OVERLAY_CATEGORY_SHAPE,
+ OVERLAY_CATEGORY_ICON_ANDROID,
+ OVERLAY_CATEGORY_ICON_SYSUI);
+
+ /* Allowed overlay categories for each target package. */
+ private final Map<String, Set<String>> mTargetPackageToCategories = new ArrayMap<>();
+ /* Target package for each overlay category. */
+ private final Map<String, String> mCategoryToTargetPackage = new ArrayMap<>();
+ private final OverlayManager mOverlayManager;
+ private final String mLauncherPackage;
+
+ ThemeOverlayManager(OverlayManager overlayManager, String launcherPackage) {
+ mOverlayManager = overlayManager;
+ mLauncherPackage = launcherPackage;
+ mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet(
+ OVERLAY_CATEGORY_COLOR, OVERLAY_CATEGORY_FONT,
+ OVERLAY_CATEGORY_SHAPE, OVERLAY_CATEGORY_ICON_ANDROID));
+ mTargetPackageToCategories.put(SYSUI_PACKAGE,
+ Sets.newHashSet(OVERLAY_CATEGORY_ICON_SYSUI));
+ mTargetPackageToCategories.put(SETTINGS_PACKAGE,
+ Sets.newHashSet(OVERLAY_CATEGORY_ICON_SETTINGS));
+ mTargetPackageToCategories.put(mLauncherPackage,
+ Sets.newHashSet(OVERLAY_CATEGORY_ICON_LAUNCHER));
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_COLOR, ANDROID_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_FONT, ANDROID_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_SHAPE, ANDROID_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_ANDROID, ANDROID_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SYSUI, SYSUI_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SETTINGS, SETTINGS_PACKAGE);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_LAUNCHER, mLauncherPackage);
+ }
+
+ /**
+ * Apply the set of overlay packages to the set of {@code UserHandle}s provided. Overlays that
+ * affect sysui will also be applied to the system user.
+ */
+ void applyCurrentUserOverlays(
+ Map<String, String> categoryToPackage, Set<UserHandle> userHandles) {
+ final Map<Boolean, List<String>> categorySplit = THEME_CATEGORIES.stream().collect(
+ Collectors.partitioningBy((category) -> categoryToPackage.containsKey(category)));
+ final List<String> overlayCategoriesToEnable = categorySplit.get(true);
+ final List<String> overlayCategoriesToDisable = categorySplit.get(false);
+
+ // Disable all overlays that have not been specified in the user setting.
+ final List<OverlayInfo> overlays = new ArrayList<>();
+ overlayCategoriesToDisable.stream()
+ .map(category -> mCategoryToTargetPackage.get(category))
+ .collect(Collectors.toSet())
+ .forEach(targetPackage -> overlays.addAll(mOverlayManager
+ .getOverlayInfosForTarget(targetPackage, UserHandle.SYSTEM)));
+ overlays.stream()
+ .filter(o ->
+ mTargetPackageToCategories.get(o.targetPackageName).contains(o.category))
+ .filter(o -> overlayCategoriesToDisable.contains(o.category))
+ .filter(o -> o.isEnabled())
+ .forEach(o -> setEnabled(o.packageName, o.category, userHandles, false));
+
+
+ // Enable all overlays specified in the user setting.
+ overlayCategoriesToEnable.forEach((category) ->
+ setEnabled(categoryToPackage.get(category), category, userHandles, true));
+ }
+
+ private void setEnabled(
+ String packageName, String category, Set<UserHandle> handles, boolean enabled) {
+ for (UserHandle userHandle : handles) {
+ setEnabled(packageName, userHandle, enabled);
+ }
+ if (!handles.contains(UserHandle.SYSTEM) && SYSTEM_USER_CATEGORIES.contains(category)) {
+ setEnabled(packageName, UserHandle.SYSTEM, enabled);
+ }
+ }
+
+ private void setEnabled(String pkg, UserHandle userHandle, boolean enabled) {
+ if (DEBUG) Log.d(TAG, String.format("setEnabled: %s %s %b", pkg, userHandle, enabled));
+ if (enabled) {
+ mOverlayManager.setEnabledExclusiveInCategory(pkg, userHandle);
+ } else {
+ mOverlayManager.setEnabled(pkg, false, userHandle);
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
index e3c081ea2a67..c837c9ccea95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
@@ -179,8 +179,10 @@ public class NavigationBarContextTest extends SysuiTestCase {
final int unusedColor = 0;
final Drawable d = mock(Drawable.class);
final ContextualButton button = spy(mBtn0);
- final KeyButtonDrawable kbd1 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor));
- final KeyButtonDrawable kbd2 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor));
+ final KeyButtonDrawable kbd1 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor,
+ false /* horizontalFlip */));
+ final KeyButtonDrawable kbd2 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor,
+ false /* horizontalFlip */));
kbd1.setDarkIntensity(TEST_DARK_INTENSITY);
kbd2.setDarkIntensity(0f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java
new file mode 100644
index 000000000000..da039a403087
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.systemui.theme;
+
+import static com.android.systemui.theme.ThemeOverlayManager.ANDROID_PACKAGE;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_COLOR;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_FONT;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_ANDROID;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_LAUNCHER;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_SETTINGS;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_SYSUI;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_SHAPE;
+import static com.android.systemui.theme.ThemeOverlayManager.SETTINGS_PACKAGE;
+import static com.android.systemui.theme.ThemeOverlayManager.SYSTEM_USER_CATEGORIES;
+import static com.android.systemui.theme.ThemeOverlayManager.SYSUI_PACKAGE;
+import static com.android.systemui.theme.ThemeOverlayManager.THEME_CATEGORIES;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayManager;
+import android.os.UserHandle;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import com.google.android.collect.Maps;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ThemeOverlayManagerTest extends SysuiTestCase {
+ private static final String TEST_DISABLED_PREFIX = "com.example.";
+ private static final String TEST_ENABLED_PREFIX = "com.example.enabled.";
+
+ private static final Map<String, String> ALL_CATEGORIES_MAP = Maps.newArrayMap();
+
+ static {
+ for (String category : THEME_CATEGORIES) {
+ ALL_CATEGORIES_MAP.put(category, TEST_DISABLED_PREFIX + category);
+ }
+ }
+
+ private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
+ private static final UserHandle TEST_USER = UserHandle.of(5);
+ private static final Set<UserHandle> TEST_USER_HANDLES = Sets.newHashSet(TEST_USER);
+
+ @Mock
+ OverlayManager mOverlayManager;
+
+ private ThemeOverlayManager mManager;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mManager = new ThemeOverlayManager(mOverlayManager, LAUNCHER_PACKAGE);
+ when(mOverlayManager.getOverlayInfosForTarget(ANDROID_PACKAGE, UserHandle.SYSTEM))
+ .thenReturn(Lists.newArrayList(
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_COLOR,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_COLOR, false),
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_FONT,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, false),
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE, false),
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_ICON_ANDROID, false),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_COLOR,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_COLOR, true),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_FONT,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, true),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE, true),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_ICON_ANDROID, true)));
+ when(mOverlayManager.getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM))
+ .thenReturn(Lists.newArrayList(
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_SYSUI,
+ SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI, false),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SYSUI,
+ SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI, true)));
+ when(mOverlayManager.getOverlayInfosForTarget(SETTINGS_PACKAGE, UserHandle.SYSTEM))
+ .thenReturn(Lists.newArrayList(
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS,
+ SETTINGS_PACKAGE, OVERLAY_CATEGORY_ICON_SETTINGS, false),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS,
+ SETTINGS_PACKAGE, OVERLAY_CATEGORY_ICON_SETTINGS, true)));
+ when(mOverlayManager.getOverlayInfosForTarget(LAUNCHER_PACKAGE, UserHandle.SYSTEM))
+ .thenReturn(Lists.newArrayList(
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_LAUNCHER,
+ LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, false),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_LAUNCHER,
+ LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, true)));
+ }
+
+ @Test
+ public void allCategoriesSpecified_allEnabledExclusively() {
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, TEST_USER_HANDLES);
+
+ for (String overlayPackage : ALL_CATEGORIES_MAP.values()) {
+ verify(mOverlayManager).setEnabledExclusiveInCategory(overlayPackage, TEST_USER);
+ }
+ }
+
+ @Test
+ public void allCategoriesSpecified_sysuiCategoriesAlsoAppliedToSysuiUser() {
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, TEST_USER_HANDLES);
+
+ for (Map.Entry<String, String> entry : ALL_CATEGORIES_MAP.entrySet()) {
+ if (SYSTEM_USER_CATEGORIES.contains(entry.getKey())) {
+ verify(mOverlayManager).setEnabledExclusiveInCategory(
+ entry.getValue(), UserHandle.SYSTEM);
+ } else {
+ verify(mOverlayManager, never()).setEnabledExclusiveInCategory(
+ entry.getValue(), UserHandle.SYSTEM);
+ }
+ }
+ }
+
+ @Test
+ public void allCategoriesSpecified_enabledForAllUserHandles() {
+ Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
+ UserHandle newUserHandle = UserHandle.of(10);
+ userHandles.add(newUserHandle);
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, userHandles);
+
+ for (String overlayPackage : ALL_CATEGORIES_MAP.values()) {
+ verify(mOverlayManager).setEnabledExclusiveInCategory(overlayPackage, TEST_USER);
+ verify(mOverlayManager).setEnabledExclusiveInCategory(overlayPackage, newUserHandle);
+ }
+ }
+
+ @Test
+ public void allCategoriesSpecified_overlayManagerNotQueried() {
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, TEST_USER_HANDLES);
+
+ verify(mOverlayManager, never())
+ .getOverlayInfosForTarget(anyString(), any(UserHandle.class));
+ }
+
+ @Test
+ public void someCategoriesSpecified_specifiedEnabled_unspecifiedDisabled() {
+ Map<String, String> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
+ categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
+ categoryToPackage.remove(OVERLAY_CATEGORY_ICON_ANDROID);
+
+ mManager.applyCurrentUserOverlays(categoryToPackage, TEST_USER_HANDLES);
+
+ for (String overlayPackage : categoryToPackage.values()) {
+ verify(mOverlayManager).setEnabledExclusiveInCategory(overlayPackage, TEST_USER);
+ }
+ verify(mOverlayManager).setEnabled(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS,
+ false, TEST_USER);
+ verify(mOverlayManager).setEnabled(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID,
+ false, TEST_USER);
+ }
+
+ @Test
+ public void zeroCategoriesSpecified_allDisabled() {
+ mManager.applyCurrentUserOverlays(Maps.newArrayMap(), TEST_USER_HANDLES);
+
+ for (String category : THEME_CATEGORIES) {
+ verify(mOverlayManager).setEnabled(TEST_ENABLED_PREFIX + category, false, TEST_USER);
+ }
+ }
+
+ @Test
+ public void nonThemeCategorySpecified_ignored() {
+ Map<String, String> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
+ categoryToPackage.put("blah.category", "com.example.blah.category");
+
+ mManager.applyCurrentUserOverlays(categoryToPackage, TEST_USER_HANDLES);
+
+ verify(mOverlayManager, never()).setEnabled("com.example.blah.category", false, TEST_USER);
+ verify(mOverlayManager, never()).setEnabledExclusiveInCategory("com.example.blah.category",
+ TEST_USER);
+ }
+
+ @Test
+ public void overlayManagerOnlyQueriedForUnspecifiedPackages() {
+ Map<String, String> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
+ categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
+
+ mManager.applyCurrentUserOverlays(categoryToPackage, TEST_USER_HANDLES);
+
+ verify(mOverlayManager).getOverlayInfosForTarget(SETTINGS_PACKAGE, UserHandle.SYSTEM);
+ verify(mOverlayManager, never()).getOverlayInfosForTarget(ANDROID_PACKAGE,
+ UserHandle.SYSTEM);
+ verify(mOverlayManager, never()).getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM);
+ verify(mOverlayManager, never()).getOverlayInfosForTarget(LAUNCHER_PACKAGE,
+ UserHandle.SYSTEM);
+ }
+
+ private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName,
+ String category, boolean enabled) {
+ return new OverlayInfo(packageName, targetPackageName, null, category, "",
+ enabled ? OverlayInfo.STATE_ENABLED : OverlayInfo.STATE_DISABLED, 0, 0, false);
+ }
+}
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_perm_group_sms.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml
index d15cfa3b1e3a..d15cfa3b1e3a 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_perm_group_sms.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
index 87d82e58cd67..87d82e58cd67 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
new file mode 100644
index 000000000000..4e5497a76991
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10c5.52,0,10-4.48,10-10S17.52,2,12,2z M12,17v-1.5h7.74 c-0.24,0.53-0.54,1.03-0.88,1.5H12z M12,14v-1.5h8.47c-0.03,0.51-0.1,1.01-0.22,1.5H12z M12,11V9.5h8.12 c0.15,0.48,0.25,0.99,0.31,1.5H12z M12,8V6.5h6.47c0.39,0.46,0.74,0.96,1.03,1.5H12z M16.81,5H12V3.5C13.79,3.5,15.44,4.06,16.81,5 z M3.5,12c0-4.17,3.03-7.65,7-8.36v16.72C6.53,19.65,3.5,16.17,3.5,12z M12,18.5h5.47c-1.48,1.25-3.39,2-5.47,2V18.5z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_perm_group_sms.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml
index eef9e62f15b0..eef9e62f15b0 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_perm_group_sms.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
index b4baf231d1b6..b4baf231d1b6 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
new file mode 100644
index 000000000000..6b5903c569c0
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M11,19.93C7.06,19.44,4,16.08,4,12 c0-4.08,3.05-7.44,7-7.93V19.93z M13,4.07C14.03,4.2,15,4.52,15.87,5H13V4.07z M13,7h5.24c0.25,0.31,0.48,0.65,0.68,1H13V7z M13,19.93V19h2.87C15,19.48,14.03,19.8,13,19.93z M18.24,17H13v-1h5.92C18.72,16.35,18.49,16.69,18.24,17z M19.74,14H13v-1h6.93 C19.89,13.34,19.82,13.67,19.74,14z M19.93,11H13v-1h6.74C19.82,10.33,19.89,10.66,19.93,11z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_perm_group_sms.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml
index b5509d12a059..b5509d12a059 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_perm_group_sms.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
index 5f704f0ed828..5f704f0ed828 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_do_not_disturb_on_24dp.xml
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
new file mode 100644
index 000000000000..308c2ab34563
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_gray_scale_24dp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10c5.52,0,10-4.48,10-10S17.52,2,12,2z M12,12.5h8.47c-0.03,0.51-0.1,1.01-0.22,1.5 H12V12.5z M12,11V9.5h8.12c0.15,0.48,0.25,0.99,0.31,1.5H12z M12,8V6.5h6.47c0.39,0.46,0.74,0.96,1.03,1.5H12z M16.81,5H12V3.5 C13.79,3.5,15.44,4.06,16.81,5z M3.5,12c0-4.17,3.03-7.65,7-8.36v16.72C6.53,19.65,3.5,16.17,3.5,12z M12,18.5h5.47 c-1.48,1.25-3.39,2-5.47,2V18.5z M18.86,17H12v-1.5h7.74C19.5,16.03,19.2,16.53,18.86,17z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
index 2e2ea085f396..2e662684438f 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -21,5 +21,8 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M20.49,11.26h-1.03c-0.15-1.51-0.74-2.88-1.65-3.99l0.73-0.73c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0L16.75,6.2 c-1.11-0.91-2.49-1.51-4-1.66V3.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.04c-1.5,0.15-2.88,0.75-3.99,1.65L6.53,5.46 c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L6.2,7.25c-0.91,1.11-1.51,2.49-1.66,3.99H3.51c-0.41,0-0.75,0.34-0.75,0.75 s0.34,0.75,0.75,0.75h1.03c0.15,1.51,0.74,2.88,1.65,3.99l-0.73,0.73c-0.29,0.29-0.29,0.77,0,1.06c0.15,0.15,0.34,0.22,0.53,0.22 s0.38-0.07,0.53-0.22l0.73-0.73c1.11,0.91,2.48,1.51,3.98,1.66v1.02c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.02 c1.48-0.14,2.86-0.71,4.01-1.65l0.73,0.73c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06 l-0.72-0.72c0.94-1.14,1.51-2.52,1.66-4h1.03c0.41,0,0.75-0.34,0.75-0.75S20.9,11.26,20.49,11.26z M12,18c-3.31,0-6-2.69-6-6 s2.69-6,6-6s6,2.69,6,6S15.31,18,12,18z" />
+ android:pathData="M21.25,11.25h-2.8A6.46,6.46,0,0,0,17.09,8l2-2A0.75 0.75 ,0,0,0,18,4.93l-2,2a6.46,6.46,0,0,0-3.28-1.36V2.75a0.75 0.75 ,0,0,0-1.5,0v2.8A6.46,6.46,0,0,0,8,6.91l-2-2A0.75 0.75 ,0,0,0,4.93,6l2,2a6.46,6.46,0,0,0-1.36,3.28H2.75a0.75 0.75 ,0,0,0,0,1.5h2.8A6.46,6.46,0,0,0,6.91,16l-2,2A0.75 0.75 ,0,0,0,6,19.07l2-2a6.46,6.46,0,0,0,3.28,1.36v2.8a0.75 0.75 ,0,0,0,1.5,0v-2.8A6.46,6.46,0,0,0,16,17.09l2,2A0.75 0.75 ,0,0,0,19.07,18l-2-2a6.46,6.46,0,0,0,1.36-3.28h2.8a0.75 0.75 ,0,0,0,0-1.5ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,15.5a3.5,3.5,0,0,0,0-7Z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
index 2e4665e59f1e..697d1c29eac7 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="?android:attr/colorControlActivated"
- android:pathData="M22.46,11.25h-3.02c-0.15-1.51-0.75-2.88-1.66-4l2.17-2.17c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0l-2.18,2.18 c-1.11-0.91-2.49-1.51-3.99-1.66V1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v3.04c-1.5,0.15-2.88,0.75-3.99,1.65 L5.06,4.01C4.77,3.71,4.29,3.71,4,4.01S3.71,4.77,4,5.07l2.18,2.18c-0.91,1.11-1.51,2.48-1.66,3.98H1.48 c-0.41,0-0.75,0.34-0.75,0.75s0.34,0.75,0.75,0.75h3.04c0.15,1.51,0.74,2.88,1.65,3.99L3.99,18.9c-0.29,0.29-0.29,0.77,0,1.06 c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22l2.17-2.17c1.11,0.91,2.49,1.52,3.99,1.67v3.02c0,0.41,0.34,0.75,0.75,0.75 s0.75-0.34,0.75-0.75v-3.02c1.48-0.14,2.86-0.71,4.01-1.65l2.16,2.16c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22 c0.29-0.29,0.29-0.77,0-1.06l-2.16-2.16c0.94-1.15,1.52-2.53,1.66-4.01h3.02c0.41,0,0.75-0.34,0.75-0.75S22.88,11.25,22.46,11.25z M12,18c-3.31,0-6-2.69-6-6s2.69-6,6-6s6,2.69,6,6S15.31,18,12,18z" />
- <path
android:fillColor="?android:attr/colorPrimary"
- android:pathData="M 12 6 C 15.313708499 6 18 8.68629150102 18 12 C 18 15.313708499 15.313708499 18 12 18 C 8.68629150102 18 6 15.313708499 6 12 C 6 8.68629150102 8.68629150102 6 12 6 Z" />
+ android:pathData="M 12 0 L 12 0 Q 24 0 24 12 L 24 12 Q 24 24 12 24 L 12 24 Q 0 24 0 12 L 0 12 Q 0 0 12 0 Z" />
+ <path
+ android:fillColor="?android:attr/colorControlActivated"
+ android:pathData="M21.25,11.25h-2.8A6.46,6.46,0,0,0,17.09,8l2-2A0.75 0.75 ,0,0,0,18,4.93l-2,2a6.46,6.46,0,0,0-3.28-1.36V2.75a0.75 0.75 ,0,0,0-1.5,0v2.8A6.46,6.46,0,0,0,8,6.91l-2-2A0.75 0.75 ,0,0,0,4.93,6l2,2a6.46,6.46,0,0,0-1.36,3.28H2.75a0.75 0.75 ,0,0,0,0,1.5h2.8A6.46,6.46,0,0,0,6.91,16l-2,2A0.75 0.75 ,0,0,0,6,19.07l2-2a6.46,6.46,0,0,0,3.28,1.36v2.8a0.75 0.75 ,0,0,0,1.5,0v-2.8A6.46,6.46,0,0,0,16,17.09l2,2A0.75 0.75 ,0,0,0,19.07,18l-2-2a6.46,6.46,0,0,0,1.36-3.28h2.8a0.75 0.75 ,0,0,0,0-1.5ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z" />
</vector> \ No newline at end of file
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 640525411239..57de67e1a38c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -133,6 +133,7 @@ import android.os.ServiceSpecificException;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -1628,8 +1629,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private boolean disallowedBecauseSystemCaller() {
// TODO: start throwing a SecurityException when GnssLocationProvider stops calling
- // requestRouteToHost.
- if (isSystem(Binder.getCallingUid())) {
+ // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
+ // for devices launched with Q and above. However, existing devices upgrading to Q and
+ // above must continued to be supported for few more releases.
+ if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
+ "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
log("This method exists only for app backwards compatibility"
+ " and must not be called by system services.");
return true;
@@ -1767,11 +1771,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// caller type. Need to re-factor NetdEventListenerService to allow multiple
// NetworkMonitor registrants.
if (nai != null && nai.satisfies(mDefaultRequest)) {
- try {
- nai.networkMonitor().notifyDnsResponse(returnCode);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ Binder.withCleanCallingIdentity(() ->
+ nai.networkMonitor().notifyDnsResponse(returnCode));
}
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 126bf6556538..2cfcecca5f99 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -96,9 +96,10 @@ public class IpSecService extends IIpSecService.Stub {
new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
- private static final int MAX_PORT_BIND_ATTEMPTS = 10;
private static final InetAddress INADDR_ANY;
+ @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
+
static {
try {
INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 0786b1819b71..da9cffa73585 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3836,9 +3836,9 @@ class StorageManagerService extends IStorageManager.Stub
}
// Determine if caller is holding runtime permission
- final boolean hasRead = StorageManager.checkPermissionAndAppOp(mContext, false, 0,
+ final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
- final boolean hasWrite = StorageManager.checkPermissionAndAppOp(mContext, false, 0,
+ final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
// STOPSHIP: remove this temporary hack once we have dynamic runtime
// permissions fully enabled again
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index 5cc9bfd52b13..6bb3200f7cc1 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -22,9 +22,10 @@ import android.util.Slog;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.Preconditions;
+import com.android.server.am.ActivityManagerService;
+import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -47,6 +48,8 @@ public class SystemServerInitThreadPool {
private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(4,
"system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
+ private List<String> mPendingTasks = new ArrayList<>();
+
public static synchronized SystemServerInitThreadPool get() {
if (sInstance == null) {
sInstance = new SystemServerInitThreadPool();
@@ -57,19 +60,26 @@ public class SystemServerInitThreadPool {
}
public Future<?> submit(Runnable runnable, String description) {
- if (IS_DEBUGGABLE) {
- return mService.submit(() -> {
- Slog.d(TAG, "Started executing " + description);
- try {
- runnable.run();
- } catch (RuntimeException e) {
- Slog.e(TAG, "Failure in " + description + ": " + e, e);
- throw e;
- }
- Slog.d(TAG, "Finished executing " + description);
- });
+ synchronized (mPendingTasks) {
+ mPendingTasks.add(description);
}
- return mService.submit(runnable);
+ return mService.submit(() -> {
+ if (IS_DEBUGGABLE) {
+ Slog.d(TAG, "Started executing " + description);
+ }
+ try {
+ runnable.run();
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "Failure in " + description + ": " + e, e);
+ throw e;
+ }
+ synchronized (mPendingTasks) {
+ mPendingTasks.remove(description);
+ }
+ if (IS_DEBUGGABLE) {
+ Slog.d(TAG, "Finished executing " + description);
+ }
+ });
}
static synchronized void shutdown() {
@@ -81,16 +91,36 @@ public class SystemServerInitThreadPool {
TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
+ dumpStackTraces();
throw new IllegalStateException(TAG + " init interrupted");
}
+ if (!terminated) {
+ // dump stack must be called before shutdownNow() to collect stacktrace of threads
+ // in the thread pool.
+ dumpStackTraces();
+ }
List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
if (!terminated) {
+ final List<String> copy = new ArrayList<>();
+ synchronized (sInstance.mPendingTasks) {
+ copy.addAll(sInstance.mPendingTasks);
+ }
throw new IllegalStateException("Cannot shutdown. Unstarted tasks "
- + unstartedRunnables);
+ + unstartedRunnables + " Unfinished tasks " + copy);
}
sInstance.mService = null; // Make mService eligible for GC
+ sInstance.mPendingTasks = null;
Slog.d(TAG, "Shutdown successful");
}
}
+ /**
+ * A helper function to call ActivityManagerService.dumpStackTraces().
+ */
+ private static void dumpStackTraces() {
+ final ArrayList<Integer> pids = new ArrayList<>();
+ pids.add(Process.myPid());
+ ActivityManagerService.dumpStackTraces(
+ pids, null, null, null);
+ }
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index c647e2ed824f..ac584e9571fc 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1304,12 +1304,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return;
}
if (VDBG) {
- log("notifyUserMobileDataStateChangedForSubscriberPhoneID: subId=" + phoneId
- + " state=" + state);
+ log("notifyUserMobileDataStateChangedForSubscriberPhoneID: PhoneId=" + phoneId
+ + " subId=" + subId + " state=" + state);
}
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mMessageWaiting[phoneId] = state;
+ mUserMobileDataState[phoneId] = state;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) &&
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 5d47c9dfdddd..44d435f2b539 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1262,15 +1262,16 @@ public final class OomAdjuster {
// processes). These should not bring the current process
// into the top state, since they are not on top. Instead
// give them the best bound state after that.
+ final int bestState = cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)
+ ? PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
+ : PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
if ((cr.flags & Context.BIND_FOREGROUND_SERVICE) != 0) {
- clientProcState =
- PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ clientProcState = bestState;
} else if (mService.mWakefulness
== PowerManagerInternal.WAKEFULNESS_AWAKE
&& (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
!= 0) {
- clientProcState =
- PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ clientProcState = bestState;
} else {
clientProcState =
PROCESS_STATE_IMPORTANT_FOREGROUND;
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index bc78d1ad751f..3dbea0d1978e 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -22,7 +22,6 @@ import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCE
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
import android.Manifest;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
@@ -51,6 +50,7 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.attention.AttentionService;
import android.service.attention.AttentionService.AttentionFailureCodes;
+import android.service.attention.AttentionService.AttentionSuccessCodes;
import android.service.attention.IAttentionCallback;
import android.service.attention.IAttentionService;
import android.text.TextUtils;
@@ -75,6 +75,7 @@ import java.io.PrintWriter;
*/
public class AttentionManagerService extends SystemService {
private static final String LOG_TAG = "AttentionManagerService";
+ private static final boolean DEBUG = false;
/**
* DeviceConfig flag name, allows a CTS to inject a fake implementation.
@@ -156,7 +157,11 @@ public class AttentionManagerService extends SystemService {
/**
* Checks whether user attention is at the screen and calls in the provided callback.
*
- * @return {@code true} if the framework was able to send the provided callback to the service
+ * Calling this multiple times quickly in a row will result in either a) returning a cached
+ * value, if present, or b) returning {@code false} because only one active request at a time is
+ * allowed.
+ *
+ * @return {@code true} if the framework was able to dispatch the request
*/
private boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
Preconditions.checkNotNull(callbackInternal);
@@ -182,54 +187,30 @@ public class AttentionManagerService extends SystemService {
return false;
}
- if (userState.mService == null) {
- // make sure every callback is called back
- if (userState.mPendingAttentionCheck != null) {
- userState.mPendingAttentionCheck.cancel(
- ATTENTION_FAILURE_CANCELLED);
+ // throttle frequent requests
+ final AttentionCheckCache cache = userState.mAttentionCheckCache;
+ if (cache != null && now < cache.mLastComputed + STALE_AFTER_MILLIS) {
+ callbackInternal.onSuccess(cache.mResult, cache.mTimestamp);
+ return true;
+ }
+
+ // prevent spamming with multiple requests, only one at a time is allowed
+ if (userState.mCurrentAttentionCheck != null) {
+ if (!userState.mCurrentAttentionCheck.mIsDispatched
+ || !userState.mCurrentAttentionCheck.mIsFulfilled) {
+ return false;
}
- // fire the check when the service is started
- userState.mPendingAttentionCheck = new PendingAttentionCheck(
- callbackInternal, () -> checkAttention(timeout, callbackInternal));
- } else {
- try {
- // throttle frequent requests
- final AttentionCheckCache cache = userState.mAttentionCheckCache;
- if (cache != null && now < cache.mLastComputed + STALE_AFTER_MILLIS) {
- callbackInternal.onSuccess(cache.mResult, cache.mTimestamp);
- return true;
- }
+ }
+ userState.mCurrentAttentionCheck = createAttentionCheck(callbackInternal, userState);
+
+ if (userState.mService != null) {
+ try {
// schedule request cancellation if not returned by that point yet
cancelAfterTimeoutLocked(timeout);
-
- userState.mCurrentAttentionCheck = new AttentionCheck(callbackInternal,
- new IAttentionCallback.Stub() {
- @Override
- public void onSuccess(int result, long timestamp) {
- callbackInternal.onSuccess(result, timestamp);
- synchronized (mLock) {
- userState.mAttentionCheckCache = new AttentionCheckCache(
- SystemClock.uptimeMillis(), result,
- timestamp);
- userState.mCurrentAttentionCheckIsFulfilled = true;
- }
- StatsLog.write(
- StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
- result);
- }
-
- @Override
- public void onFailure(int error) {
- callbackInternal.onFailure(error);
- userState.mCurrentAttentionCheckIsFulfilled = true;
- StatsLog.write(
- StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
- error);
- }
- });
userState.mService.checkAttention(
userState.mCurrentAttentionCheck.mIAttentionCallback);
+ userState.mCurrentAttentionCheck.mIsDispatched = true;
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Cannot call into the AttentionService");
return false;
@@ -239,6 +220,44 @@ public class AttentionManagerService extends SystemService {
}
}
+ private AttentionCheck createAttentionCheck(AttentionCallbackInternal callbackInternal,
+ UserState userState) {
+ final IAttentionCallback iAttentionCallback = new IAttentionCallback.Stub() {
+ @Override
+ public void onSuccess(@AttentionSuccessCodes int result, long timestamp) {
+ // the callback might have been cancelled already
+ if (!userState.mCurrentAttentionCheck.mIsFulfilled) {
+ callbackInternal.onSuccess(result, timestamp);
+ userState.mCurrentAttentionCheck.mIsFulfilled = true;
+ }
+
+ synchronized (mLock) {
+ userState.mAttentionCheckCache = new AttentionCheckCache(
+ SystemClock.uptimeMillis(), result,
+ timestamp);
+ }
+ StatsLog.write(
+ StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
+ result);
+ }
+
+ @Override
+ public void onFailure(@AttentionFailureCodes int error) {
+ // the callback might have been cancelled already
+ if (!userState.mCurrentAttentionCheck.mIsFulfilled) {
+ callbackInternal.onFailure(error);
+ userState.mCurrentAttentionCheck.mIsFulfilled = true;
+ }
+
+ StatsLog.write(
+ StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
+ error);
+ }
+ };
+
+ return new AttentionCheck(callbackInternal, iAttentionCallback);
+ }
+
/** Cancels the specified attention check. */
private void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
synchronized (mLock) {
@@ -246,25 +265,13 @@ public class AttentionManagerService extends SystemService {
if (userState == null) {
return;
}
- if (userState.mService == null) {
- if (userState.mPendingAttentionCheck != null
- && userState.mPendingAttentionCheck.mCallbackInternal.equals(
- callbackInternal)) {
- userState.mPendingAttentionCheck.cancel(ATTENTION_FAILURE_UNKNOWN);
- userState.mPendingAttentionCheck = null;
- }
- return;
- }
- if (userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
- try {
- userState.mService.cancelAttentionCheck(
- userState.mCurrentAttentionCheck.mIAttentionCallback);
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Cannot call into the AttentionService");
- }
- } else {
+
+ if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
Slog.e(LOG_TAG, "Cannot cancel a non-current request");
+ return;
}
+
+ cancel(userState);
}
}
@@ -272,6 +279,9 @@ public class AttentionManagerService extends SystemService {
private void disableSelf() {
final long identity = Binder.clearCallingIdentity();
try {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Disabling self.");
+ }
Settings.System.putInt(mContext.getContentResolver(), ADAPTIVE_SLEEP, 0);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -428,34 +438,21 @@ public class AttentionManagerService extends SystemService {
}
}
- private static final class PendingAttentionCheck {
- private final AttentionCallbackInternal mCallbackInternal;
- private final Runnable mRunnable;
-
- PendingAttentionCheck(AttentionCallbackInternal callbackInternal,
- Runnable runnable) {
- mCallbackInternal = callbackInternal;
- mRunnable = runnable;
- }
-
- void cancel(@AttentionFailureCodes int failureCode) {
- mCallbackInternal.onFailure(failureCode);
- }
-
- void run() {
- mRunnable.run();
- }
- }
-
private static final class AttentionCheck {
private final AttentionCallbackInternal mCallbackInternal;
private final IAttentionCallback mIAttentionCallback;
+ private boolean mIsDispatched;
+ private boolean mIsFulfilled;
AttentionCheck(AttentionCallbackInternal callbackInternal,
IAttentionCallback iAttentionCallback) {
mCallbackInternal = callbackInternal;
mIAttentionCallback = iAttentionCallback;
}
+
+ void cancelInternal() {
+ mCallbackInternal.onFailure(ATTENTION_FAILURE_CANCELLED);
+ }
}
private static final class UserState {
@@ -469,11 +466,6 @@ public class AttentionManagerService extends SystemService {
@GuardedBy("mLock")
AttentionCheck mCurrentAttentionCheck;
@GuardedBy("mLock")
- boolean mCurrentAttentionCheckIsFulfilled;
-
- @GuardedBy("mLock")
- PendingAttentionCheck mPendingAttentionCheck;
- @GuardedBy("mLock")
AttentionCheckCache mAttentionCheckCache;
@UserIdInt
@@ -491,9 +483,17 @@ public class AttentionManagerService extends SystemService {
@GuardedBy("mLock")
private void handlePendingCallbackLocked() {
- if (mService != null && mPendingAttentionCheck != null) {
- mPendingAttentionCheck.run();
- mPendingAttentionCheck = null;
+ if (!mCurrentAttentionCheck.mIsDispatched) {
+ if (mService != null) {
+ try {
+ mService.checkAttention(mCurrentAttentionCheck.mIAttentionCallback);
+ mCurrentAttentionCheck.mIsDispatched = true;
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Cannot call into the AttentionService");
+ }
+ } else {
+ mCurrentAttentionCheck.mCallbackInternal.onFailure(ATTENTION_FAILURE_UNKNOWN);
+ }
}
}
@@ -526,7 +526,6 @@ public class AttentionManagerService extends SystemService {
pw.printPair("userId", mUserId);
synchronized (mLock) {
pw.printPair("binding", mBinding);
- pw.printPair("isAttentionCheckPending", mPendingAttentionCheck != null);
}
}
@@ -586,14 +585,7 @@ public class AttentionManagerService extends SystemService {
// Callee is no longer interested in the attention check result - cancel.
case ATTENTION_CHECK_TIMEOUT: {
synchronized (mLock) {
- final UserState userState = peekCurrentUserStateLocked();
- if (userState != null) {
- // If not called back already.
- if (!userState.mCurrentAttentionCheckIsFulfilled) {
- cancel(userState, AttentionService.ATTENTION_FAILURE_TIMED_OUT);
- }
-
- }
+ cancel(peekCurrentUserStateLocked());
}
}
break;
@@ -604,19 +596,30 @@ public class AttentionManagerService extends SystemService {
}
}
- private void cancel(@NonNull UserState userState, @AttentionFailureCodes int failureCode) {
- if (userState.mService != null) {
- try {
- userState.mService.cancelAttentionCheck(
- userState.mCurrentAttentionCheck.mIAttentionCallback);
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Unable to cancel attention check");
- }
+ private void cancel(UserState userState) {
+ if (userState == null || userState.mCurrentAttentionCheck == null) {
+ return;
+ }
- if (userState.mPendingAttentionCheck != null) {
- userState.mPendingAttentionCheck.cancel(failureCode);
- userState.mPendingAttentionCheck = null;
+ if (userState.mCurrentAttentionCheck.mIsFulfilled) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Trying to cancel the check that has been already fulfilled.");
}
+ return;
+ }
+ userState.mCurrentAttentionCheck.mIsFulfilled = true;
+
+ if (userState.mService == null) {
+ userState.mCurrentAttentionCheck.cancelInternal();
+ return;
+ }
+
+ try {
+ userState.mService.cancelAttentionCheck(
+ userState.mCurrentAttentionCheck.mIAttentionCallback);
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Unable to cancel attention check");
+ userState.mCurrentAttentionCheck.cancelInternal();
}
}
@@ -626,7 +629,12 @@ public class AttentionManagerService extends SystemService {
if (userState == null) {
return;
}
- cancel(userState, ATTENTION_FAILURE_UNKNOWN);
+
+ cancel(userState);
+
+ if (userState.mService == null) {
+ return;
+ }
mContext.unbindService(userState.mConnection);
userState.mConnection.cleanupService();
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 32781a90348b..3fc2d3712fed 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -855,8 +855,7 @@ public class AudioService extends IAudioService.Stub
public void onSystemReady() {
mSystemReady = true;
- sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
- 0, 0, null, 0);
+ scheduleLoadSoundEffects();
mDeviceBroker.onSystemReady();
@@ -3225,6 +3224,14 @@ public class AudioService extends IAudioService.Stub
}
/**
+ * Schedule loading samples into the soundpool.
+ * This method can be overridden to schedule loading at a later time.
+ */
+ protected void scheduleLoadSoundEffects() {
+ sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
+ }
+
+ /**
* Unloads samples from the sound pool.
* This method can be called to free some memory when
* sound effects are disabled.
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index da1360d59539..b6946023e870 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -469,7 +469,10 @@ public class PermissionMonitor {
*/
@VisibleForTesting
void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) {
-
+ if (mNetd == null) {
+ Log.e(TAG, "Failed to get the netd service");
+ return;
+ }
ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3010324488b8..3abd0ba29871 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1269,21 +1269,14 @@ public final class DisplayManagerService extends SystemService {
return null;
}
- private boolean screenshotInternal(int displayId, Surface outSurface) {
+ private SurfaceControl.ScreenshotGraphicBuffer screenshotInternal(int displayId) {
final IBinder token = getDisplayToken(displayId);
if (token == null) {
- return false;
+ return null;
}
- final SurfaceControl.ScreenshotGraphicBuffer gb =
- SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
+ return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
token, new Rect(), 0 /* width */, 0 /* height */,
false /* useIdentityTransform */, 0 /* rotation */);
- try {
- outSurface.attachAndQueueBuffer(gb.getGraphicBuffer());
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failed to take screenshot - " + e.getMessage());
- }
- return true;
}
@VisibleForTesting
@@ -2354,8 +2347,8 @@ public final class DisplayManagerService extends SystemService {
}
@Override
- public boolean screenshot(int displayId, Surface outSurface) {
- return screenshotInternal(displayId, outSurface);
+ public SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId) {
+ return screenshotInternal(displayId);
}
@Override
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index e7181e23f15d..c32ae97da14f 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -271,7 +271,7 @@ public class DisplayWhiteBalanceController implements
final long time = System.currentTimeMillis();
float ambientColorTemperature = mColorTemperatureFilter.getEstimate(time);
- if (mAmbientToDisplayColorTemperatureSpline != null) {
+ if (mAmbientToDisplayColorTemperatureSpline != null && ambientColorTemperature != -1.0f) {
ambientColorTemperature =
mAmbientToDisplayColorTemperatureSpline.interpolate(ambientColorTemperature);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 647e95284534..6f1929fd464a 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -231,6 +231,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Context.BIND_AUTO_CREATE
| Context.BIND_TREAT_LIKE_ACTIVITY
| Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_INCLUDE_CAPABILITIES
| Context.BIND_SHOWING_UI
| Context.BIND_SCHEDULE_LIKE_TOP_APP;
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index ab75b21e41ca..2948aafbb931 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -199,29 +199,27 @@ class GnssNetworkConnectivityHandler {
}
/**
- * called from native code to update AGPS status
+ * Called from native code to update AGPS connection status, or to request or release a SUPL
+ * connection.
+ *
+ * <p>Note: {@code suplIpAddr} parameter is not present from IAGnssCallback.hal@2.0 onwards
+ * and is set to {@code null}.
*/
void onReportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) {
+ if (DEBUG) Log.d(TAG, "AGPS_DATA_CONNECTION: " + agpsDataConnStatusAsString(agpsStatus));
switch (agpsStatus) {
case GPS_REQUEST_AGPS_DATA_CONN:
- if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
runOnHandler(() -> handleRequestSuplConnection(agpsType, suplIpAddr));
break;
case GPS_RELEASE_AGPS_DATA_CONN:
- if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
runOnHandler(() -> handleReleaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN));
break;
case GPS_AGPS_DATA_CONNECTED:
- if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
- break;
case GPS_AGPS_DATA_CONN_DONE:
- if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
- break;
case GPS_AGPS_DATA_CONN_FAILED:
- if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
default:
- if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + agpsStatus);
+ Log.w(TAG, "Received unknown AGPS status: " + agpsStatus);
}
}
@@ -459,11 +457,17 @@ class GnssNetworkConnectivityHandler {
}
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
- NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
- requestBuilder.addCapability(getNetworkCapability(mAGpsType));
- NetworkRequest request = requestBuilder.build();
+ // The NetworkRequest.Builder class is not used to construct the network request because
+ // the ConnectivityService requires the network request to be constructed in this way
+ // to extend support for requestRouteToHostAddress() method for pre-gnss@2.0 devices.
+ NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+ networkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ networkCapabilities.addCapability(getNetworkCapability(mAGpsType));
+ NetworkRequest networkRequest = new NetworkRequest(networkCapabilities,
+ getLegacyDataConnectionType(agpsType), ConnectivityManager.REQUEST_ID_UNSET,
+ NetworkRequest.Type.REQUEST);
mConnMgr.requestNetwork(
- request,
+ networkRequest,
mSuplConnectivityCallback,
mHandler,
SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
@@ -483,6 +487,19 @@ class GnssNetworkConnectivityHandler {
}
}
+ private int getLegacyDataConnectionType(int agpsType) {
+ switch (agpsType) {
+ case AGPS_TYPE_C2K:
+ case AGPS_TYPE_SUPL:
+ return ConnectivityManager.TYPE_MOBILE_SUPL;
+ case AGPS_TYPE_EIMS:
+ return ConnectivityManager.TYPE_MOBILE_EMERGENCY;
+ case AGPS_TYPE_IMS:
+ return ConnectivityManager.TYPE_MOBILE_IMS;
+ default:
+ throw new IllegalArgumentException("agpsType: " + agpsType);
+ }
+ }
private void handleReleaseSuplConnection(int agpsDataConnStatus) {
if (DEBUG) {
String message = String.format(
@@ -546,7 +563,7 @@ class GnssNetworkConnectivityHandler {
case AGPS_DATA_CONNECTION_OPENING:
return "OPENING";
default:
- return "<Unknown>";
+ return "<Unknown>(" + mAGpsDataConnectionState + ")";
}
}
@@ -566,7 +583,7 @@ class GnssNetworkConnectivityHandler {
case GPS_REQUEST_AGPS_DATA_CONN:
return "REQUEST";
default:
- return "<Unknown>";
+ return "<Unknown>(" + agpsDataConnStatus + ")";
}
}
@@ -581,7 +598,7 @@ class GnssNetworkConnectivityHandler {
case AGPS_TYPE_IMS:
return "IMS";
default:
- return "<Unknown>";
+ return "<Unknown>(" + agpsType + ")";
}
}
@@ -658,4 +675,4 @@ class GnssNetworkConnectivityHandler {
private native void native_update_network_state(boolean connected, int type, boolean roaming,
boolean available, String apn, long networkHandle, short capabilities);
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index f34b2cb5cf29..642fa7fc3ba6 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -38,7 +38,6 @@ import android.service.notification.RankingHelperProto;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
@@ -180,7 +179,7 @@ public class PreferencesHelper implements RankingConfig {
}
}
- PackagePreferences r = getOrCreatePackagePreferences(name, uid,
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(name, uid,
XmlUtils.readIntAttribute(
parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
XmlUtils.readIntAttribute(parser, ATT_PRIORITY,
@@ -264,9 +263,9 @@ public class PreferencesHelper implements RankingConfig {
}
try {
- deleteDefaultChannelIfNeeded(r);
+ deleteDefaultChannelIfNeededLocked(r);
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "deleteDefaultChannelIfNeeded - Exception: " + e);
+ Slog.e(TAG, "deleteDefaultChannelIfNeededLocked - Exception: " + e);
}
}
}
@@ -276,50 +275,46 @@ public class PreferencesHelper implements RankingConfig {
throw new IllegalStateException("Failed to reach END_DOCUMENT");
}
- private PackagePreferences getPackagePreferences(String pkg, int uid) {
+ private PackagePreferences getPackagePreferencesLocked(String pkg, int uid) {
final String key = packagePreferencesKey(pkg, uid);
- synchronized (mPackagePreferences) {
- return mPackagePreferences.get(key);
- }
+ return mPackagePreferences.get(key);
}
- private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid) {
- return getOrCreatePackagePreferences(pkg, uid,
+ private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg, int uid) {
+ return getOrCreatePackagePreferencesLocked(pkg, uid,
DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE,
DEFAULT_ALLOW_BUBBLE);
}
- private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid, int importance,
- int priority, int visibility, boolean showBadge, boolean allowBubble) {
+ private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg, int uid,
+ int importance, int priority, int visibility, boolean showBadge, boolean allowBubble) {
final String key = packagePreferencesKey(pkg, uid);
- synchronized (mPackagePreferences) {
- PackagePreferences
- r = (uid == UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg)
- : mPackagePreferences.get(key);
- if (r == null) {
- r = new PackagePreferences();
- r.pkg = pkg;
- r.uid = uid;
- r.importance = importance;
- r.priority = priority;
- r.visibility = visibility;
- r.showBadge = showBadge;
- r.allowBubble = allowBubble;
-
- try {
- createDefaultChannelIfNeeded(r);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
- }
+ PackagePreferences
+ r = (uid == UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg)
+ : mPackagePreferences.get(key);
+ if (r == null) {
+ r = new PackagePreferences();
+ r.pkg = pkg;
+ r.uid = uid;
+ r.importance = importance;
+ r.priority = priority;
+ r.visibility = visibility;
+ r.showBadge = showBadge;
+ r.allowBubble = allowBubble;
+
+ try {
+ createDefaultChannelIfNeededLocked(r);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "createDefaultChannelIfNeededLocked - Exception: " + e);
+ }
- if (r.uid == UNKNOWN_UID) {
- mRestoredWithoutUids.put(pkg, r);
- } else {
- mPackagePreferences.put(key, r);
- }
+ if (r.uid == UNKNOWN_UID) {
+ mRestoredWithoutUids.put(pkg, r);
+ } else {
+ mPackagePreferences.put(key, r);
}
- return r;
}
+ return r;
}
private boolean shouldHaveDefaultChannel(PackagePreferences r) throws
@@ -336,7 +331,7 @@ public class PreferencesHelper implements RankingConfig {
return true;
}
- private void deleteDefaultChannelIfNeeded(PackagePreferences r) throws
+ private void deleteDefaultChannelIfNeededLocked(PackagePreferences r) throws
PackageManager.NameNotFoundException {
if (!r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Not present
@@ -352,7 +347,7 @@ public class PreferencesHelper implements RankingConfig {
r.channels.remove(NotificationChannel.DEFAULT_CHANNEL_ID);
}
- private void createDefaultChannelIfNeeded(PackagePreferences r) throws
+ private void createDefaultChannelIfNeededLocked(PackagePreferences r) throws
PackageManager.NameNotFoundException {
if (r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(mContext.getString(
@@ -479,9 +474,11 @@ public class PreferencesHelper implements RankingConfig {
* @param allowed whether bubbles are allowed.
*/
public void setBubblesAllowed(String pkg, int uid, boolean allowed) {
- PackagePreferences p = getOrCreatePackagePreferences(pkg, uid);
- p.allowBubble = allowed;
- p.lockedAppFields = p.lockedAppFields | LockableAppFields.USER_LOCKED_BUBBLE;
+ synchronized (mPackagePreferences) {
+ PackagePreferences p = getOrCreatePackagePreferencesLocked(pkg, uid);
+ p.allowBubble = allowed;
+ p.lockedAppFields = p.lockedAppFields | LockableAppFields.USER_LOCKED_BUBBLE;
+ }
}
/**
@@ -493,11 +490,15 @@ public class PreferencesHelper implements RankingConfig {
*/
@Override
public boolean areBubblesAllowed(String pkg, int uid) {
- return getOrCreatePackagePreferences(pkg, uid).allowBubble;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(pkg, uid).allowBubble;
+ }
}
public int getAppLockedFields(String pkg, int uid) {
- return getOrCreatePackagePreferences(pkg, uid).lockedAppFields;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(pkg, uid).lockedAppFields;
+ }
}
/**
@@ -505,7 +506,9 @@ public class PreferencesHelper implements RankingConfig {
*/
@Override
public int getImportance(String packageName, int uid) {
- return getOrCreatePackagePreferences(packageName, uid).importance;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(packageName, uid).importance;
+ }
}
/**
@@ -514,18 +517,24 @@ public class PreferencesHelper implements RankingConfig {
* locking field, see {@link NotificationChannel#USER_LOCKED_IMPORTANCE}.
*/
public boolean getIsAppImportanceLocked(String packageName, int uid) {
- int userLockedFields = getOrCreatePackagePreferences(packageName, uid).lockedAppFields;
- return (userLockedFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0;
+ synchronized (mPackagePreferences) {
+ int userLockedFields = getOrCreatePackagePreferencesLocked(packageName, uid).lockedAppFields;
+ return (userLockedFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0;
+ }
}
@Override
public boolean canShowBadge(String packageName, int uid) {
- return getOrCreatePackagePreferences(packageName, uid).showBadge;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(packageName, uid).showBadge;
+ }
}
@Override
public void setShowBadge(String packageName, int uid, boolean showBadge) {
- getOrCreatePackagePreferences(packageName, uid).showBadge = showBadge;
+ synchronized (mPackagePreferences) {
+ getOrCreatePackagePreferencesLocked(packageName, uid).showBadge = showBadge;
+ }
updateConfig();
}
@@ -534,20 +543,26 @@ public class PreferencesHelper implements RankingConfig {
if (groupId == null) {
return false;
}
- PackagePreferences r = getOrCreatePackagePreferences(packageName, uid);
- NotificationChannelGroup group = r.groups.get(groupId);
- if (group == null) {
- return false;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+ NotificationChannelGroup group = r.groups.get(groupId);
+ if (group == null) {
+ return false;
+ }
+ return group.isBlocked();
}
- return group.isBlocked();
}
int getPackagePriority(String pkg, int uid) {
- return getOrCreatePackagePreferences(pkg, uid).priority;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(pkg, uid).priority;
+ }
}
int getPackageVisibility(String pkg, int uid) {
- return getOrCreatePackagePreferences(pkg, uid).visibility;
+ synchronized (mPackagePreferences) {
+ return getOrCreatePackagePreferencesLocked(pkg, uid).visibility;
+ }
}
@Override
@@ -557,32 +572,34 @@ public class PreferencesHelper implements RankingConfig {
Preconditions.checkNotNull(group);
Preconditions.checkNotNull(group.getId());
Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
- PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
- if (r == null) {
- throw new IllegalArgumentException("Invalid package");
- }
- final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
- if (!group.equals(oldGroup)) {
- // will log for new entries as well as name/description changes
- MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
- }
- if (oldGroup != null) {
- group.setChannels(oldGroup.getChannels());
-
- // apps can't update the blocked status or app overlay permission
- if (fromTargetApp) {
- group.setBlocked(oldGroup.isBlocked());
- group.unlockFields(group.getUserLockedFields());
- group.lockFields(oldGroup.getUserLockedFields());
- } else {
- // but the system can
- if (group.isBlocked() != oldGroup.isBlocked()) {
- group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
- updateChannelsBypassingDnd(mContext.getUserId());
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
+ final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
+ if (!group.equals(oldGroup)) {
+ // will log for new entries as well as name/description changes
+ MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
+ }
+ if (oldGroup != null) {
+ group.setChannels(oldGroup.getChannels());
+
+ // apps can't update the blocked status or app overlay permission
+ if (fromTargetApp) {
+ group.setBlocked(oldGroup.isBlocked());
+ group.unlockFields(group.getUserLockedFields());
+ group.lockFields(oldGroup.getUserLockedFields());
+ } else {
+ // but the system can
+ if (group.isBlocked() != oldGroup.isBlocked()) {
+ group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
}
}
+ r.groups.put(group.getId(), group);
}
- r.groups.put(group.getId(), group);
}
@Override
@@ -592,94 +609,96 @@ public class PreferencesHelper implements RankingConfig {
Preconditions.checkNotNull(channel);
Preconditions.checkNotNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
- PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
- if (r == null) {
- throw new IllegalArgumentException("Invalid package");
- }
- if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
- throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
- }
- if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
- throw new IllegalArgumentException("Reserved id");
- }
- NotificationChannel existing = r.channels.get(channel.getId());
- // Keep most of the existing settings
- if (existing != null && fromTargetApp) {
- if (existing.isDeleted()) {
- existing.setDeleted(false);
-
- // log a resurrected channel as if it's new again
- MetricsLogger.action(getChannelLog(channel, pkg).setType(
- com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
}
-
- existing.setName(channel.getName().toString());
- existing.setDescription(channel.getDescription());
- existing.setBlockableSystem(channel.isBlockableSystem());
- if (existing.getGroup() == null) {
- existing.setGroup(channel.getGroup());
+ if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
+ throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
}
-
- // Apps are allowed to downgrade channel importance if the user has not changed any
- // fields on this channel yet.
- final int previousExistingImportance = existing.getImportance();
- if (existing.getUserLockedFields() == 0 &&
- channel.getImportance() < existing.getImportance()) {
- existing.setImportance(channel.getImportance());
+ if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
+ throw new IllegalArgumentException("Reserved id");
}
+ NotificationChannel existing = r.channels.get(channel.getId());
+ // Keep most of the existing settings
+ if (existing != null && fromTargetApp) {
+ if (existing.isDeleted()) {
+ existing.setDeleted(false);
+
+ // log a resurrected channel as if it's new again
+ MetricsLogger.action(getChannelLog(channel, pkg).setType(
+ com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
+ }
+
+ existing.setName(channel.getName().toString());
+ existing.setDescription(channel.getDescription());
+ existing.setBlockableSystem(channel.isBlockableSystem());
+ if (existing.getGroup() == null) {
+ existing.setGroup(channel.getGroup());
+ }
+
+ // Apps are allowed to downgrade channel importance if the user has not changed any
+ // fields on this channel yet.
+ final int previousExistingImportance = existing.getImportance();
+ if (existing.getUserLockedFields() == 0 &&
+ channel.getImportance() < existing.getImportance()) {
+ existing.setImportance(channel.getImportance());
+ }
- // system apps and dnd access apps can bypass dnd if the user hasn't changed any
- // fields on the channel yet
- if (existing.getUserLockedFields() == 0 && hasDndAccess) {
- boolean bypassDnd = channel.canBypassDnd();
- existing.setBypassDnd(bypassDnd);
+ // system apps and dnd access apps can bypass dnd if the user hasn't changed any
+ // fields on the channel yet
+ if (existing.getUserLockedFields() == 0 && hasDndAccess) {
+ boolean bypassDnd = channel.canBypassDnd();
+ existing.setBypassDnd(bypassDnd);
- if (bypassDnd != mAreChannelsBypassingDnd
- || previousExistingImportance != existing.getImportance()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ if (bypassDnd != mAreChannelsBypassingDnd
+ || previousExistingImportance != existing.getImportance()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
}
- }
- updateConfig();
- return;
- }
- if (channel.getImportance() < IMPORTANCE_NONE
- || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
- throw new IllegalArgumentException("Invalid importance level");
- }
+ updateConfig();
+ return;
+ }
+ if (channel.getImportance() < IMPORTANCE_NONE
+ || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
+ throw new IllegalArgumentException("Invalid importance level");
+ }
- // Reset fields that apps aren't allowed to set.
- if (fromTargetApp && !hasDndAccess) {
- channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
- }
- if (fromTargetApp) {
- channel.setLockscreenVisibility(r.visibility);
- }
- clearLockedFields(channel);
- channel.setImportanceLockedByOEM(r.oemLockedImportance);
- if (!channel.isImportanceLockedByOEM()) {
- if (r.futureOemLockedChannels.remove(channel.getId())) {
- channel.setImportanceLockedByOEM(true);
+ // Reset fields that apps aren't allowed to set.
+ if (fromTargetApp && !hasDndAccess) {
+ channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
+ }
+ if (fromTargetApp) {
+ channel.setLockscreenVisibility(r.visibility);
+ }
+ clearLockedFieldsLocked(channel);
+ channel.setImportanceLockedByOEM(r.oemLockedImportance);
+ if (!channel.isImportanceLockedByOEM()) {
+ if (r.futureOemLockedChannels.remove(channel.getId())) {
+ channel.setImportanceLockedByOEM(true);
+ }
+ }
+ channel.setImportanceLockedByCriticalDeviceFunction(r.defaultAppLockedImportance);
+ if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+ channel.setLockscreenVisibility(
+ NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+ }
+ if (!r.showBadge) {
+ channel.setShowBadge(false);
}
- }
- channel.setImportanceLockedByCriticalDeviceFunction(r.defaultAppLockedImportance);
- if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
- channel.setLockscreenVisibility(
- NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
- }
- if (!r.showBadge) {
- channel.setShowBadge(false);
- }
- r.channels.put(channel.getId(), channel);
- if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ r.channels.put(channel.getId(), channel);
+ if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
+ MetricsLogger.action(getChannelLog(channel, pkg).setType(
+ com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
}
- MetricsLogger.action(getChannelLog(channel, pkg).setType(
- com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
}
- void clearLockedFields(NotificationChannel channel) {
+ void clearLockedFieldsLocked(NotificationChannel channel) {
channel.unlockFields(channel.getUserLockedFields());
}
@@ -688,55 +707,58 @@ public class PreferencesHelper implements RankingConfig {
boolean fromUser) {
Preconditions.checkNotNull(updatedChannel);
Preconditions.checkNotNull(updatedChannel.getId());
- PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
- if (r == null) {
- throw new IllegalArgumentException("Invalid package");
- }
- NotificationChannel channel = r.channels.get(updatedChannel.getId());
- if (channel == null || channel.isDeleted()) {
- throw new IllegalArgumentException("Channel does not exist");
- }
- if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
- updatedChannel.setLockscreenVisibility(
- NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
- }
- if (fromUser) {
- updatedChannel.lockFields(channel.getUserLockedFields());
- lockFieldsForUpdate(channel, updatedChannel);
- } else {
- updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
- }
- // no importance updates are allowed if OEM blocked it
- updatedChannel.setImportanceLockedByOEM(channel.isImportanceLockedByOEM());
- if (updatedChannel.isImportanceLockedByOEM()) {
- updatedChannel.setImportance(channel.getImportance());
- }
- updatedChannel.setImportanceLockedByCriticalDeviceFunction(r.defaultAppLockedImportance);
- if (updatedChannel.isImportanceLockedByCriticalDeviceFunction()) {
- updatedChannel.setImportance(channel.getImportance());
- }
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
+ NotificationChannel channel = r.channels.get(updatedChannel.getId());
+ if (channel == null || channel.isDeleted()) {
+ throw new IllegalArgumentException("Channel does not exist");
+ }
+ if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+ updatedChannel.setLockscreenVisibility(
+ NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+ }
+ if (fromUser) {
+ updatedChannel.lockFields(channel.getUserLockedFields());
+ lockFieldsForUpdateLocked(channel, updatedChannel);
+ } else {
+ updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
+ }
+ // no importance updates are allowed if OEM blocked it
+ updatedChannel.setImportanceLockedByOEM(channel.isImportanceLockedByOEM());
+ if (updatedChannel.isImportanceLockedByOEM()) {
+ updatedChannel.setImportance(channel.getImportance());
+ }
+ updatedChannel.setImportanceLockedByCriticalDeviceFunction(
+ r.defaultAppLockedImportance);
+ if (updatedChannel.isImportanceLockedByCriticalDeviceFunction()) {
+ updatedChannel.setImportance(channel.getImportance());
+ }
- r.channels.put(updatedChannel.getId(), updatedChannel);
+ r.channels.put(updatedChannel.getId(), updatedChannel);
- if (onlyHasDefaultChannel(pkg, uid)) {
- // copy settings to app level so they are inherited by new channels
- // when the app migrates
- r.importance = updatedChannel.getImportance();
- r.priority = updatedChannel.canBypassDnd()
- ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
- r.visibility = updatedChannel.getLockscreenVisibility();
- r.showBadge = updatedChannel.canShowBadge();
- }
+ if (onlyHasDefaultChannel(pkg, uid)) {
+ // copy settings to app level so they are inherited by new channels
+ // when the app migrates
+ r.importance = updatedChannel.getImportance();
+ r.priority = updatedChannel.canBypassDnd()
+ ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
+ r.visibility = updatedChannel.getLockscreenVisibility();
+ r.showBadge = updatedChannel.canShowBadge();
+ }
- if (!channel.equals(updatedChannel)) {
- // only log if there are real changes
- MetricsLogger.action(getChannelLog(updatedChannel, pkg)
- .setSubtype(fromUser ? 1 : 0));
- }
+ if (!channel.equals(updatedChannel)) {
+ // only log if there are real changes
+ MetricsLogger.action(getChannelLog(updatedChannel, pkg)
+ .setSubtype(fromUser ? 1 : 0));
+ }
- if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
- || channel.getImportance() != updatedChannel.getImportance()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
+ || channel.getImportance() != updatedChannel.getImportance()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
}
updateConfig();
}
@@ -745,35 +767,39 @@ public class PreferencesHelper implements RankingConfig {
public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
- PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
- if (r == null) {
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return null;
+ }
+ if (channelId == null) {
+ channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
+ }
+ final NotificationChannel nc = r.channels.get(channelId);
+ if (nc != null && (includeDeleted || !nc.isDeleted())) {
+ return nc;
+ }
return null;
}
- if (channelId == null) {
- channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
- }
- final NotificationChannel nc = r.channels.get(channelId);
- if (nc != null && (includeDeleted || !nc.isDeleted())) {
- return nc;
- }
- return null;
}
@Override
public void deleteNotificationChannel(String pkg, int uid, String channelId) {
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return;
- }
- NotificationChannel channel = r.channels.get(channelId);
- if (channel != null) {
- channel.setDeleted(true);
- LogMaker lm = getChannelLog(channel, pkg);
- lm.setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
- MetricsLogger.action(lm);
-
- if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return;
+ }
+ NotificationChannel channel = r.channels.get(channelId);
+ if (channel != null) {
+ channel.setDeleted(true);
+ LogMaker lm = getChannelLog(channel, pkg);
+ lm.setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
+ MetricsLogger.action(lm);
+
+ if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
}
}
}
@@ -783,25 +809,29 @@ public class PreferencesHelper implements RankingConfig {
public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(channelId);
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return;
+ }
+ r.channels.remove(channelId);
}
- r.channels.remove(channelId);
}
@Override
public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
Preconditions.checkNotNull(pkg);
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return;
- }
- int N = r.channels.size() - 1;
- for (int i = N; i >= 0; i--) {
- String key = r.channels.keyAt(i);
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
- r.channels.remove(key);
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return;
+ }
+ int N = r.channels.size() - 1;
+ for (int i = N; i >= 0; i--) {
+ String key = r.channels.keyAt(i);
+ if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
+ r.channels.remove(key);
+ }
}
}
}
@@ -875,32 +905,36 @@ public class PreferencesHelper implements RankingConfig {
public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
int uid, String groupId, boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
- return null;
- }
- NotificationChannelGroup group = r.groups.get(groupId).clone();
- group.setChannels(new ArrayList<>());
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (includeDeleted || !nc.isDeleted()) {
- if (groupId.equals(nc.getGroup())) {
- group.addChannel(nc);
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
+ return null;
+ }
+ NotificationChannelGroup group = r.groups.get(groupId).clone();
+ group.setChannels(new ArrayList<>());
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (includeDeleted || !nc.isDeleted()) {
+ if (groupId.equals(nc.getGroup())) {
+ group.addChannel(nc);
+ }
}
}
+ return group;
}
- return group;
}
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
int uid) {
Preconditions.checkNotNull(pkg);
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return null;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return null;
+ }
+ return r.groups.get(groupId);
}
- return r.groups.get(groupId);
}
@Override
@@ -908,60 +942,64 @@ public class PreferencesHelper implements RankingConfig {
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
Preconditions.checkNotNull(pkg);
Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return ParceledListSlice.emptyList();
- }
- NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (includeDeleted || !nc.isDeleted()) {
- if (nc.getGroup() != null) {
- if (r.groups.get(nc.getGroup()) != null) {
- NotificationChannelGroup ncg = groups.get(nc.getGroup());
- if (ncg == null) {
- ncg = r.groups.get(nc.getGroup()).clone();
- ncg.setChannels(new ArrayList<>());
- groups.put(nc.getGroup(), ncg);
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return ParceledListSlice.emptyList();
+ }
+ NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (includeDeleted || !nc.isDeleted()) {
+ if (nc.getGroup() != null) {
+ if (r.groups.get(nc.getGroup()) != null) {
+ NotificationChannelGroup ncg = groups.get(nc.getGroup());
+ if (ncg == null) {
+ ncg = r.groups.get(nc.getGroup()).clone();
+ ncg.setChannels(new ArrayList<>());
+ groups.put(nc.getGroup(), ncg);
+ }
+ ncg.addChannel(nc);
}
- ncg.addChannel(nc);
+ } else {
+ nonGrouped.addChannel(nc);
}
- } else {
- nonGrouped.addChannel(nc);
}
}
- }
- if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
- groups.put(null, nonGrouped);
- }
- if (includeEmpty) {
- for (NotificationChannelGroup group : r.groups.values()) {
- if (!groups.containsKey(group.getId())) {
- groups.put(group.getId(), group);
+ if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
+ groups.put(null, nonGrouped);
+ }
+ if (includeEmpty) {
+ for (NotificationChannelGroup group : r.groups.values()) {
+ if (!groups.containsKey(group.getId())) {
+ groups.put(group.getId(), group);
+ }
}
}
+ return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
- return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
public List<NotificationChannel> deleteNotificationChannelGroup(String pkg, int uid,
String groupId) {
List<NotificationChannel> deletedChannels = new ArrayList<>();
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null || TextUtils.isEmpty(groupId)) {
- return deletedChannels;
- }
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null || TextUtils.isEmpty(groupId)) {
+ return deletedChannels;
+ }
- r.groups.remove(groupId);
+ r.groups.remove(groupId);
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (groupId.equals(nc.getGroup())) {
- nc.setDeleted(true);
- deletedChannels.add(nc);
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (groupId.equals(nc.getGroup())) {
+ nc.setDeleted(true);
+ deletedChannels.add(nc);
+ }
}
}
return deletedChannels;
@@ -970,11 +1008,15 @@ public class PreferencesHelper implements RankingConfig {
@Override
public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid) {
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return new ArrayList<>();
+ List<NotificationChannelGroup> groups = new ArrayList<>();
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return groups;
+ }
+ groups.addAll(r.groups.values());
}
- return r.groups.values();
+ return groups;
}
@Override
@@ -982,18 +1024,20 @@ public class PreferencesHelper implements RankingConfig {
boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return ParceledListSlice.emptyList();
- }
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (includeDeleted || !nc.isDeleted()) {
- channels.add(nc);
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return ParceledListSlice.emptyList();
}
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (includeDeleted || !nc.isDeleted()) {
+ channels.add(nc);
+ }
+ }
+ return new ParceledListSlice<>(channels);
}
- return new ParceledListSlice<>(channels);
}
/**
@@ -1008,7 +1052,7 @@ public class PreferencesHelper implements RankingConfig {
// notifications from this package aren't blocked
if (r != null && r.importance != IMPORTANCE_NONE) {
for (NotificationChannel channel : r.channels.values()) {
- if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+ if (channelIsLiveLocked(r, channel) && channel.canBypassDnd()) {
channels.add(channel);
}
}
@@ -1024,46 +1068,52 @@ public class PreferencesHelper implements RankingConfig {
* upgrades.
*/
public boolean onlyHasDefaultChannel(String pkg, int uid) {
- PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
- if (r.channels.size() == 1
- && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- return true;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r.channels.size() == 1
+ && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return true;
+ }
+ return false;
}
- return false;
}
public int getDeletedChannelCount(String pkg, int uid) {
Preconditions.checkNotNull(pkg);
int deletedCount = 0;
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return deletedCount;
- }
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (nc.isDeleted()) {
- deletedCount++;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return deletedCount;
}
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (nc.isDeleted()) {
+ deletedCount++;
+ }
+ }
+ return deletedCount;
}
- return deletedCount;
}
public int getBlockedChannelCount(String pkg, int uid) {
Preconditions.checkNotNull(pkg);
int blockedCount = 0;
- PackagePreferences r = getPackagePreferences(pkg, uid);
- if (r == null) {
- return blockedCount;
- }
- int N = r.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = r.channels.valueAt(i);
- if (!nc.isDeleted() && IMPORTANCE_NONE == nc.getImportance()) {
- blockedCount++;
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ return blockedCount;
+ }
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (!nc.isDeleted() && IMPORTANCE_NONE == nc.getImportance()) {
+ blockedCount++;
+ }
}
+ return blockedCount;
}
- return blockedCount;
}
public int getBlockedAppCount(int userId) {
@@ -1098,7 +1148,7 @@ public class PreferencesHelper implements RankingConfig {
}
for (NotificationChannel channel : r.channels.values()) {
- if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+ if (channelIsLiveLocked(r, channel) && channel.canBypassDnd()) {
count++;
break;
}
@@ -1136,7 +1186,7 @@ public class PreferencesHelper implements RankingConfig {
}
for (NotificationChannel channel : r.channels.values()) {
- if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+ if (channelIsLiveLocked(r, channel) && channel.canBypassDnd()) {
if (!mAreChannelsBypassingDnd) {
mAreChannelsBypassingDnd = true;
updateZenPolicy(true);
@@ -1153,7 +1203,7 @@ public class PreferencesHelper implements RankingConfig {
}
}
- private boolean channelIsLive(PackagePreferences pkgPref, NotificationChannel channel) {
+ private boolean channelIsLiveLocked(PackagePreferences pkgPref, NotificationChannel channel) {
// Channel is in a group that's blocked
if (isGroupBlocked(pkgPref.pkg, pkgPref.uid, channel.getGroup())) {
return false;
@@ -1185,7 +1235,9 @@ public class PreferencesHelper implements RankingConfig {
*/
@Override
public void setImportance(String pkgName, int uid, int importance) {
- getOrCreatePackagePreferences(pkgName, uid).importance = importance;
+ synchronized (mPackagePreferences) {
+ getOrCreatePackagePreferencesLocked(pkgName, uid).importance = importance;
+ }
updateConfig();
}
@@ -1204,12 +1256,15 @@ public class PreferencesHelper implements RankingConfig {
* considered for sentiment adjustments (and thus never show a blocking helper).
*/
public void setAppImportanceLocked(String packageName, int uid) {
- PackagePreferences prefs = getOrCreatePackagePreferences(packageName, uid);
- if ((prefs.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
- return;
- }
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getOrCreatePackagePreferencesLocked(packageName, uid);
+ if ((prefs.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
+ return;
+ }
- prefs.lockedAppFields = prefs.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
+ prefs.lockedAppFields =
+ prefs.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
+ }
updateConfig();
}
@@ -1217,15 +1272,17 @@ public class PreferencesHelper implements RankingConfig {
* Returns the delegate for a given package, if it's allowed by the package and the user.
*/
public @Nullable String getNotificationDelegate(String sourcePkg, int sourceUid) {
- PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
- if (prefs == null || prefs.delegate == null) {
- return null;
- }
- if (!prefs.delegate.mUserAllowed || !prefs.delegate.mEnabled) {
- return null;
+ if (prefs == null || prefs.delegate == null) {
+ return null;
+ }
+ if (!prefs.delegate.mUserAllowed || !prefs.delegate.mEnabled) {
+ return null;
+ }
+ return prefs.delegate.mPkg;
}
- return prefs.delegate.mPkg;
}
/**
@@ -1233,11 +1290,13 @@ public class PreferencesHelper implements RankingConfig {
*/
public void setNotificationDelegate(String sourcePkg, int sourceUid,
String delegatePkg, int delegateUid) {
- PackagePreferences prefs = getOrCreatePackagePreferences(sourcePkg, sourceUid);
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getOrCreatePackagePreferencesLocked(sourcePkg, sourceUid);
- boolean userAllowed = prefs.delegate == null || prefs.delegate.mUserAllowed;
- Delegate delegate = new Delegate(delegatePkg, delegateUid, true, userAllowed);
- prefs.delegate = delegate;
+ boolean userAllowed = prefs.delegate == null || prefs.delegate.mUserAllowed;
+ Delegate delegate = new Delegate(delegatePkg, delegateUid, true, userAllowed);
+ prefs.delegate = delegate;
+ }
updateConfig();
}
@@ -1245,9 +1304,15 @@ public class PreferencesHelper implements RankingConfig {
* Used by an app to turn off its notification delegate.
*/
public void revokeNotificationDelegate(String sourcePkg, int sourceUid) {
- PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
- if (prefs != null && prefs.delegate != null) {
- prefs.delegate.mEnabled = false;
+ boolean changed = false;
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
+ if (prefs != null && prefs.delegate != null) {
+ prefs.delegate.mEnabled = false;
+ changed = true;
+ }
+ }
+ if (changed) {
updateConfig();
}
}
@@ -1256,9 +1321,15 @@ public class PreferencesHelper implements RankingConfig {
* Toggles whether an app can have a notification delegate on behalf of a user.
*/
public void toggleNotificationDelegate(String sourcePkg, int sourceUid, boolean userAllowed) {
- PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
- if (prefs != null && prefs.delegate != null) {
- prefs.delegate.mUserAllowed = userAllowed;
+ boolean changed = false;
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
+ if (prefs != null && prefs.delegate != null) {
+ prefs.delegate.mUserAllowed = userAllowed;
+ changed = true;
+ }
+ }
+ if (changed) {
updateConfig();
}
}
@@ -1269,13 +1340,16 @@ public class PreferencesHelper implements RankingConfig {
*/
public boolean isDelegateAllowed(String sourcePkg, int sourceUid,
String potentialDelegatePkg, int potentialDelegateUid) {
- PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+ synchronized (mPackagePreferences) {
+ PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
- return prefs != null && prefs.isValidDelegate(potentialDelegatePkg, potentialDelegateUid);
+ return prefs != null && prefs.isValidDelegate(potentialDelegatePkg,
+ potentialDelegateUid);
+ }
}
@VisibleForTesting
- void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) {
+ void lockFieldsForUpdateLocked(NotificationChannel original, NotificationChannel update) {
if (original.canBypassDnd() != update.canBypassDnd()) {
update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
}
@@ -1309,30 +1383,30 @@ public class PreferencesHelper implements RankingConfig {
pw.print(prefix);
pw.println("per-package config:");
- pw.println("PackagePreferencess:");
+ pw.println("PackagePreferences:");
synchronized (mPackagePreferences) {
- dumpPackagePreferencess(pw, prefix, filter, mPackagePreferences);
+ dumpPackagePreferencesLocked(pw, prefix, filter, mPackagePreferences);
}
pw.println("Restored without uid:");
- dumpPackagePreferencess(pw, prefix, filter, mRestoredWithoutUids);
+ dumpPackagePreferencesLocked(pw, prefix, filter, mRestoredWithoutUids);
}
public void dump(ProtoOutputStream proto,
@NonNull NotificationManagerService.DumpFilter filter) {
synchronized (mPackagePreferences) {
- dumpPackagePreferencess(proto, RankingHelperProto.RECORDS, filter,
+ dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS, filter,
mPackagePreferences);
}
- dumpPackagePreferencess(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
+ dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
mRestoredWithoutUids);
}
- private static void dumpPackagePreferencess(PrintWriter pw, String prefix,
+ private static void dumpPackagePreferencesLocked(PrintWriter pw, String prefix,
@NonNull NotificationManagerService.DumpFilter filter,
- ArrayMap<String, PackagePreferences> PackagePreferencess) {
- final int N = PackagePreferencess.size();
+ ArrayMap<String, PackagePreferences> packagePreferences) {
+ final int N = packagePreferences.size();
for (int i = 0; i < N; i++) {
- final PackagePreferences r = PackagePreferencess.valueAt(i);
+ final PackagePreferences r = packagePreferences.valueAt(i);
if (filter.matches(r.pkg)) {
pw.print(prefix);
pw.print(" AppSettings: ");
@@ -1369,13 +1443,13 @@ public class PreferencesHelper implements RankingConfig {
}
}
- private static void dumpPackagePreferencess(ProtoOutputStream proto, long fieldId,
+ private static void dumpPackagePreferencesLocked(ProtoOutputStream proto, long fieldId,
@NonNull NotificationManagerService.DumpFilter filter,
- ArrayMap<String, PackagePreferences> PackagePreferencess) {
- final int N = PackagePreferencess.size();
+ ArrayMap<String, PackagePreferences> packagePreferences) {
+ final int N = packagePreferences.size();
long fToken;
for (int i = 0; i < N; i++) {
- final PackagePreferences r = PackagePreferencess.valueAt(i);
+ final PackagePreferences r = packagePreferences.valueAt(i);
if (filter.matches(r.pkg)) {
fToken = proto.start(fieldId);
@@ -1626,11 +1700,11 @@ public class PreferencesHelper implements RankingConfig {
// Package upgrade
try {
synchronized (mPackagePreferences) {
- PackagePreferences fullPackagePreferences = getPackagePreferences(pkg,
+ PackagePreferences fullPackagePreferences = getPackagePreferencesLocked(pkg,
mPm.getPackageUidAsUser(pkg, changeUserId));
if (fullPackagePreferences != null) {
- createDefaultChannelIfNeeded(fullPackagePreferences);
- deleteDefaultChannelIfNeeded(fullPackagePreferences);
+ createDefaultChannelIfNeededLocked(fullPackagePreferences);
+ deleteDefaultChannelIfNeededLocked(fullPackagePreferences);
}
}
} catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 51d5acc9b555..ee07c7de9dbc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -166,6 +166,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
* . . . . . . . . . . . . . . . . . . . . . .
* </pre>
*
+ * <p>To test the OMS, execute:
+ * <code>
+ * atest FrameworksServicesTests:com.android.server.om # internal tests
+ * atest OverlayDeviceTests OverlayHostTests # public API tests
+ * </code>
+ * </p>
+ *
* <p>Finally, here is a list of keywords used in the OMS context.</p>
*
* <ul>
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 36b5beb7bbb2..f35c70780db9 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -26,6 +26,7 @@ import android.util.ArrayMap;
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
@@ -327,7 +328,8 @@ final class OverlayManagerSettings {
Serializer.persist(mItems, os);
}
- private static final class Serializer {
+ @VisibleForTesting
+ static final class Serializer {
private static final String TAG_OVERLAYS = "overlays";
private static final String TAG_ITEM = "item";
@@ -343,7 +345,8 @@ final class OverlayManagerSettings {
private static final String ATTR_USER_ID = "userId";
private static final String ATTR_VERSION = "version";
- private static final int CURRENT_VERSION = 3;
+ @VisibleForTesting
+ static final int CURRENT_VERSION = 3;
public static void restore(@NonNull final ArrayList<SettingsItem> table,
@NonNull final InputStream is) throws IOException, XmlPullParserException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 51bf5191247f..898437ddae41 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3051,7 +3051,7 @@ public class PackageManagerService extends IPackageManager.Stub
+ mSdkVersion + "; regranting permissions for internal storage");
}
mPermissionManager.updateAllPermissions(
- StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, false, mPackages.values(),
+ StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
mPermissionCallback);
ver.sdkVersion = mSdkVersion;
@@ -5569,7 +5569,7 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mPackages) {
mPermissionManager.updateAllPermissions(
- StorageManager.UUID_PRIVATE_INTERNAL, false, false, mPackages.values(),
+ StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
mPermissionCallback);
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int packageCount = mPackages.size();
@@ -21222,8 +21222,8 @@ public class PackageManagerService extends IPackageManager.Stub
// try optimizing this.
synchronized (mPackages) {
mPermissionManager.updateAllPermissions(
- StorageManager.UUID_PRIVATE_INTERNAL, false, mIsPreQUpgrade,
- mPackages.values(), mPermissionCallback);
+ StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
+ mPermissionCallback);
}
// Watch for external volumes that come and go over time
@@ -22213,8 +22213,8 @@ public class PackageManagerService extends IPackageManager.Stub
logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for " + volumeUuid);
}
- mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated, false,
- mPackages.values(), mPermissionCallback);
+ mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated, mPackages.values(),
+ mPermissionCallback);
// Yay, everything is now upgraded
ver.forceCurrent();
@@ -23247,7 +23247,7 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized(mPackages) {
// NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
mPermissionManager.updateAllPermissions(
- StorageManager.UUID_PRIVATE_INTERNAL, true, false, mPackages.values(),
+ StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(),
mPermissionCallback);
}
}
@@ -24816,11 +24816,9 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (mExternalSourcesPolicy != null) {
int isTrusted = mExternalSourcesPolicy.getPackageTrustedToInstallApps(packageName, uid);
- if (isTrusted != PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT) {
- return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
- }
+ return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
}
- return checkUidPermission(appOpPermission, uid) == PERMISSION_GRANTED;
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 9336c55d4a79..c75a462d5bc1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -34,10 +34,10 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQU
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
-import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
+import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
import static android.content.pm.PackageManager.RESTRICTED_PERMISSIONS_ENABLED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.UserHandle.getAppId;
@@ -69,7 +69,6 @@ import android.content.pm.PermissionInfo;
import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Build;
-import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -82,7 +81,6 @@ import android.os.storage.StorageManagerInternal;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.permission.PermissionManagerInternal;
-import android.provider.Settings;
import android.permission.PermissionManagerInternal.OnRuntimePermissionStateChangedListener;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -2458,9 +2456,8 @@ public class PermissionManagerService {
}
if (updatePermissions) {
- // Update app permissions to take into account the new whitelist state.
- updatePermissions(pkg.packageName, pkg, getVolumeUuidForPackage(pkg),
- 0 /*flags*/, null /*allPackages*/, callback);
+ // Update permission of this app to take into account the new whitelist state.
+ restorePermissionState(pkg, false, pkg.packageName, callback);
// If this resulted in losing a permission we need to kill the app.
if (oldGrantedRestrictedPermissions != null) {
@@ -2605,62 +2602,12 @@ public class PermissionManagerService {
}
private void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
- boolean updatePermissionsOnPreQUpdate, Collection<PackageParser.Package> allPackages,
- PermissionCallback callback) {
+ Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
final int flags = UPDATE_PERMISSIONS_ALL |
(sdkUpdated
? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
: 0);
updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
-
- if (updatePermissionsOnPreQUpdate) {
- final int[] userIds = UserManagerService.getInstance().getUserIds();
-
- for (PackageParser.Package pkg : allPackages) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
- if (ps == null) {
- return;
- }
-
- final boolean appSupportsRuntimePermissions =
- pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;
- final PermissionsState permsState = ps.getPermissionsState();
-
- for (String permName : new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_BACKGROUND_LOCATION}) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
-
- for (int userId : userIds) {
- if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE, 0, userId)
- != 0) {
- continue;
- }
-
- final PermissionState permState = permsState.getRuntimePermissionState(
- permName, userId);
-
- if (permState != null
- && (permState.getFlags() & BLOCKING_PERMISSION_FLAGS) == 0) {
- if (permState.isGranted()) {
- permsState.updatePermissionFlags(bp, userId,
- USER_PERMISSION_FLAGS, 0);
- }
-
- if (appSupportsRuntimePermissions) {
- permsState.revokeRuntimePermission(bp, userId);
- } else {
- // Force a review even for apps that were already installed
- permsState.updatePermissionFlags(bp, userId,
- FLAG_PERMISSION_REVIEW_REQUIRED,
- FLAG_PERMISSION_REVIEW_REQUIRED);
- }
- }
- }
- }
- }
- }
}
private void updatePermissions(String changingPkgName, PackageParser.Package changingPkg,
@@ -3150,10 +3097,9 @@ public class PermissionManagerService {
}
@Override
public void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
- boolean updatePermissionsOnPreQUpdate, Collection<PackageParser.Package> allPackages,
- PermissionCallback callback) {
+ Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
PermissionManagerService.this.updateAllPermissions(
- volumeUuid, sdkUpdated, updatePermissionsOnPreQUpdate, allPackages, callback);
+ volumeUuid, sdkUpdated, allPackages, callback);
}
@Override
public String[] getAppOpPermissionPackages(String permName) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 34f922e11d08..9fb71f44716b 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -93,7 +93,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@Nullable PackageParser.Package pkg, boolean replaceGrant,
@NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate,
- boolean updatePermissionsOnPreQUpdate,
@NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
/**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index d52ba169768f..9908b3657121 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2629,7 +2629,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
0, null, new UserHandle(serviceUserId)));
if (!mContext.bindServiceAsUser(intent, newConn,
Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
- | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+ | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+ | Context.BIND_INCLUDE_CAPABILITIES,
new UserHandle(serviceUserId))) {
String msg = "Unable to bind service: "
+ componentName;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 91ec4a083ed9..e08e1ff01348 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -863,7 +863,7 @@ final class ActivityRecord extends ConfigurationContainer {
name = intent.getComponent().flattenToShortString();
}
- private static ActivityRecord tokenToActivityRecordLocked(Token token) {
+ private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
if (token == null) {
return null;
}
@@ -891,7 +891,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
}
- static ActivityRecord forTokenLocked(IBinder token) {
+ static @Nullable ActivityRecord forTokenLocked(IBinder token) {
try {
return Token.tokenToActivityRecordLocked((Token)token);
} catch (ClassCastException e) {
@@ -1595,8 +1595,8 @@ final class ActivityRecord extends ConfigurationContainer {
try {
ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
ar.add(rintent);
- mAtmService.getLifecycleManager().scheduleTransaction(
- app.getThread(), appToken, NewIntentItem.obtain(ar, mState == PAUSED));
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ NewIntentItem.obtain(ar));
unsent = false;
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
@@ -2127,10 +2127,13 @@ final class ActivityRecord extends ConfigurationContainer {
static void activityResumedLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
- if (r != null) {
- r.icicle = null;
- r.haveState = false;
+ if (r == null) {
+ // If an app reports resumed after a long delay, the record on server side might have
+ // been removed (e.g. destroy timeout), so the token could be null.
+ return;
}
+ r.icicle = null;
+ r.haveState = false;
final ActivityDisplay display = r.getDisplay();
if (display != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6bc9fc8a9f7c..fad4dbd5613b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1804,7 +1804,7 @@ class ActivityStack extends ConfigurationContainer {
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
- "completedPausedLocked");
+ "completePausedLocked");
} else if (prev.hasProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
+ " wasStopping=" + wasStopping + " visible=" + prev.visible);
@@ -2962,8 +2962,7 @@ class ActivityStack extends ConfigurationContainer {
}
if (next.newIntents != null) {
- transaction.addCallback(NewIntentItem.obtain(next.newIntents,
- false /* andPause */));
+ transaction.addCallback(NewIntentItem.obtain(next.newIntents));
}
// Well the app will no longer be stopped.
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index f9980bebca9e..c1d872f23f0f 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -73,6 +73,13 @@ public class BoundsAnimationController {
/** Schedule a PiP mode changed callback when this animation ends. */
public static final int SCHEDULE_PIP_MODE_CHANGED_ON_END = 2;
+ public static final int BOUNDS = 0;
+ public static final int FADE_IN = 1;
+
+ @IntDef({BOUNDS, FADE_IN}) public @interface AnimationType {}
+
+ private static final int FADE_IN_DURATION = 500;
+
// Only accessed on UI thread.
private ArrayMap<BoundsAnimationTarget, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
@@ -115,6 +122,7 @@ public class BoundsAnimationController {
private boolean mFinishAnimationAfterTransition = false;
private final AnimationHandler mAnimationHandler;
private Choreographer mChoreographer;
+ private @AnimationType int mAnimationType;
private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
@@ -140,6 +148,7 @@ public class BoundsAnimationController {
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
private final BoundsAnimationTarget mTarget;
+ private final @AnimationType int mAnimationType;
private final Rect mFrom = new Rect();
private final Rect mTo = new Rect();
private final Rect mTmpRect = new Rect();
@@ -166,8 +175,8 @@ public class BoundsAnimationController {
// Depending on whether we are animating from
// a smaller to a larger size
- private final int mFrozenTaskWidth;
- private final int mFrozenTaskHeight;
+ private int mFrozenTaskWidth;
+ private int mFrozenTaskHeight;
// Timeout callback to ensure we continue the animation if waiting for resuming or app
// windows drawn fails
@@ -176,12 +185,13 @@ public class BoundsAnimationController {
resume();
};
- BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
- @SchedulePipModeChangedState int schedulePipModeChangedState,
+ BoundsAnimator(BoundsAnimationTarget target, @AnimationType int animationType, Rect from,
+ Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState,
@SchedulePipModeChangedState int prevShedulePipModeChangedState,
boolean moveFromFullscreen, boolean moveToFullscreen, Rect frozenTask) {
super();
mTarget = target;
+ mAnimationType = animationType;
mFrom.set(from);
mTo.set(to);
mSchedulePipModeChangedState = schedulePipModeChangedState;
@@ -195,12 +205,14 @@ public class BoundsAnimationController {
// to their final size immediately so we can use scaling to make the window
// larger. Likewise if we are going from bigger to smaller, we want to wait until
// the end so we don't have to upscale from the smaller finished size.
- if (animatingToLargerSize()) {
- mFrozenTaskWidth = mTo.width();
- mFrozenTaskHeight = mTo.height();
- } else {
- mFrozenTaskWidth = frozenTask.isEmpty() ? mFrom.width() : frozenTask.width();
- mFrozenTaskHeight = frozenTask.isEmpty() ? mFrom.height() : frozenTask.height();
+ if (mAnimationType == BOUNDS) {
+ if (animatingToLargerSize()) {
+ mFrozenTaskWidth = mTo.width();
+ mFrozenTaskHeight = mTo.height();
+ } else {
+ mFrozenTaskWidth = frozenTask.isEmpty() ? mFrom.width() : frozenTask.width();
+ mFrozenTaskHeight = frozenTask.isEmpty() ? mFrom.height() : frozenTask.height();
+ }
}
}
@@ -222,8 +234,9 @@ public class BoundsAnimationController {
// otherwise.
boolean continueAnimation;
if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) {
- continueAnimation = mTarget.onAnimationStart(mSchedulePipModeChangedState ==
- SCHEDULE_PIP_MODE_CHANGED_ON_START, false /* forceUpdate */);
+ continueAnimation = mTarget.onAnimationStart(
+ mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START,
+ false /* forceUpdate */, mAnimationType);
// When starting an animation from fullscreen, pause here and wait for the
// windows-drawn signal before we start the rest of the transition down into PiP.
@@ -238,7 +251,8 @@ public class BoundsAnimationController {
// However, we still need to report to them that they are leaving PiP, so this will
// force an update via a mode changed callback.
continueAnimation = mTarget.onAnimationStart(
- true /* schedulePipModeChangedCallback */, true /* forceUpdate */);
+ true /* schedulePipModeChangedCallback */, true /* forceUpdate */,
+ mAnimationType);
} else {
// The animation is already running, but we should check that the TaskStack is still
// valid before continuing with the animation
@@ -285,6 +299,13 @@ public class BoundsAnimationController {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (Float) animation.getAnimatedValue();
+ if (mAnimationType == FADE_IN) {
+ if (!mTarget.setPinnedStackAlpha(value)) {
+ cancelAndCallAnimationEnd();
+ }
+ return;
+ }
+
final float remains = 1 - value;
mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value + 0.5f);
mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
@@ -408,16 +429,29 @@ public class BoundsAnimationController {
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveFromFullscreen, boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen,
+ @AnimationType int animationType) {
animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
- moveFromFullscreen, moveToFullscreen);
+ moveFromFullscreen, moveToFullscreen, animationType);
}
@VisibleForTesting
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveFromFullscreen, boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen,
+ @AnimationType int animationType) {
final BoundsAnimator existing = mRunningAnimations.get(target);
+ // animateBoundsImpl gets called twice for each animation. The second time we get the final
+ // to rect that respects the shelf, which is when we want to resize. Our signal for fade in
+ // comes in from how to enter into pip, but we also need to use the to and from rect to
+ // decide which animation we want to run finally.
+ boolean shouldResize = false;
+ if (isRunningFadeInAnimation(target)) {
+ shouldResize = true;
+ if (from.contains(to)) {
+ animationType = FADE_IN;
+ }
+ }
final boolean replacing = existing != null;
@SchedulePipModeChangedState int prevSchedulePipModeChangedState =
NO_PIP_MODE_CHANGED_CALLBACKS;
@@ -477,18 +511,34 @@ public class BoundsAnimationController {
// Since we are replacing, we skip both animation start and end callbacks
existing.cancel();
}
- final BoundsAnimator animator = new BoundsAnimator(target, from, to,
+ if (shouldResize) {
+ target.setPinnedStackSize(to, null);
+ }
+ final BoundsAnimator animator = new BoundsAnimator(target, animationType, from, to,
schedulePipModeChangedState, prevSchedulePipModeChangedState,
moveFromFullscreen, moveToFullscreen, frozenTask);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
- animator.setDuration((animationDuration != -1 ? animationDuration
- : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
+ animator.setDuration(animationType == FADE_IN ? FADE_IN_DURATION
+ : (animationDuration != -1 ? animationDuration : DEFAULT_TRANSITION_DURATION)
+ * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.start();
return animator;
}
+ public void setAnimationType(@AnimationType int animationType) {
+ mAnimationType = animationType;
+ }
+
+ /** return the current animation type. */
+ public @AnimationType int getAnimationType() {
+ @AnimationType int animationType = mAnimationType;
+ // Default to BOUNDS.
+ mAnimationType = BOUNDS;
+ return animationType;
+ }
+
public Handler getHandler() {
return mHandler;
}
@@ -498,6 +548,11 @@ public class BoundsAnimationController {
mHandler.post(this::resume);
}
+ private boolean isRunningFadeInAnimation(final BoundsAnimationTarget target) {
+ final BoundsAnimator existing = mRunningAnimations.get(target);
+ return existing != null && existing.mAnimationType == FADE_IN && existing.isStarted();
+ }
+
private void resume() {
for (int i = 0; i < mRunningAnimations.size(); i++) {
final BoundsAnimator b = mRunningAnimations.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index 5cb80de1a36d..9f54e49e0022 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -32,7 +32,8 @@ interface BoundsAnimationTarget {
* callbacks
* @return whether to continue the animation
*/
- boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
+ boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
+ @BoundsAnimationController.AnimationType int animationType);
/**
* @return Whether the animation should be paused waiting for the windows to draw before
@@ -53,6 +54,9 @@ interface BoundsAnimationTarget {
*/
boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds);
+ /** Sets the alpha of the animation target */
+ boolean setPinnedStackAlpha(float alpha);
+
/**
* Callback for the target to inform it that the animation has ended, so it can do some
* necessary cleanup.
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 144efb49e84a..07d3fb990470 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -26,6 +26,8 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.WindowManager.TRANSIT_NONE;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.BoundsAnimationController.BOUNDS;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
@@ -201,7 +203,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
}
- private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
+ private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
+ boolean sendUserLeaveHint) {
synchronized (mService.mGlobalLock) {
if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
+ mWindowManager.getRecentsAnimationController()
@@ -246,7 +249,18 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
if (reorderMode == REORDER_MOVE_TO_TOP) {
// Bring the target stack to the front
mStackSupervisor.mNoAnimActivities.add(targetActivity);
- targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+
+ if (sendUserLeaveHint) {
+ // Setting this allows the previous app to PiP.
+ mStackSupervisor.mUserLeaving = true;
+ targetStack.moveTaskToFrontLocked(targetActivity.getTaskRecord(),
+ true /* noAnimation */, null /* activityOptions */,
+ targetActivity.appTimeTracker,
+ "RecentsAnimation.onAnimationFinished()");
+ } else {
+ targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+ }
+
if (DEBUG) {
final ActivityStack topStack = getTopNonAlwaysOnTopStack();
if (topStack != targetStack) {
@@ -300,11 +314,11 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
@Override
public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
- boolean runSychronously) {
+ boolean runSychronously, boolean sendUserLeaveHint) {
if (runSychronously) {
- finishAnimation(reorderMode);
+ finishAnimation(reorderMode, sendUserLeaveHint);
} else {
- mService.mH.post(() -> finishAnimation(reorderMode));
+ mService.mH.post(() -> finishAnimation(reorderMode, sendUserLeaveHint));
}
}
@@ -317,6 +331,10 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
final RecentsAnimationController controller =
mWindowManager.getRecentsAnimationController();
+ final DisplayContent dc =
+ mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ dc.mBoundsAnimationController.setAnimationType(
+ controller.shouldCancelWithDeferredScreenshot() ? FADE_IN : BOUNDS);
// Cancel running recents animation and screenshot previous task when the next
// transition starts in below cases:
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 381366995dd5..d2c510fa8902 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -27,6 +27,7 @@ import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -142,7 +143,9 @@ public class RecentsAnimationController implements DeathRecipient {
};
public interface RecentsAnimationCallbacks {
- void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously);
+ /** Callback when recents animation is finished. */
+ void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously,
+ boolean sendUserLeaveHint);
}
private final IRecentsAnimationController mController =
@@ -179,7 +182,7 @@ public class RecentsAnimationController implements DeathRecipient {
}
@Override
- public void finish(boolean moveHomeToTop) {
+ public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint) {
if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "finish(" + moveHomeToTop + "):"
+ " mCanceled=" + mCanceled);
final long token = Binder.clearCallingIdentity();
@@ -195,7 +198,9 @@ public class RecentsAnimationController implements DeathRecipient {
mCallbacks.onAnimationFinished(moveHomeToTop
? REORDER_MOVE_TO_TOP
: REORDER_MOVE_TO_ORIGINAL_POSITION,
- true /* runSynchronously */);
+ true /* runSynchronously */, sendUserLeaveHint);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
+ dc.mBoundsAnimationController.setAnimationType(FADE_IN);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -497,7 +502,8 @@ public class RecentsAnimationController implements DeathRecipient {
Slog.e(TAG, "Failed to cancel recents animation", e);
}
// Clean up and return to the previous app
- mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
}
}
@@ -542,7 +548,8 @@ public class RecentsAnimationController implements DeathRecipient {
if (DEBUG_RECENTS_ANIMATIONS) {
Slog.d(TAG, "mRecentScreenshotAnimator finish");
}
- mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
}, mService);
mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 2d5c97f9a3a5..b90d60227be4 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -275,7 +275,20 @@ class ScreenRotationAnimation {
final int displayId = display.getDisplayId();
final Surface surface = mService.mSurfaceFactory.make();
surface.copyFrom(mSurfaceControl);
- if (mService.mDisplayManagerInternal.screenshot(displayId, surface)) {
+ SurfaceControl.ScreenshotGraphicBuffer gb =
+ mService.mDisplayManagerInternal.screenshot(displayId);
+ if (gb != null) {
+ try {
+ surface.attachAndQueueBuffer(gb.getGraphicBuffer());
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage());
+ }
+ // If the screenshot contains secure layers, we have to make sure the
+ // screenshot surface we display it in also has FLAG_SECURE so that
+ // the user can not screenshot secure layers via the screenshot surface.
+ if (gb.containsSecureLayers()) {
+ t.setSecure(mSurfaceControl, true);
+ }
t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
t.setAlpha(mSurfaceControl, 0);
t.show(mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 4a0831e39100..7714458bb167 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -104,7 +104,8 @@ class TaskPositioner {
private int mMinVisibleWidth;
private int mMinVisibleHeight;
- private Task mTask;
+ @VisibleForTesting
+ Task mTask;
private boolean mResizing;
private boolean mPreserveOrientation;
private boolean mStartOrientationWasLandscape;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 09baf8cf1111..bdb4d0474865 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -34,6 +34,7 @@ import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
@@ -148,6 +149,7 @@ public class TaskStack extends WindowContainer<Task> implements
private boolean mCancelCurrentBoundsAnimation = false;
private Rect mBoundsAnimationTarget = new Rect();
private Rect mBoundsAnimationSourceHintBounds = new Rect();
+ private @BoundsAnimationController.AnimationType int mAnimationType;
Rect mPreAnimationBounds = new Rect();
@@ -1572,7 +1574,8 @@ public class TaskStack extends WindowContainer<Task> implements
}
@Override // AnimatesBounds
- public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+ public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
+ @BoundsAnimationController.AnimationType int animationType) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mWmService.mGlobalLock) {
if (!isAttached()) {
@@ -1583,6 +1586,7 @@ public class TaskStack extends WindowContainer<Task> implements
mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
mCancelCurrentBoundsAnimation = false;
+ mAnimationType = animationType;
// If we are changing UI mode, as in the PiP to fullscreen
// transition, then we need to wait for the window to draw.
@@ -1599,7 +1603,8 @@ public class TaskStack extends WindowContainer<Task> implements
// I don't believe you...
}
- if (schedulePipModeChangedCallback && mActivityStack != null) {
+ if ((schedulePipModeChangedCallback || animationType == FADE_IN)
+ && mActivityStack != null) {
// We need to schedule the PiP mode change before the animation up. It is possible
// in this case for the animation down to not have been completed, so always
// force-schedule and update to the client to ensure that it is notified that it
@@ -1614,6 +1619,21 @@ public class TaskStack extends WindowContainer<Task> implements
@Override // AnimatesBounds
public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
boolean moveToFullscreen) {
+ if (mAnimationType == BoundsAnimationController.FADE_IN) {
+ setPinnedStackAlpha(1f);
+ try {
+ mWmService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
+ } catch (RemoteException e) {
+ // I don't believe you...
+ }
+ return;
+ }
+
+ onBoundAnimationEnd(schedulePipModeChangedCallback, finalStackSize, moveToFullscreen);
+ }
+
+ private void onBoundAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
+ boolean moveToFullscreen) {
if (inPinnedWindowingMode()) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1725,10 +1745,23 @@ public class TaskStack extends WindowContainer<Task> implements
final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
schedulePipModeChangedState;
final DisplayContent displayContent = getDisplayContent();
+ @BoundsAnimationController.AnimationType int intendedAnimationType =
+ displayContent.mBoundsAnimationController.getAnimationType();
+ if (intendedAnimationType == FADE_IN) {
+ if (fromFullscreen) {
+ setPinnedStackAlpha(0f);
+ }
+ if (toBounds.width() == fromBounds.width()
+ && toBounds.height() == fromBounds.height()) {
+ intendedAnimationType = BoundsAnimationController.BOUNDS;
+ }
+ }
+
+ final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
displayContent.mBoundsAnimationController.getHandler().post(() -> {
displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
finalToBounds, animationDuration, finalSchedulePipModeChangedState,
- fromFullscreen, toFullscreen);
+ fromFullscreen, toFullscreen, animationType);
});
}
@@ -1905,6 +1938,20 @@ public class TaskStack extends WindowContainer<Task> implements
}
}
+ @Override
+ public boolean setPinnedStackAlpha(float alpha) {
+ // Hold the lock since this is called from the BoundsAnimator running on the UiThread
+ synchronized (mWmService.mGlobalLock) {
+ if (mCancelCurrentBoundsAnimation) {
+ return false;
+ }
+ getPendingTransaction().setAlpha(getSurfaceControl(), alpha);
+ scheduleAnimation();
+ }
+
+ return true;
+ }
+
public DisplayInfo getDisplayInfo() {
return mDisplayContent.getDisplayInfo();
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 57311e19bc76..d8ebd84b3e73 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -98,14 +98,25 @@ public class WindowAnimationSpec implements AnimationSpec {
tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
t.setAlpha(leash, tmp.transformation.getAlpha());
- if (mStackClipMode == STACK_CLIP_NONE || mStackClipMode == STACK_CLIP_AFTER_ANIM) {
- t.setWindowCrop(leash, tmp.transformation.getClipRect());
+
+ boolean cropSet = false;
+ if (mStackClipMode == STACK_CLIP_NONE) {
+ if (tmp.transformation.hasClipRect()) {
+ t.setWindowCrop(leash, tmp.transformation.getClipRect());
+ cropSet = true;
+ }
} else {
mTmpRect.set(mStackBounds);
- mTmpRect.intersect(tmp.transformation.getClipRect());
+ if (tmp.transformation.hasClipRect()) {
+ mTmpRect.intersect(tmp.transformation.getClipRect());
+ }
t.setWindowCrop(leash, mTmpRect);
+ cropSet = true;
}
- if (mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {
+
+ // We can only apply rounded corner if a crop is set, as otherwise the value is meaningless,
+ // since it doesn't have anything it's relative to.
+ if (cropSet && mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {
t.setCornerRadius(leash, mWindowCornerRadius);
}
}
diff --git a/services/net/java/android/net/ip/IIpClient.aidl b/services/net/java/android/net/ip/IIpClient.aidl
index b834e45c6852..1e7726472ff6 100644
--- a/services/net/java/android/net/ip/IIpClient.aidl
+++ b/services/net/java/android/net/ip/IIpClient.aidl
@@ -32,4 +32,5 @@ oneway interface IIpClient {
void setMulticastFilter(boolean enabled);
void addKeepalivePacketFilter(int slot, in TcpKeepalivePacketDataParcelable pkt);
void removeKeepalivePacketFilter(int slot);
+ void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
new file mode 100644
index 000000000000..3f9a57e07876
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -0,0 +1,504 @@
+/*
+ * 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.om;
+
+import static android.content.om.OverlayInfo.STATE_DISABLED;
+import static android.content.om.OverlayInfo.STATE_ENABLED;
+import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
+import static android.content.om.OverlayInfo.STATE_TARGET_IS_BEING_REPLACED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.annotation.NonNull;
+import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.util.ArraySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayManagerServiceImplTests {
+ private OverlayManagerServiceImpl mImpl;
+ private DummyDeviceState mState;
+ private DummyListener mListener;
+
+ private static final String OVERLAY = "com.dummy.overlay";
+ private static final String TARGET = "com.dummy.target";
+ private static final int USER = 0;
+
+ private static final String OVERLAY2 = OVERLAY + "2";
+ private static final String TARGET2 = TARGET + "2";
+ private static final int USER2 = USER + 1;
+
+ private static final String OVERLAY3 = OVERLAY + "3";
+ private static final int USER3 = USER2 + 1;
+
+
+ @Before
+ public void setUp() throws Exception {
+ mState = new DummyDeviceState();
+ mListener = new DummyListener();
+ DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
+ mImpl = new OverlayManagerServiceImpl(pmh,
+ new DummyIdmapManager(mState, pmh),
+ new OverlayManagerSettings(),
+ new String[0],
+ mListener);
+ }
+
+ // tests: basics
+
+ @Test
+ public void testGetOverlayInfo() throws Exception {
+ installOverlayPackage(OVERLAY, TARGET, USER, false);
+ final OverlayInfo oi = mImpl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(oi);
+ assertEquals(oi.packageName, OVERLAY);
+ assertEquals(oi.targetPackageName, TARGET);
+ assertEquals(oi.userId, USER);
+ }
+
+ @Test
+ public void testGetOverlayInfosForTarget() throws Exception {
+ installOverlayPackage(OVERLAY, TARGET, USER, false);
+ installOverlayPackage(OVERLAY2, TARGET, USER, false);
+
+ installOverlayPackage(OVERLAY3, TARGET, USER2, false);
+
+ final List<OverlayInfo> ois = mImpl.getOverlayInfosForTarget(TARGET, USER);
+ assertEquals(ois.size(), 2);
+ assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
+ assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+
+ final List<OverlayInfo> ois2 = mImpl.getOverlayInfosForTarget(TARGET, USER2);
+ assertEquals(ois2.size(), 1);
+ assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER2)));
+
+ final List<OverlayInfo> ois3 = mImpl.getOverlayInfosForTarget(TARGET, USER3);
+ assertNotNull(ois3);
+ assertEquals(ois3.size(), 0);
+
+ final List<OverlayInfo> ois4 = mImpl.getOverlayInfosForTarget("no.such.overlay", USER);
+ assertNotNull(ois4);
+ assertEquals(ois4.size(), 0);
+ }
+
+ @Test
+ public void testGetOverlayInfosForUser() throws Exception {
+ installOverlayPackage(OVERLAY, TARGET, USER, false);
+ installOverlayPackage(OVERLAY2, TARGET, USER, false);
+ installOverlayPackage(OVERLAY3, TARGET2, USER, false);
+
+ final Map<String, List<OverlayInfo>> everything = mImpl.getOverlaysForUser(USER);
+ assertEquals(everything.size(), 2);
+
+ final List<OverlayInfo> ois = everything.get(TARGET);
+ assertNotNull(ois);
+ assertEquals(ois.size(), 2);
+ assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
+ assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+
+ final List<OverlayInfo> ois2 = everything.get(TARGET2);
+ assertNotNull(ois2);
+ assertEquals(ois2.size(), 1);
+ assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER)));
+
+ final Map<String, List<OverlayInfo>> everything2 = mImpl.getOverlaysForUser(USER2);
+ assertNotNull(everything2);
+ assertEquals(everything2.size(), 0);
+ }
+
+ @Test
+ public void testPriority() throws Exception {
+ installOverlayPackage(OVERLAY, TARGET, USER, false);
+ installOverlayPackage(OVERLAY2, TARGET, USER, false);
+ installOverlayPackage(OVERLAY3, TARGET, USER, false);
+
+ final OverlayInfo o1 = mImpl.getOverlayInfo(OVERLAY, USER);
+ final OverlayInfo o2 = mImpl.getOverlayInfo(OVERLAY2, USER);
+ final OverlayInfo o3 = mImpl.getOverlayInfo(OVERLAY3, USER);
+
+ assertOverlayInfoList(TARGET, USER, o1, o2, o3);
+
+ assertTrue(mImpl.setLowestPriority(OVERLAY3, USER));
+ assertOverlayInfoList(TARGET, USER, o3, o1, o2);
+
+ assertTrue(mImpl.setHighestPriority(OVERLAY3, USER));
+ assertOverlayInfoList(TARGET, USER, o1, o2, o3);
+
+ assertTrue(mImpl.setPriority(OVERLAY, OVERLAY2, USER));
+ assertOverlayInfoList(TARGET, USER, o2, o1, o3);
+ }
+
+ @Test
+ public void testOverlayInfoStateTransitions() throws Exception {
+ assertNull(mImpl.getOverlayInfo(OVERLAY, USER));
+
+ installOverlayPackage(OVERLAY, TARGET, USER, true);
+ assertState(STATE_MISSING_TARGET, OVERLAY, USER);
+
+ installTargetPackage(TARGET, USER);
+ assertState(STATE_DISABLED, OVERLAY, USER);
+
+ mImpl.setEnabled(OVERLAY, true, USER);
+ assertState(STATE_ENABLED, OVERLAY, USER);
+
+ beginUpgradeTargetPackage(TARGET, USER);
+ assertState(STATE_TARGET_IS_BEING_REPLACED, OVERLAY, USER);
+
+ endUpgradeTargetPackage(TARGET, USER);
+ assertState(STATE_ENABLED, OVERLAY, USER);
+
+ uninstallTargetPackage(TARGET, USER);
+ assertState(STATE_MISSING_TARGET, OVERLAY, USER);
+
+ installTargetPackage(TARGET, USER);
+ assertState(STATE_ENABLED, OVERLAY, USER);
+ }
+
+ @Test
+ public void testUpdateOverlaysForUser() throws Exception {
+ installTargetPackage(TARGET, USER);
+ installTargetPackage("some.other.target", USER);
+ installOverlayPackage(OVERLAY, TARGET, USER, true);
+
+ // do nothing, expect no change
+ List<String> a = mImpl.updateOverlaysForUser(USER);
+ assertEquals(1, a.size());
+ assertTrue(a.contains(TARGET));
+
+ // upgrade overlay, keep target
+ upgradeOverlayPackage(OVERLAY, TARGET, USER, true);
+ List<String> b = mImpl.updateOverlaysForUser(USER);
+ assertEquals(1, b.size());
+ assertTrue(b.contains(TARGET));
+
+ // do nothing, expect no change
+ List<String> c = mImpl.updateOverlaysForUser(USER);
+ assertEquals(1, c.size());
+ assertTrue(c.contains(TARGET));
+
+ // upgrade overlay, switch to new target
+ upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
+ List<String> d = mImpl.updateOverlaysForUser(USER);
+ assertEquals(2, d.size());
+ assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
+
+ // do nothing, expect no change
+ List<String> e = mImpl.updateOverlaysForUser(USER);
+ assertEquals(1, e.size());
+ assertTrue(e.contains("some.other.target"));
+ }
+
+ @Test
+ public void testOnOverlayPackageUpgraded() throws Exception {
+ installTargetPackage(TARGET, USER);
+ installOverlayPackage(OVERLAY, TARGET, USER, true);
+ mImpl.onOverlayPackageReplacing(OVERLAY, USER);
+ mListener.count = 0;
+ mImpl.onOverlayPackageReplaced(OVERLAY, USER);
+ assertEquals(1, mListener.count);
+
+ // upgrade to a version where the overlay has changed its target
+ upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
+ mImpl.onOverlayPackageReplacing(OVERLAY, USER);
+ mListener.count = 0;
+ mImpl.onOverlayPackageReplaced(OVERLAY, USER);
+ // expect once for the old target package, once for the new target package
+ assertEquals(2, mListener.count);
+
+ upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
+ mImpl.onOverlayPackageReplacing(OVERLAY, USER);
+ mListener.count = 0;
+ mImpl.onOverlayPackageReplaced(OVERLAY, USER);
+ assertEquals(1, mListener.count);
+ }
+
+ // tests: listener interface
+
+ @Test
+ public void testListener() throws Exception {
+ installOverlayPackage(OVERLAY, TARGET, USER, true);
+ assertEquals(1, mListener.count);
+ mListener.count = 0;
+
+ installTargetPackage(TARGET, USER);
+ assertEquals(1, mListener.count);
+ mListener.count = 0;
+
+ mImpl.setEnabled(OVERLAY, true, USER);
+ assertEquals(1, mListener.count);
+ mListener.count = 0;
+
+ mImpl.setEnabled(OVERLAY, true, USER);
+ assertEquals(0, mListener.count);
+ }
+
+ // helper methods
+
+ private void assertState(int expected, final String overlayPackageName, int userId) {
+ int actual = mImpl.getOverlayInfo(OVERLAY, USER).state;
+ String msg = String.format("expected %s but was %s:",
+ OverlayInfo.stateToString(expected), OverlayInfo.stateToString(actual));
+ assertEquals(msg, expected, actual);
+ }
+
+ private void assertOverlayInfoList(final String targetPackageName, int userId,
+ OverlayInfo... overlayInfos) {
+ final List<OverlayInfo> expected =
+ mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+ final List<OverlayInfo> actual = Arrays.asList(overlayInfos);
+ assertEquals(expected, actual);
+ }
+
+ private void installTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) != null) {
+ throw new IllegalStateException("package already installed");
+ }
+ mState.add(packageName, null, userId, false);
+ mImpl.onTargetPackageAdded(packageName, userId);
+ }
+
+ private void beginUpgradeTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mState.add(packageName, null, userId, false);
+ mImpl.onTargetPackageReplacing(packageName, userId);
+ }
+
+ private void endUpgradeTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mState.add(packageName, null, userId, false);
+ mImpl.onTargetPackageReplaced(packageName, userId);
+ }
+
+ private void uninstallTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mState.remove(packageName, userId);
+ mImpl.onTargetPackageRemoved(packageName, userId);
+ }
+
+ private void installOverlayPackage(String packageName, String targetPackageName, int userId,
+ boolean canCreateIdmap) {
+ if (mState.select(packageName, userId) != null) {
+ throw new IllegalStateException("package already installed");
+ }
+ mState.add(packageName, targetPackageName, userId, canCreateIdmap);
+ mImpl.onOverlayPackageAdded(packageName, userId);
+ }
+
+ private void upgradeOverlayPackage(String packageName, String targetPackageName, int userId,
+ boolean canCreateIdmap) {
+ DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ if (pkg == null) {
+ throw new IllegalStateException("package not installed, cannot upgrade");
+ }
+ pkg.targetPackageName = targetPackageName;
+ pkg.canCreateIdmap = canCreateIdmap;
+ }
+
+ private void uninstallOverlayPackage(String packageName, int userId) {
+ // implement this when adding support for downloadable overlays
+ throw new IllegalArgumentException("not implemented");
+ }
+
+ private static final class DummyDeviceState {
+ private List<Package> mPackages = new ArrayList<>();
+
+ public void add(String packageName, String targetPackageName, int userId,
+ boolean canCreateIdmap) {
+ remove(packageName, userId);
+ Package pkg = new Package();
+ pkg.packageName = packageName;
+ pkg.targetPackageName = targetPackageName;
+ pkg.userId = userId;
+ pkg.canCreateIdmap = canCreateIdmap;
+ mPackages.add(pkg);
+ }
+
+ public void remove(String packageName, int userId) {
+ final Iterator<Package> iter = mPackages.iterator();
+ while (iter.hasNext()) {
+ final Package pkg = iter.next();
+ if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
+ iter.remove();
+ return;
+ }
+ }
+ }
+
+ public List<Package> select(int userId) {
+ List<Package> out = new ArrayList<>();
+ final int packageCount = mPackages.size();
+ for (int i = 0; i < packageCount; i++) {
+ final Package pkg = mPackages.get(i);
+ if (pkg.userId == userId) {
+ out.add(pkg);
+ }
+ }
+ return out;
+ }
+
+ public Package select(String packageName, int userId) {
+ final int packageCount = mPackages.size();
+ for (int i = 0; i < packageCount; i++) {
+ final Package pkg = mPackages.get(i);
+ if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
+ return pkg;
+ }
+ }
+ return null;
+ }
+
+ private static final class Package {
+ public String packageName;
+ public int userId;
+ public String targetPackageName;
+ public boolean canCreateIdmap;
+ }
+ }
+
+ private static final class DummyPackageManagerHelper implements
+ OverlayManagerServiceImpl.PackageManagerHelper {
+ private final DummyDeviceState mState;
+
+ DummyPackageManagerHelper(DummyDeviceState state) {
+ mState = state;
+ }
+
+ @Override
+ public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
+ final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ if (pkg == null) {
+ return null;
+ }
+ ApplicationInfo ai = new ApplicationInfo();
+ ai.sourceDir = String.format("%s/%s/base.apk",
+ pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
+ pkg.packageName);
+ PackageInfo pi = new PackageInfo();
+ pi.applicationInfo = ai;
+ pi.packageName = pkg.packageName;
+ pi.overlayTarget = pkg.targetPackageName;
+ pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
+ return pi;
+ }
+
+ @Override
+ public boolean signaturesMatching(@NonNull String packageName1,
+ @NonNull String packageName2, int userId) {
+ return false;
+ }
+
+ @Override
+ public List<PackageInfo> getOverlayPackages(int userId) {
+ List<PackageInfo> out = new ArrayList<>();
+ final List<DummyDeviceState.Package> packages = mState.select(userId);
+ final int packageCount = packages.size();
+ for (int i = 0; i < packageCount; i++) {
+ final DummyDeviceState.Package pkg = packages.get(i);
+ if (pkg.targetPackageName != null) {
+ out.add(getPackageInfo(pkg.packageName, pkg.userId));
+ }
+ }
+ return out;
+ }
+ }
+
+ private static class DummyIdmapManager extends IdmapManager {
+ private final DummyDeviceState mState;
+ private Set<String> mIdmapFiles = new ArraySet<>();
+
+ DummyIdmapManager(DummyDeviceState state, DummyPackageManagerHelper packageManagerHelper) {
+ super(null, packageManagerHelper);
+ mState = state;
+ }
+
+ @Override
+ boolean createIdmap(@NonNull final PackageInfo targetPackage,
+ @NonNull final PackageInfo overlayPackage, int userId) {
+ final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
+ if (t == null) {
+ return false;
+ }
+ final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
+ if (o == null) {
+ return false;
+ }
+ if (!o.canCreateIdmap) {
+ return false;
+ }
+ final String key = createKey(overlayPackage.packageName, userId);
+ mIdmapFiles.add(key);
+ return true;
+ }
+
+ @Override
+ boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
+ final String key = createKey(oi.packageName, oi.userId);
+ if (!mIdmapFiles.contains(key)) {
+ return false;
+ }
+ mIdmapFiles.remove(key);
+ return true;
+ }
+
+ @Override
+ boolean idmapExists(@NonNull final OverlayInfo oi) {
+ final String key = createKey(oi.packageName, oi.userId);
+ return mIdmapFiles.contains(key);
+ }
+
+ @Override
+ boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
+ final String key = createKey(overlayPackage.packageName, userId);
+ return mIdmapFiles.contains(key);
+ }
+
+ private String createKey(@NonNull final String packageName, final int userId) {
+ return String.format("%s:%d", packageName, userId);
+ }
+ }
+
+ private static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+ public int count;
+
+ public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
+ count++;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
new file mode 100644
index 000000000000..8ff8b6e4a9e0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -0,0 +1,505 @@
+/*
+ * 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.om;
+
+import static android.content.om.OverlayInfo.STATE_DISABLED;
+import static android.content.om.OverlayInfo.STATE_ENABLED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.om.OverlayInfo;
+import android.text.TextUtils;
+import android.util.Xml;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayManagerSettingsTests {
+ private OverlayManagerSettings mSettings;
+
+ private static final OverlayInfo OVERLAY_A0 = new OverlayInfo(
+ "com.dummy.overlay_a",
+ "com.dummy.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_a-1/base.apk",
+ STATE_DISABLED,
+ 0,
+ 0,
+ false);
+
+ private static final OverlayInfo OVERLAY_B0 = new OverlayInfo(
+ "com.dummy.overlay_b",
+ "com.dummy.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_b-1/base.apk",
+ STATE_DISABLED,
+ 0,
+ 0,
+ false);
+
+ private static final OverlayInfo OVERLAY_C0 = new OverlayInfo(
+ "com.dummy.overlay_c",
+ "com.dummy.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_c-1/base.apk",
+ STATE_DISABLED,
+ 0,
+ 0,
+ false);
+
+ private static final OverlayInfo OVERLAY_A1 = new OverlayInfo(
+ "com.dummy.overlay_a",
+ "com.dummy.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_a-1/base.apk",
+ STATE_DISABLED,
+ 1,
+ 0,
+ false);
+
+ private static final OverlayInfo OVERLAY_B1 = new OverlayInfo(
+ "com.dummy.overlay_b",
+ "com.dummy.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_b-1/base.apk",
+ STATE_DISABLED,
+ 1,
+ 0,
+ false);
+
+ @Before
+ public void setUp() throws Exception {
+ mSettings = new OverlayManagerSettings();
+ }
+
+ // tests: generic functionality
+
+ @Test
+ public void testSettingsInitiallyEmpty() throws Exception {
+ final int userId = 0;
+ Map<String, List<OverlayInfo>> map = mSettings.getOverlaysForUser(userId);
+ assertEquals(0, map.size());
+ }
+
+ @Test
+ public void testBasicSetAndGet() throws Exception {
+ assertDoesNotContain(mSettings, OVERLAY_A0.packageName, OVERLAY_A0.userId);
+
+ insert(OVERLAY_A0);
+ assertContains(mSettings, OVERLAY_A0);
+ OverlayInfo oi = mSettings.getOverlayInfo(OVERLAY_A0.packageName, OVERLAY_A0.userId);
+ assertEquals(OVERLAY_A0, oi);
+
+ assertTrue(mSettings.remove(OVERLAY_A0.packageName, OVERLAY_A0.userId));
+ assertDoesNotContain(mSettings, OVERLAY_A0.packageName, OVERLAY_A0.userId);
+ }
+
+ @Test
+ public void testGetUsers() throws Exception {
+ int[] users = mSettings.getUsers();
+ assertEquals(0, users.length);
+
+ insert(OVERLAY_A0);
+ users = mSettings.getUsers();
+ assertEquals(1, users.length);
+ assertContains(users, OVERLAY_A0.userId);
+
+ insert(OVERLAY_A1);
+ insert(OVERLAY_B1);
+ users = mSettings.getUsers();
+ assertEquals(2, users.length);
+ assertContains(users, OVERLAY_A0.userId);
+ assertContains(users, OVERLAY_A1.userId);
+ }
+
+ @Test
+ public void testGetOverlaysForUser() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_A1);
+ insert(OVERLAY_B1);
+
+ Map<String, List<OverlayInfo>> map = mSettings.getOverlaysForUser(OVERLAY_A0.userId);
+ assertEquals(1, map.keySet().size());
+ assertTrue(map.keySet().contains(OVERLAY_A0.targetPackageName));
+
+ List<OverlayInfo> list = map.get(OVERLAY_A0.targetPackageName);
+ assertEquals(2, list.size());
+ assertTrue(list.contains(OVERLAY_A0));
+ assertTrue(list.contains(OVERLAY_B0));
+
+ // getOverlaysForUser should never return null
+ map = mSettings.getOverlaysForUser(-1);
+ assertNotNull(map);
+ assertEquals(0, map.size());
+ }
+
+ @Test
+ public void testRemoveUser() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_A1);
+
+ assertContains(mSettings, OVERLAY_A0);
+ assertContains(mSettings, OVERLAY_B0);
+ assertContains(mSettings, OVERLAY_A1);
+
+ mSettings.removeUser(OVERLAY_A0.userId);
+
+ assertDoesNotContain(mSettings, OVERLAY_A0);
+ assertDoesNotContain(mSettings, OVERLAY_B0);
+ assertContains(mSettings, OVERLAY_A1);
+ }
+
+ @Test
+ public void testOrderOfNewlyAddedItems() throws Exception {
+ // new items are appended to the list
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_C0);
+
+ List<OverlayInfo> list =
+ mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_B0, OVERLAY_C0);
+
+ // overlays keep their positions when updated
+ mSettings.setState(OVERLAY_B0.packageName, OVERLAY_B0.userId, STATE_ENABLED);
+ OverlayInfo oi = mSettings.getOverlayInfo(OVERLAY_B0.packageName, OVERLAY_B0.userId);
+
+ list = mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, oi, OVERLAY_C0);
+ }
+
+ @Test
+ public void testSetPriority() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_C0);
+
+ List<OverlayInfo> list =
+ mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_B0, OVERLAY_C0);
+
+ boolean changed = mSettings.setPriority(OVERLAY_B0.packageName, OVERLAY_C0.packageName,
+ OVERLAY_B0.userId);
+ assertTrue(changed);
+ list = mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0);
+
+ changed =
+ mSettings.setPriority(OVERLAY_B0.packageName, "does.not.exist", OVERLAY_B0.userId);
+ assertFalse(changed);
+ list = mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0);
+
+ OverlayInfo otherTarget = new OverlayInfo(
+ "com.dummy.overlay_other",
+ "com.dummy.some.other.target",
+ null,
+ "some-category",
+ "/data/app/com.dummy.overlay_other-1/base.apk",
+ STATE_DISABLED,
+ 0,
+ 0,
+ false);
+ insert(otherTarget);
+ changed = mSettings.setPriority(OVERLAY_A0.packageName, otherTarget.packageName,
+ OVERLAY_A0.userId);
+ assertFalse(changed);
+ }
+
+ @Test
+ public void testSetLowestPriority() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_C0);
+
+ List<OverlayInfo> list =
+ mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_B0, OVERLAY_C0);
+
+ boolean changed = mSettings.setLowestPriority(OVERLAY_B0.packageName, OVERLAY_B0.userId);
+ assertTrue(changed);
+
+ list = mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_B0, OVERLAY_A0, OVERLAY_C0);
+ }
+
+ @Test
+ public void testSetHighestPriority() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+ insert(OVERLAY_C0);
+
+ List<OverlayInfo> list =
+ mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_B0, OVERLAY_C0);
+
+ boolean changed = mSettings.setHighestPriority(OVERLAY_B0.packageName, OVERLAY_B0.userId);
+ assertTrue(changed);
+
+ list = mSettings.getOverlaysForTarget(OVERLAY_A0.targetPackageName, OVERLAY_A0.userId);
+ assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0);
+ }
+
+ // tests: persist and restore
+
+ @Test
+ public void testPersistEmpty() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mSettings.persist(os);
+ String xml = new String(os.toByteArray(), "utf-8");
+
+ assertEquals(1, countXmlTags(xml, "overlays"));
+ assertEquals(0, countXmlTags(xml, "item"));
+ }
+
+ @Test
+ public void testPersistDifferentOverlaysSameUser() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B0);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mSettings.persist(os);
+ final String xml = new String(os.toByteArray(), "utf-8");
+
+ assertEquals(1, countXmlTags(xml, "overlays"));
+ assertEquals(2, countXmlTags(xml, "item"));
+ assertEquals(1, countXmlAttributesWhere(xml, "item", "packageName",
+ OVERLAY_A0.packageName));
+ assertEquals(1, countXmlAttributesWhere(xml, "item", "packageName",
+ OVERLAY_B0.packageName));
+ assertEquals(2, countXmlAttributesWhere(xml, "item", "userId",
+ Integer.toString(OVERLAY_A0.userId)));
+ }
+
+ @Test
+ public void testPersistSameOverlayDifferentUsers() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_A1);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mSettings.persist(os);
+ String xml = new String(os.toByteArray(), "utf-8");
+
+ assertEquals(1, countXmlTags(xml, "overlays"));
+ assertEquals(2, countXmlTags(xml, "item"));
+ assertEquals(2, countXmlAttributesWhere(xml, "item", "packageName",
+ OVERLAY_A0.packageName));
+ assertEquals(1, countXmlAttributesWhere(xml, "item", "userId",
+ Integer.toString(OVERLAY_A0.userId)));
+ assertEquals(1, countXmlAttributesWhere(xml, "item", "userId",
+ Integer.toString(OVERLAY_A1.userId)));
+ }
+
+ @Test
+ public void testPersistEnabled() throws Exception {
+ insert(OVERLAY_A0);
+ mSettings.setEnabled(OVERLAY_A0.packageName, OVERLAY_A0.userId, true);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mSettings.persist(os);
+ String xml = new String(os.toByteArray(), "utf-8");
+
+ assertEquals(1, countXmlAttributesWhere(xml, "item", "isEnabled", "true"));
+ }
+
+ @Test
+ public void testRestoreEmpty() throws Exception {
+ final int version = OverlayManagerSettings.Serializer.CURRENT_VERSION;
+ final String xml =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<overlays version=\"" + version + "\" />\n";
+ ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
+
+ mSettings.restore(is);
+ assertDoesNotContain(mSettings, "com.dummy.overlay", 0);
+ }
+
+ @Test
+ public void testRestoreSingleUserSingleOverlay() throws Exception {
+ final int version = OverlayManagerSettings.Serializer.CURRENT_VERSION;
+ final String xml =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n"
+ + "<overlays version='" + version + "'>\n"
+ + "<item packageName='com.dummy.overlay'\n"
+ + " userId='1234'\n"
+ + " targetPackageName='com.dummy.target'\n"
+ + " baseCodePath='/data/app/com.dummy.overlay-1/base.apk'\n"
+ + " state='" + STATE_DISABLED + "'\n"
+ + " isEnabled='false'\n"
+ + " category='dummy-category'\n"
+ + " isStatic='false'\n"
+ + " priority='0' />\n"
+ + "</overlays>\n";
+ ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
+
+ mSettings.restore(is);
+ OverlayInfo oi = mSettings.getOverlayInfo("com.dummy.overlay", 1234);
+ assertNotNull(oi);
+ assertEquals("com.dummy.overlay", oi.packageName);
+ assertEquals("com.dummy.target", oi.targetPackageName);
+ assertEquals("/data/app/com.dummy.overlay-1/base.apk", oi.baseCodePath);
+ assertEquals(1234, oi.userId);
+ assertEquals(STATE_DISABLED, oi.state);
+ assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234));
+ }
+
+ @Test
+ public void testPersistAndRestore() throws Exception {
+ insert(OVERLAY_A0);
+ insert(OVERLAY_B1);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mSettings.persist(os);
+ String xml = new String(os.toByteArray(), "utf-8");
+ ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
+ OverlayManagerSettings newSettings = new OverlayManagerSettings();
+ newSettings.restore(is);
+
+ OverlayInfo a = newSettings.getOverlayInfo(OVERLAY_A0.packageName, OVERLAY_A0.userId);
+ assertEquals(OVERLAY_A0, a);
+
+ OverlayInfo b = newSettings.getOverlayInfo(OVERLAY_B1.packageName, OVERLAY_B1.userId);
+ assertEquals(OVERLAY_B1, b);
+ }
+
+ private int countXmlTags(String xml, String tagToLookFor) throws Exception {
+ int count = 0;
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new StringReader(xml));
+ int event = parser.getEventType();
+ while (event != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG && tagToLookFor.equals(parser.getName())) {
+ count++;
+ }
+ event = parser.next();
+ }
+ return count;
+ }
+
+ private int countXmlAttributesWhere(String xml, String tag, String attr, String value)
+ throws Exception {
+ int count = 0;
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new StringReader(xml));
+ int event = parser.getEventType();
+ while (event != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG && tag.equals(parser.getName())) {
+ String v = parser.getAttributeValue(null, attr);
+ if (value.equals(v)) {
+ count++;
+ }
+ }
+ event = parser.next();
+ }
+ return count;
+ }
+
+ private void insert(OverlayInfo oi) throws Exception {
+ mSettings.init(oi.packageName, oi.userId, oi.targetPackageName, null, oi.baseCodePath,
+ false, 0, oi.category);
+ mSettings.setState(oi.packageName, oi.userId, oi.state);
+ mSettings.setEnabled(oi.packageName, oi.userId, false);
+ }
+
+ private static void assertContains(final OverlayManagerSettings settings,
+ final OverlayInfo oi) {
+ assertContains(settings, oi.packageName, oi.userId);
+ }
+
+ private static void assertContains(final OverlayManagerSettings settings,
+ final String packageName, int userId) {
+ try {
+ settings.getOverlayInfo(packageName, userId);
+ } catch (OverlayManagerSettings.BadKeyException e) {
+ fail(String.format("settings does not contain packageName=%s userId=%d",
+ packageName, userId));
+ }
+ }
+
+ private static void assertDoesNotContain(final OverlayManagerSettings settings,
+ final OverlayInfo oi) {
+ assertDoesNotContain(settings, oi.packageName, oi.userId);
+ }
+
+ private static void assertDoesNotContain(final OverlayManagerSettings settings,
+ final String packageName, int userId) {
+ try {
+ settings.getOverlayInfo(packageName, userId);
+ fail(String.format("settings contains packageName=%s userId=%d", packageName, userId));
+ } catch (OverlayManagerSettings.BadKeyException e) {
+ // do nothing: we expect to end up here
+ }
+ }
+
+ private static void assertContains(int[] haystack, int needle) {
+ List<Integer> list = IntStream.of(haystack)
+ .boxed()
+ .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+ if (!list.contains(needle)) {
+ fail(String.format("integer array [%s] does not contain value %s",
+ TextUtils.join(",", list), needle));
+ }
+ }
+
+ private static void assertDoesNotContain(int[] haystack, int needle) {
+ List<Integer> list = IntStream.of(haystack)
+ .boxed()
+ .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+ if (list.contains(needle)) {
+ fail(String.format("integer array [%s] contains value %s",
+ TextUtils.join(",", list), needle));
+ }
+ }
+
+ private static void assertListsAreEqual(List<OverlayInfo> list, OverlayInfo... array) {
+ List<OverlayInfo> other = Stream.of(array)
+ .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+ assertListsAreEqual(list, other);
+ }
+
+ private static void assertListsAreEqual(List<OverlayInfo> list, List<OverlayInfo> other) {
+ if (!list.equals(other)) {
+ fail(String.format("lists [%s] and [%s] differ",
+ TextUtils.join(",", list), TextUtils.join(",", other)));
+ }
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 6ed78b36190f..b34bd2595287 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -940,12 +940,12 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testClearLockedFields() {
final NotificationChannel channel = getChannel();
- mHelper.clearLockedFields(channel);
+ mHelper.clearLockedFieldsLocked(channel);
assertEquals(0, channel.getUserLockedFields());
channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY
| NotificationChannel.USER_LOCKED_IMPORTANCE);
- mHelper.clearLockedFields(channel);
+ mHelper.clearLockedFieldsLocked(channel);
assertEquals(0, channel.getUserLockedFields());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 9ce579512eda..beec1a8b8942 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -18,6 +18,8 @@ package com.android.server.wm;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.server.wm.BoundsAnimationController.BOUNDS;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
@@ -131,6 +133,8 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
boolean mCancelRequested;
Rect mStackBounds;
Rect mTaskBounds;
+ float mAlpha;
+ @BoundsAnimationController.AnimationType int mAnimationType;
void initialize(Rect from) {
mAwaitingAnimationStart = true;
@@ -148,11 +152,12 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@Override
public boolean onAnimationStart(boolean schedulePipModeChangedCallback,
- boolean forceUpdate) {
+ boolean forceUpdate, @BoundsAnimationController.AnimationType int animationType) {
mAwaitingAnimationStart = false;
mAnimationStarted = true;
mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
mForcePipModeChangedCallback = forceUpdate;
+ mAnimationType = animationType;
return true;
}
@@ -185,6 +190,12 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
mMovedToFullscreen = moveToFullscreen;
mTaskBounds = null;
}
+
+ @Override
+ public boolean setPinnedStackAlpha(float alpha) {
+ mAlpha = alpha;
+ return true;
+ }
}
/**
@@ -201,6 +212,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
private Rect mTo;
private Rect mLargerBounds;
private Rect mExpectedFinalBounds;
+ private @BoundsAnimationController.AnimationType int mAnimationType;
BoundsAnimationDriver(BoundsAnimationController controller,
TestBoundsAnimationTarget target, MockValueAnimator mockValueAnimator) {
@@ -209,7 +221,8 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
mMockAnimator = mockValueAnimator;
}
- BoundsAnimationDriver start(Rect from, Rect to) {
+ BoundsAnimationDriver start(Rect from, Rect to,
+ @BoundsAnimationController.AnimationType int animationType) {
if (mAnimator != null) {
throw new IllegalArgumentException("Call restart() to restart an animation");
}
@@ -223,7 +236,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
assertTrue(mTarget.mAwaitingAnimationStart);
assertFalse(mTarget.mAnimationStarted);
- startImpl(from, to);
+ startImpl(from, to, animationType);
// Ensure that the animator is paused for the all windows drawn signal when animating
// to/from fullscreen
@@ -253,7 +266,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
mTarget.mAnimationStarted = false;
// Start animation
- startImpl(mTarget.mStackBounds, to);
+ startImpl(mTarget.mStackBounds, to, BOUNDS);
if (toSameBounds) {
// Same animator if same final bounds
@@ -273,13 +286,15 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
return this;
}
- private BoundsAnimationDriver startImpl(Rect from, Rect to) {
+ private BoundsAnimationDriver startImpl(Rect from, Rect to,
+ @BoundsAnimationController.AnimationType int animationType) {
boolean fromFullscreen = from.equals(BOUNDS_FULL);
boolean toFullscreen = to.equals(BOUNDS_FULL);
mFrom = new Rect(from);
mTo = new Rect(to);
mExpectedFinalBounds = new Rect(to);
mLargerBounds = getLargerBounds(mFrom, mTo);
+ mAnimationType = animationType;
// Start animation
final @SchedulePipModeChangedState int schedulePipModeChangedState = toFullscreen
@@ -288,17 +303,19 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
? SCHEDULE_PIP_MODE_CHANGED_ON_END
: NO_PIP_MODE_CHANGED_CALLBACKS;
mAnimator = mController.animateBoundsImpl(mTarget, from, to, DURATION,
- schedulePipModeChangedState, fromFullscreen, toFullscreen);
-
- // Original stack bounds, frozen task bounds
- assertEquals(mFrom, mTarget.mStackBounds);
- assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
+ schedulePipModeChangedState, fromFullscreen, toFullscreen, animationType);
- // Animating to larger size
- if (mFrom.equals(mLargerBounds)) {
- assertFalse(mAnimator.animatingToLargerSize());
- } else if (mTo.equals(mLargerBounds)) {
- assertTrue(mAnimator.animatingToLargerSize());
+ if (animationType == BOUNDS) {
+ // Original stack bounds, frozen task bounds
+ assertEquals(mFrom, mTarget.mStackBounds);
+ assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
+
+ // Animating to larger size
+ if (mFrom.equals(mLargerBounds)) {
+ assertFalse(mAnimator.animatingToLargerSize());
+ } else if (mTo.equals(mLargerBounds)) {
+ assertTrue(mAnimator.animatingToLargerSize());
+ }
}
return this;
@@ -315,16 +332,20 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
BoundsAnimationDriver update(float t) {
mAnimator.onAnimationUpdate(mMockAnimator.getWithValue(t));
- // Temporary stack bounds, frozen task bounds
- if (t == 0f) {
- assertEquals(mFrom, mTarget.mStackBounds);
- } else if (t == 1f) {
- assertEquals(mTo, mTarget.mStackBounds);
+ if (mAnimationType == BOUNDS) {
+ // Temporary stack bounds, frozen task bounds
+ if (t == 0f) {
+ assertEquals(mFrom, mTarget.mStackBounds);
+ } else if (t == 1f) {
+ assertEquals(mTo, mTarget.mStackBounds);
+ } else {
+ assertNotEquals(mFrom, mTarget.mStackBounds);
+ assertNotEquals(mTo, mTarget.mStackBounds);
+ }
+ assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
} else {
- assertNotEquals(mFrom, mTarget.mStackBounds);
- assertNotEquals(mTo, mTarget.mStackBounds);
+ assertEquals((float) mMockAnimator.getAnimatedValue(), mTarget.mAlpha, 0.01f);
}
- assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
return this;
}
@@ -353,10 +374,14 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
BoundsAnimationDriver end() {
mAnimator.end();
- // Final stack bounds
- assertEquals(mTo, mTarget.mStackBounds);
- assertEquals(mExpectedFinalBounds, mTarget.mAnimationEndFinalStackBounds);
- assertNull(mTarget.mTaskBounds);
+ if (mAnimationType == BOUNDS) {
+ // Final stack bounds
+ assertEquals(mTo, mTarget.mStackBounds);
+ assertEquals(mExpectedFinalBounds, mTarget.mAnimationEndFinalStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ } else {
+ assertEquals(mTarget.mAlpha, 1f, 0.01f);
+ }
return this;
}
@@ -413,7 +438,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFullscreenToFloatingTransition() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -425,7 +450,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToFullscreenTransition() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -437,7 +462,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToSmallerFloatingTransition() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -449,7 +474,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToLargerFloatingTransition() {
- mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -463,7 +488,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -473,7 +498,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromAnimationToSameBounds() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FLOATING, false /* expectStartedAndPipModeChangedCallback */)
@@ -484,7 +509,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromAnimationToFloatingBounds() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_SMALLER_FLOATING,
@@ -498,7 +523,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
public void testFullscreenToFloatingCancelFromAnimationToFullscreenBounds() {
// When animating from fullscreen and the animation is interruped, we expect the animation
// start callback to be made, with a forced pip mode change callback
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FULL, true /* expectStartedAndPipModeChangedCallback */)
@@ -511,7 +536,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromTarget() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -521,7 +546,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromAnimationToSameBounds() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FULL, false /* expectStartedAndPipModeChangedCallback */)
@@ -532,7 +557,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromAnimationToFloatingBounds() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_SMALLER_FLOATING,
@@ -546,7 +571,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToSmallerFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -556,13 +581,25 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
@UiThreadTest
@Test
public void testFloatingToLargerFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
.expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
}
+ @UiThreadTest
+ @Test
+ public void testFadeIn() {
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, FADE_IN)
+ .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+ .update(0f)
+ .update(0.5f)
+ .update(1f)
+ .end()
+ .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+ }
+
/** MISC **/
@UiThreadTest
@@ -570,7 +607,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
public void testBoundsAreCopied() {
Rect from = new Rect(0, 0, 100, 100);
Rect to = new Rect(25, 25, 75, 75);
- mDriver.start(from, to)
+ mDriver.start(from, to, BOUNDS)
.update(0.25f)
.end();
assertEquals(new Rect(0, 0, 100, 100), from);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index e392353a8875..0c2ce614b772 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -163,7 +163,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
// Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot
// animation.
mController.mRecentScreenshotAnimator.cancelAnimation();
- verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true);
+ verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true, false);
}
private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 5625ea42726f..f615823a645c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -71,6 +71,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testCancelAnimationOnVisibleStackOrderChange() {
ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
+ display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
new ActivityBuilder(mService)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 2377df406fbc..9cdb465dc445 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -19,16 +19,14 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -39,9 +37,9 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -53,7 +51,6 @@ import org.junit.Test;
*/
@SmallTest
@Presubmit
-@FlakyTest
public class TaskPositionerTests extends WindowTestsBase {
private static final boolean DEBUGGING = false;
@@ -66,10 +63,9 @@ public class TaskPositionerTests extends WindowTestsBase {
private int mMinVisibleHeight;
private TaskPositioner mPositioner;
private WindowState mWindow;
- private Rect mDimBounds = new Rect();
@Before
- public void setUp() throws Exception {
+ public void setUp() {
TaskPositioner.setFactory(null);
final Display display = mDisplayContent.getDisplay();
@@ -84,17 +80,16 @@ public class TaskPositionerTests extends WindowTestsBase {
mPositioner.register(mDisplayContent);
mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- final Task task = mWindow.getTask();
- spyOn(task);
- doAnswer(invocation -> {
- final Rect rect = (Rect) invocation.getArguments()[0];
- rect.set(mDimBounds);
- return null;
- }).when(task).getDimBounds(any(Rect.class));
-
+ mPositioner.mTask = mWindow.getTask();
mWindow.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
}
+ @After
+ public void tearDown() {
+ mWindow = null;
+ mPositioner = null;
+ }
+
@Test
public void testOverrideFactory() {
final boolean[] created = new boolean[1];
@@ -119,11 +114,11 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testBasicFreeWindowResizing() {
final Rect r = new Rect(100, 220, 700, 520);
final int midY = (r.top + r.bottom) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
// Start a drag resize starting upper left.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -149,8 +144,8 @@ public class TaskPositionerTests extends WindowTestsBase {
mPositioner.getWindowDragBounds());
// Start a drag resize left and see that only the left coord changes..
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -181,77 +176,77 @@ public class TaskPositionerTests extends WindowTestsBase {
final Rect r = new Rect(100, 220, 700, 520);
final int midX = (r.left + r.right) / 2;
final int midY = (r.top + r.bottom) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
// Drag upper left.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
- assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
- assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertNotEquals(r.top, mPositioner.getWindowDragBounds().top);
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
- assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertNotEquals(r.top, mPositioner.getWindowDragBounds().top);
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper right.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
- assertTrue(r.right != mPositioner.getWindowDragBounds().right);
- assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertNotEquals(r.top, mPositioner.getWindowDragBounds().top);
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag right.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.right + MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
- assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
assertEquals(r.top, mPositioner.getWindowDragBounds().top);
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom right.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/,
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */,
r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
- assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
assertEquals(r.top, mPositioner.getWindowDragBounds().top);
- assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+ assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, midX, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
assertEquals(r.top, mPositioner.getWindowDragBounds().top);
- assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+ assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom left.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
- assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
assertEquals(r.top, mPositioner.getWindowDragBounds().top);
- assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+ assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag left.
- mPositioner.startDrag(mWindow, true /*resizing*/,
- false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
- assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
assertEquals(r.top, mPositioner.getWindowDragBounds().top);
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
@@ -264,10 +259,10 @@ public class TaskPositionerTests extends WindowTestsBase {
@Test
public void testLandscapePreservedWindowResizingDragTopLeft() {
final Rect r = new Rect(100, 220, 700, 520);
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ true /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -303,10 +298,10 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testLandscapePreservedWindowResizingDragLeft() {
final Rect r = new Rect(100, 220, 700, 520);
final int midY = (r.top + r.bottom) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -344,7 +339,7 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testLandscapePreservedWindowResizingDragTop() {
final Rect r = new Rect(100, 220, 700, 520);
final int midX = (r.left + r.right) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
mPositioner.startDrag(mWindow, true /*resizing*/,
true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
@@ -380,7 +375,7 @@ public class TaskPositionerTests extends WindowTestsBase {
@Test
public void testPortraitPreservedWindowResizingDragTopLeft() {
final Rect r = new Rect(330, 100, 630, 600);
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
mPositioner.startDrag(mWindow, true /*resizing*/,
true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
@@ -414,10 +409,10 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testPortraitPreservedWindowResizingDragLeft() {
final Rect r = new Rect(330, 100, 630, 600);
final int midY = (r.top + r.bottom) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -457,10 +452,10 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testPortraitPreservedWindowResizingDragTop() {
final Rect r = new Rect(330, 100, 630, 600);
final int midX = (r.left + r.right) / 2;
- mDimBounds.set(r);
+ mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(mWindow, true /* resizing */,
+ true /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
// Drag to the left (no change).
mPositioner.resizeDrag(0.0f, r.top);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 897f0a2c6e81..0330de8d2c63 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -22,6 +22,8 @@ import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -70,7 +72,8 @@ public class WindowAnimationSpecTest {
mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM,
true /* isAppAnimation */, 0 /* windowCornerRadius */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
- verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
+ verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
+ argThat(rect -> rect.equals(mStackBounds)));
}
@Test
@@ -80,7 +83,8 @@ public class WindowAnimationSpecTest {
new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
STACK_CLIP_AFTER_ANIM, true /* isAppAnimation */, 0 /* windowCornerRadius */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
- verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
+ verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
+ argThat(rect -> rect.equals(mStackBounds)));
}
@Test
@@ -121,6 +125,17 @@ public class WindowAnimationSpecTest {
}
@Test
+ public void testApply_setCornerRadius_noClip() {
+ final float windowCornerRadius = 30f;
+ WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE,
+ true /* isAppAnimation */, windowCornerRadius);
+ when(mAnimation.hasRoundedCorners()).thenReturn(true);
+ windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
+ verify(mTransaction, never()).setCornerRadius(any(), anyFloat());
+ }
+
+ @Test
public void testApply_clipBeforeSmallerAnimationClip() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5)
Rect windowCrop = new Rect(0, 0, 5, 5);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index ad1e3ef43ea4..4d7ae7309e27 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1238,6 +1238,9 @@ public class VoiceInteractionManagerService extends SystemService {
RoleObserver(@NonNull @CallbackExecutor Executor executor) {
mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
+ UserHandle currentUser = UserHandle.of(LocalServices.getService(
+ ActivityManagerInternal.class).getCurrentUserId());
+ onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
}
private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
@@ -1285,7 +1288,9 @@ public class VoiceInteractionManagerService extends SystemService {
// Try to set role holder as VoiceInteractionService
List<ResolveInfo> services = mPm.queryIntentServicesAsUser(
new Intent(VoiceInteractionService.SERVICE_INTERFACE).setPackage(pkg),
- PackageManager.GET_META_DATA, userId);
+ PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
for (ResolveInfo resolveInfo : services) {
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
@@ -1318,7 +1323,9 @@ public class VoiceInteractionManagerService extends SystemService {
// If no service could be found try to set assist activity
final List<ResolveInfo> activities = mPm.queryIntentActivitiesAsUser(
new Intent(Intent.ACTION_ASSIST).setPackage(pkg),
- PackageManager.MATCH_DEFAULT_ONLY, userId);
+ PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
for (ResolveInfo resolveInfo : activities) {
ActivityInfo activityInfo = resolveInfo.activityInfo;
@@ -1331,6 +1338,7 @@ public class VoiceInteractionManagerService extends SystemService {
Settings.Secure.putStringForUser(getContext().getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE,
getDefaultRecognizer(user), userId);
+ return;
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 8d2cbca08586..ea523774bf84 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -25,9 +25,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
-
-import com.android.internal.app.IVoiceActionCheckCallback;
-import com.android.server.wm.ActivityTaskManagerInternal;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.content.BroadcastReceiver;
@@ -51,15 +48,16 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.view.IWindowManager;
+import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback {
final static String TAG = "VoiceInteractionServiceManager";
@@ -358,6 +356,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
intent.setComponent(mComponent);
mBound = mContext.bindServiceAsUser(intent, mConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_INCLUDE_CAPABILITIES
| Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
if (!mBound) {
Slog.w(TAG, "Failed binding to voice interaction service " + mComponent);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0f8f873b6847..970bbf89b39e 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2803,6 +2803,19 @@ public class CarrierConfigManager {
public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
"key_is_opportunistic_subscription_bool";
+ /**
+ * A list of 4 GSM RSSI thresholds above which a signal level is considered POOR,
+ * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+ *
+ * Note that the min and max thresholds are fixed at -113 and -51, as set in 3GPP TS 27.007
+ * section 8.5.
+ * <p>
+ * See CellSignalStrengthGsm#GSM_RSSI_MAX and CellSignalStrengthGsm#GSM_RSSI_MIN. Any signal
+ * level outside these boundaries is considered invalid.
+ * @hide
+ */
+ public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY =
+ "gsm_rssi_thresholds_int_array";
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3204,6 +3217,13 @@ public class CarrierConfigManager {
false);
sDefaults.putString(KEY_SUBSCRIPTION_GROUP_UUID_STRING, "");
sDefaults.putBoolean(KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false);
+ sDefaults.putIntArray(KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -107, /* SIGNAL_STRENGTH_POOR */
+ -103, /* SIGNAL_STRENGTH_MODERATE */
+ -97, /* SIGNAL_STRENGTH_GOOD */
+ -89, /* SIGNAL_STRENGTH_GREAT */
+ });
}
/**
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 5e44bf2e37a8..864540d91be3 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -166,6 +166,7 @@ public final class CellIdentityGsm extends CellIdentity {
/**
* @return Mobile Country Code in string format, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -173,6 +174,7 @@ public final class CellIdentityGsm extends CellIdentity {
/**
* @return Mobile Network Code in string format, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 2dd72d6ea69c..14503c7cdd4d 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -187,6 +187,7 @@ public final class CellIdentityLte extends CellIdentity {
/**
* @return Mobile Country Code in string format, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -194,6 +195,7 @@ public final class CellIdentityLte extends CellIdentity {
/**
* @return Mobile Network Code in string format, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index a591bd15f95f..937de706aec0 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -104,6 +104,7 @@ public final class CellIdentityTdscdma extends CellIdentity {
* Get Mobile Country Code in string format
* @return Mobile Country Code in string format, null if unknown
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -112,6 +113,7 @@ public final class CellIdentityTdscdma extends CellIdentity {
* Get Mobile Network Code in string format
* @return Mobile Network Code in string format, null if unknown
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 674c40c2d36f..b4a2ead7fc3d 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -150,6 +150,7 @@ public final class CellIdentityWcdma extends CellIdentity {
/**
* @return Mobile Country Code in string version, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -157,6 +158,7 @@ public final class CellIdentityWcdma extends CellIdentity {
/**
* @return Mobile Network Code in string version, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index a4570e41dc26..30b131faf51d 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -76,18 +77,25 @@ public final class CellInfoCdma extends CellInfo implements Parcelable {
new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
}
+ /**
+ * @return a {@link CellIdentityCdma} instance.
+ */
@Override
- public CellIdentityCdma getCellIdentity() {
+ public @NonNull CellIdentityCdma getCellIdentity() {
return mCellIdentityCdma;
}
+
/** @hide */
@UnsupportedAppUsage
public void setCellIdentity(CellIdentityCdma cid) {
mCellIdentityCdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthCdma} instance.
+ */
@Override
- public CellSignalStrengthCdma getCellSignalStrength() {
+ public @NonNull CellSignalStrengthCdma getCellSignalStrength() {
return mCellSignalStrengthCdma;
}
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index ce32bc1b9cb7..137f97eeee62 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -71,17 +72,24 @@ public final class CellInfoGsm extends CellInfo implements Parcelable {
mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
}
+ /**
+ * @return a {@link CellIdentityGsm} instance.
+ */
@Override
- public CellIdentityGsm getCellIdentity() {
+ public @NonNull CellIdentityGsm getCellIdentity() {
return mCellIdentityGsm;
}
+
/** @hide */
public void setCellIdentity(CellIdentityGsm cid) {
mCellIdentityGsm = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthGsm} instance.
+ */
@Override
- public CellSignalStrengthGsm getCellSignalStrength() {
+ public @NonNull CellSignalStrengthGsm getCellSignalStrength() {
return mCellSignalStrengthGsm;
}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 01ee20a7fa1e..da7b7ab1488d 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -79,11 +80,15 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
mCellConfig = new CellConfigLte(cil.cellConfig);
}
+ /**
+ * @return a {@link CellIdentityLte} instance.
+ */
@Override
- public CellIdentityLte getCellIdentity() {
+ public @NonNull CellIdentityLte getCellIdentity() {
if (DBG) log("getCellIdentity: " + mCellIdentityLte);
return mCellIdentityLte;
}
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void setCellIdentity(CellIdentityLte cid) {
@@ -91,8 +96,11 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
mCellIdentityLte = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthLte} instance.
+ */
@Override
- public CellSignalStrengthLte getCellSignalStrength() {
+ public @NonNull CellSignalStrengthLte getCellSignalStrength() {
if (DBG) log("getCellSignalStrength: " + mCellSignalStrengthLte);
return mCellSignalStrengthLte;
}
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index ba4a907fdce8..9775abd5075c 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -43,12 +43,18 @@ public final class CellInfoNr extends CellInfo {
mCellSignalStrength = other.mCellSignalStrength;
}
+ /**
+ * @return a {@link CellIdentityNr} instance.
+ */
@Override
@NonNull
public CellIdentity getCellIdentity() {
return mCellIdentity;
}
+ /**
+ * @return a {@link CellSignalStrengthNr} instance.
+ */
@Override
@NonNull
public CellSignalStrength getCellSignalStrength() {
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index ccafda61a177..f1305f5ca768 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -75,6 +75,9 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable {
mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
}
+ /**
+ * @return a {@link CellIdentityTdscdma} instance.
+ */
@Override
public @NonNull CellIdentityTdscdma getCellIdentity() {
return mCellIdentityTdscdma;
@@ -85,6 +88,9 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable {
mCellIdentityTdscdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthTdscdma} instance.
+ */
@Override
public @NonNull CellSignalStrengthTdscdma getCellSignalStrength() {
return mCellSignalStrengthTdscdma;
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 1b32178db337..ee5fec838d2d 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -71,15 +71,22 @@ public final class CellInfoWcdma extends CellInfo implements Parcelable {
mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
}
+ /**
+ * @return a {@link CellIdentityWcdma} instance.
+ */
@Override
public CellIdentityWcdma getCellIdentity() {
return mCellIdentityWcdma;
}
+
/** @hide */
public void setCellIdentity(CellIdentityWcdma cid) {
mCellIdentityWcdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthWcdma} instance.
+ */
@Override
public CellSignalStrengthWcdma getCellSignalStrength() {
return mCellSignalStrengthWcdma;
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index 740b970b8e7c..e65b048ec0a5 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.PersistableBundle;
/**
@@ -57,23 +58,24 @@ public abstract class CellSignalStrength {
public abstract void setDefaultValues();
/**
- * Get signal level as an int from 0..4
- * <p>
- * @see #SIGNAL_STRENGTH_NONE_OR_UNKNOWN
- * @see #SIGNAL_STRENGTH_POOR
- * @see #SIGNAL_STRENGTH_MODERATE
- * @see #SIGNAL_STRENGTH_GOOD
- * @see #SIGNAL_STRENGTH_GREAT
+ * Retrieve an abstract level value for the overall signal quality.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor or unknown signal quality while 4 represents excellent
+ * signal quality.
*/
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public abstract int getLevel();
/**
- * Get the signal level as an asu value between 0..31, 99 is unknown
+ * Get the technology-specific signal strength in Arbitrary Strength Units, calculated from the
+ * strength of the pilot signal or equivalent.
*/
public abstract int getAsuLevel();
/**
- * Get the signal strength as dBm
+ * Get the technology-specific signal strength in dBm, which is the signal strength of the
+ * pilot signal or equivalent.
*/
public abstract int getDbm();
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 5b195999078c..199843905854 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -114,13 +115,9 @@ public final class CellSignalStrengthCdma extends CellSignalStrength implements
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 0aeb0f6e66d8..14ae68981745 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,6 +38,10 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P
private static final int GSM_RSSI_GOOD = -97;
private static final int GSM_RSSI_MODERATE = -103;
private static final int GSM_RSSI_POOR = -107;
+ private static final int GSM_RSSI_MIN = -113;
+
+ private static final int[] sRssiThresholds = new int[] {
+ GSM_RSSI_POOR, GSM_RSSI_MODERATE, GSM_RSSI_GOOD, GSM_RSSI_GREAT};
private int mRssi; // in dBm [-113, -51] or UNAVAILABLE
@UnsupportedAppUsage
@@ -53,7 +58,7 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P
/** @hide */
public CellSignalStrengthGsm(int rssi, int ber, int ta) {
- mRssi = inRangeOrUnavailable(rssi, -113, -51);
+ mRssi = inRangeOrUnavailable(rssi, GSM_RSSI_MIN, GSM_RSSI_MAX);
mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
mTimingAdvance = inRangeOrUnavailable(ta, 0, 219);
updateLevel(null, null);
@@ -97,13 +102,9 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -111,12 +112,22 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mRssi > GSM_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- else if (mRssi >= GSM_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
- else if (mRssi >= GSM_RSSI_GOOD) mLevel = SIGNAL_STRENGTH_GOOD;
- else if (mRssi >= GSM_RSSI_MODERATE) mLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mRssi >= GSM_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
- else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ int[] rssiThresholds;
+ if (cc == null) {
+ rssiThresholds = sRssiThresholds;
+ } else {
+ rssiThresholds = cc.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY);
+ if (rssiThresholds == null || rssiThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
+ rssiThresholds = sRssiThresholds;
+ }
+ }
+ int level = NUM_SIGNAL_STRENGTH_THRESHOLDS;
+ if (mRssi < GSM_RSSI_MIN || mRssi > GSM_RSSI_MAX) {
+ mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ return;
+ }
+ while (level > 0 && mRssi < rssiThresholds[level - 1]) level--;
+ mLevel = level;
}
/**
@@ -141,7 +152,7 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P
/**
* Get the RSSI in ASU.
*
- * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+ * Asu is calculated based on 3GPP RSSI. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
*
* @return RSSI in ASU 0..31, 99, or UNAVAILABLE
*/
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 5687adaabed5..2272dc9071ea 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -145,13 +146,9 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index fff3adf04f7b..1912c60ac122 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -183,7 +184,9 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -227,6 +230,9 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
return asuLevel;
}
+ /**
+ * Get the CSI-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
+ */
@Override
public int getDbm() {
return mCsiRsrp;
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index ddbd851bbce5..f4a3dbb37988 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,14 +35,14 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen
private static final String LOG_TAG = "CellSignalStrengthTdscdma";
private static final boolean DBG = false;
- private static final int TDSCDMA_RSSI_MAX = -51;
- private static final int TDSCDMA_RSSI_GREAT = -77;
- private static final int TDSCDMA_RSSI_GOOD = -87;
- private static final int TDSCDMA_RSSI_MODERATE = -97;
- private static final int TDSCDMA_RSSI_POOR = -107;
-
- private static final int TDSCDMA_RSCP_MIN = -120;
+ // These levels are arbitrary but carried over from SignalStrength.java for consistency.
private static final int TDSCDMA_RSCP_MAX = -24;
+ private static final int TDSCDMA_RSCP_GREAT = -49;
+ private static final int TDSCDMA_RSCP_GOOD = -73;
+ private static final int TDSCDMA_RSCP_MODERATE = -97;
+ private static final int TDSCDMA_RSCP_POOR = -110;
+ private static final int TDSCDMA_RSCP_MIN = -120;
+
private int mRssi; // in dBm [-113, -51], CellInfo.UNAVAILABLE
@@ -121,13 +122,10 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = 0, to = 4)
public int getLevel() {
return mLevel;
}
@@ -135,16 +133,16 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mRssi > TDSCDMA_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- else if (mRssi >= TDSCDMA_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
- else if (mRssi >= TDSCDMA_RSSI_GOOD) mLevel = SIGNAL_STRENGTH_GOOD;
- else if (mRssi >= TDSCDMA_RSSI_MODERATE) mLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mRssi >= TDSCDMA_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
+ if (mRscp > TDSCDMA_RSCP_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ else if (mRscp >= TDSCDMA_RSCP_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
+ else if (mRscp >= TDSCDMA_RSCP_GOOD) mLevel = SIGNAL_STRENGTH_GOOD;
+ else if (mRscp >= TDSCDMA_RSCP_MODERATE) mLevel = SIGNAL_STRENGTH_MODERATE;
+ else if (mRscp >= TDSCDMA_RSCP_POOR) mLevel = SIGNAL_STRENGTH_POOR;
else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
/**
- * Get the signal strength as dBm
+ * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
*/
@Override
public int getDbm() {
@@ -159,6 +157,23 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen
}
/**
+ * Get the RSSI as dBm value -113..-51dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
+ *
+ * @hide
+ */
+ public int getRssi() {
+ return mRssi;
+ }
+
+ /**
+ * Get the BER as an ASU value 0..7, 99, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
+ * @hide
+ */
+ public int getBitErrorRate() {
+ return mBitErrorRate;
+ }
+
+ /**
* Get the RSCP in ASU.
*
* Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index d9fd7f39aed3..169325276821 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.StringDef;
import android.os.Parcel;
import android.os.Parcelable;
@@ -66,7 +67,7 @@ public final class CellSignalStrengthWcdma extends CellSignalStrength implements
public static final String LEVEL_CALCULATION_METHOD_RSCP = "rscp";
// Default to RSSI for backwards compatibility with older devices
- private static final String sLevelCalculationMethod = LEVEL_CALCULATION_METHOD_RSSI;
+ private static final String DEFAULT_LEVEL_CALCULATION_METHOD = LEVEL_CALCULATION_METHOD_RSSI;
private int mRssi; // in dBm [-113, 51] or CellInfo.UNAVAILABLE if unknown
private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
@@ -143,13 +144,9 @@ public final class CellSignalStrengthWcdma extends CellSignalStrength implements
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -161,14 +158,14 @@ public final class CellSignalStrengthWcdma extends CellSignalStrength implements
int[] rscpThresholds;
if (cc == null) {
- calcMethod = sLevelCalculationMethod;
+ calcMethod = DEFAULT_LEVEL_CALCULATION_METHOD;
rscpThresholds = sRscpThresholds;
} else {
// TODO: abstract this entire thing into a series of functions
calcMethod = cc.getString(
CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING,
- sLevelCalculationMethod);
- if (TextUtils.isEmpty(calcMethod)) calcMethod = sLevelCalculationMethod;
+ DEFAULT_LEVEL_CALCULATION_METHOD);
+ if (TextUtils.isEmpty(calcMethod)) calcMethod = DEFAULT_LEVEL_CALCULATION_METHOD;
rscpThresholds = cc.getIntArray(
CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
if (rscpThresholds == null || rscpThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
@@ -202,7 +199,7 @@ public final class CellSignalStrengthWcdma extends CellSignalStrength implements
}
/**
- * Get the signal strength as dBm
+ * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
*/
@Override
public int getDbm() {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a933da753c41..57c84a638f12 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2749,6 +2749,8 @@ public class SubscriptionManager {
*
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
+ * @throws IllegalArgumentException if any of the subscriptions in the list doesn't exist.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that will be in the same group
* @return groupUUID a UUID assigned to the subscription group.
@@ -2797,6 +2799,7 @@ public class SubscriptionManager {
* outlined above.
* @throws IllegalArgumentException if the some subscriptions in the list doesn't exist,
* or the groupUuid doesn't exist.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that need adding into the group
* @param groupUuid the groupUuid the subscriptions are being added to.
@@ -2849,6 +2852,7 @@ public class SubscriptionManager {
* outlined above.
* @throws IllegalArgumentException if the some subscriptions in the list doesn't belong
* the specified group.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that need removing from their groups.
*
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 7eea21860bce..a86fda4454d7 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -78,10 +78,11 @@ public class ApnSetting implements Parcelable {
*/
public static final int TYPE_NONE = ApnTypes.NONE;
/**
- * APN type for all APNs.
+ * APN type for all APNs (except wild-cardable types).
* @hide
*/
- public static final int TYPE_ALL = ApnTypes.ALL | ApnTypes.MCX;
+ public static final int TYPE_ALL = ApnTypes.DEFAULT | ApnTypes.HIPRI | ApnTypes.MMS
+ | ApnTypes.SUPL | ApnTypes.DUN | ApnTypes.FOTA | ApnTypes.IMS | ApnTypes.CBS;
/** APN type for default data traffic. */
public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI;
/** APN type for MMS traffic. */
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 70b408949dea..c8ef82ec9acc 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -4,6 +4,7 @@
java_defaults {
name: "FrameworksNetTests-jni-defaults",
static_libs: [
+ "FrameworksNetCommonTests",
"frameworks-base-testutils",
"framework-protos",
"androidx.test.rules",
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
new file mode 100644
index 000000000000..0a1ac75aac80
--- /dev/null
+++ b/tests/net/common/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Tests in this folder are included both in unit tests and CTS.
+// They must be fast and stable, and exercise public or test APIs.
+java_library {
+ name: "FrameworksNetCommonTests",
+ srcs: ["java/**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "junit",
+ ],
+ libs: [
+ "android.test.base.stubs",
+ ],
+} \ No newline at end of file
diff --git a/tests/net/java/android/net/IpPrefixTest.java b/tests/net/common/java/android/net/IpPrefixTest.java
index abf019afed44..719960d48604 100644
--- a/tests/net/java/android/net/IpPrefixTest.java
+++ b/tests/net/common/java/android/net/IpPrefixTest.java
@@ -39,7 +39,7 @@ import java.util.Random;
@SmallTest
public class IpPrefixTest {
- private static InetAddress Address(String addr) {
+ private static InetAddress address(String addr) {
return InetAddress.parseNumericAddress(addr);
}
@@ -58,59 +58,59 @@ public class IpPrefixTest {
try {
p = new IpPrefix((byte[]) null, 9);
fail("Expected NullPointerException: null byte array");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
p = new IpPrefix((InetAddress) null, 10);
fail("Expected NullPointerException: null InetAddress");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
p = new IpPrefix((String) null);
fail("Expected NullPointerException: null String");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
byte[] b2 = {1, 2, 3, 4, 5};
p = new IpPrefix(b2, 29);
fail("Expected IllegalArgumentException: invalid array length");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("1.2.3.4");
fail("Expected IllegalArgumentException: no prefix length");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("1.2.3.4/");
fail("Expected IllegalArgumentException: empty prefix length");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("foo/32");
fail("Expected IllegalArgumentException: invalid address");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("1/32");
fail("Expected IllegalArgumentException: deprecated IPv4 format");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("1.2.3.256/32");
fail("Expected IllegalArgumentException: invalid IPv4 address");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("foo/32");
fail("Expected IllegalArgumentException: non-address");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
try {
p = new IpPrefix("f00:::/32");
fail("Expected IllegalArgumentException: invalid IPv6 address");
- } catch(IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) { }
}
@Test
@@ -132,17 +132,17 @@ public class IpPrefixTest {
try {
p = new IpPrefix(IPV4_BYTES, 33);
fail("Expected IllegalArgumentException: invalid prefix length");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
p = new IpPrefix(IPV4_BYTES, 128);
fail("Expected IllegalArgumentException: invalid prefix length");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
p = new IpPrefix(IPV4_BYTES, -1);
fail("Expected IllegalArgumentException: negative prefix length");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
p = new IpPrefix(IPV6_BYTES, 128);
assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
@@ -162,12 +162,12 @@ public class IpPrefixTest {
try {
p = new IpPrefix(IPV6_BYTES, -1);
fail("Expected IllegalArgumentException: negative prefix length");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
try {
p = new IpPrefix(IPV6_BYTES, 129);
fail("Expected IllegalArgumentException: negative prefix length");
- } catch(RuntimeException expected) {}
+ } catch (RuntimeException expected) { }
}
@@ -226,28 +226,28 @@ public class IpPrefixTest {
@Test
public void testContainsInetAddress() {
IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
- assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
- assertTrue(p.contains(Address("2001:db8:f00::ace:d00d")));
- assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
- assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
- assertFalse(p.contains(Address("2001:4868:4860::8888")));
- assertFalse(p.contains(Address("8.8.8.8")));
+ assertTrue(p.contains(address("2001:db8:f00::ace:d00c")));
+ assertTrue(p.contains(address("2001:db8:f00::ace:d00d")));
+ assertFalse(p.contains(address("2001:db8:f00::ace:d00e")));
+ assertFalse(p.contains(address("2001:db8:f00::bad:d00d")));
+ assertFalse(p.contains(address("2001:4868:4860::8888")));
+ assertFalse(p.contains(address("8.8.8.8")));
p = new IpPrefix("192.0.2.0/23");
- assertTrue(p.contains(Address("192.0.2.43")));
- assertTrue(p.contains(Address("192.0.3.21")));
- assertFalse(p.contains(Address("192.0.0.21")));
- assertFalse(p.contains(Address("8.8.8.8")));
- assertFalse(p.contains(Address("2001:4868:4860::8888")));
+ assertTrue(p.contains(address("192.0.2.43")));
+ assertTrue(p.contains(address("192.0.3.21")));
+ assertFalse(p.contains(address("192.0.0.21")));
+ assertFalse(p.contains(address("8.8.8.8")));
+ assertFalse(p.contains(address("2001:4868:4860::8888")));
IpPrefix ipv6Default = new IpPrefix("::/0");
- assertTrue(ipv6Default.contains(Address("2001:db8::f00")));
- assertFalse(ipv6Default.contains(Address("192.0.2.1")));
+ assertTrue(ipv6Default.contains(address("2001:db8::f00")));
+ assertFalse(ipv6Default.contains(address("192.0.2.1")));
IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0");
- assertTrue(ipv4Default.contains(Address("255.255.255.255")));
- assertTrue(ipv4Default.contains(Address("192.0.2.1")));
- assertFalse(ipv4Default.contains(Address("2001:db8::f00")));
+ assertTrue(ipv4Default.contains(address("255.255.255.255")));
+ assertTrue(ipv4Default.contains(address("192.0.2.1")));
+ assertFalse(ipv4Default.contains(address("2001:db8::f00")));
}
@Test
@@ -315,10 +315,10 @@ public class IpPrefixTest {
p = new IpPrefix(b, random.nextInt(129));
}
if (p.equals(oldP)) {
- assertEquals(p.hashCode(), oldP.hashCode());
+ assertEquals(p.hashCode(), oldP.hashCode());
}
if (p.hashCode() != oldP.hashCode()) {
- assertNotEquals(p, oldP);
+ assertNotEquals(p, oldP);
}
}
}
@@ -332,9 +332,9 @@ public class IpPrefixTest {
new IpPrefix("0.0.0.0/0"),
};
for (int i = 0; i < prefixes.length; i++) {
- for (int j = i + 1; j < prefixes.length; j++) {
- assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
- }
+ for (int j = i + 1; j < prefixes.length; j++) {
+ assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
+ }
}
}
@@ -371,8 +371,8 @@ public class IpPrefixTest {
}
public void assertParcelingIsLossless(IpPrefix p) {
- IpPrefix p2 = passThroughParcel(p);
- assertEquals(p, p2);
+ IpPrefix p2 = passThroughParcel(p);
+ assertEquals(p, p2);
}
@Test
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index b6038aba089c..2adbb06babf1 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -45,6 +45,7 @@ import androidx.test.runner.AndroidJUnit4;
import libcore.util.HexEncoding;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -189,6 +190,7 @@ public class InetDiagSocketTest {
udp.close();
}
+ @Ignore
@Test
public void testGetConnectionOwnerUid() throws Exception {
checkGetConnectionOwnerUid("::", null);
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index b5c3e9287467..4a35015044ff 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -156,10 +156,21 @@ public class IpSecServiceTest {
@Test
public void testOpenAndCloseUdpEncapsulationSocket() throws Exception {
- int localport = findUnusedPort();
+ int localport = -1;
+ IpSecUdpEncapResponse udpEncapResp = null;
+
+ for (int i = 0; i < IpSecService.MAX_PORT_BIND_ATTEMPTS; i++) {
+ localport = findUnusedPort();
+
+ udpEncapResp = mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertNotNull(udpEncapResp);
+ if (udpEncapResp.status == IpSecManager.Status.OK) {
+ break;
+ }
+
+ // Else retry to reduce possibility for port-bind failures.
+ }
- IpSecUdpEncapResponse udpEncapResp =
- mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
assertNotNull(udpEncapResp);
assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
assertEquals(localport, udpEncapResp.port);
@@ -204,12 +215,11 @@ public class IpSecServiceTest {
@Test
public void testOpenUdpEncapsulationSocketAfterClose() throws Exception {
- int localport = findUnusedPort();
IpSecUdpEncapResponse udpEncapResp =
- mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ mIpSecService.openUdpEncapsulationSocket(0, new Binder());
assertNotNull(udpEncapResp);
assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
- assertEquals(localport, udpEncapResp.port);
+ int localport = udpEncapResp.port;
mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
udpEncapResp.fileDescriptor.close();
@@ -226,12 +236,11 @@ public class IpSecServiceTest {
*/
@Test
public void testUdpEncapPortNotReleased() throws Exception {
- int localport = findUnusedPort();
IpSecUdpEncapResponse udpEncapResp =
- mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ mIpSecService.openUdpEncapsulationSocket(0, new Binder());
assertNotNull(udpEncapResp);
assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
- assertEquals(localport, udpEncapResp.port);
+ int localport = udpEncapResp.port;
udpEncapResp.fileDescriptor.close();
@@ -273,14 +282,11 @@ public class IpSecServiceTest {
@Test
public void testOpenUdpEncapsulationSocketTwice() throws Exception {
- int localport = findUnusedPort();
-
IpSecUdpEncapResponse udpEncapResp =
- mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ mIpSecService.openUdpEncapsulationSocket(0, new Binder());
assertNotNull(udpEncapResp);
assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
- assertEquals(localport, udpEncapResp.port);
- mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ int localport = udpEncapResp.port;
IpSecUdpEncapResponse testUdpEncapResp =
mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index a24e0d2f93d0..c0802e60103a 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -138,17 +138,29 @@ static bool MergeEntry(IAaptContext* context, const Source& src,
if (src_entry->overlayable_item) {
if (dst_entry->overlayable_item) {
- // Do not allow a resource with an overlayable declaration to have that overlayable
- // declaration redefined
- context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable_item.value().source)
- << "duplicate overlayable declaration for resource '"
- << src_entry->name << "'");
- context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable_item.value().source)
- << "previous declaration here");
- return false;
- } else {
- dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
+ CHECK(src_entry->overlayable_item.value().overlayable != nullptr);
+ Overlayable* src_overlayable = src_entry->overlayable_item.value().overlayable.get();
+
+ CHECK(dst_entry->overlayable_item.value().overlayable != nullptr);
+ Overlayable* dst_overlayable = dst_entry->overlayable_item.value().overlayable.get();
+
+ if (src_overlayable->name != dst_overlayable->name
+ || src_overlayable->actor != dst_overlayable->actor
+ || src_entry->overlayable_item.value().policies !=
+ dst_entry->overlayable_item.value().policies) {
+
+ // Do not allow a resource with an overlayable declaration to have that overlayable
+ // declaration redefined.
+ context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable_item.value().source)
+ << "duplicate overlayable declaration for resource '"
+ << src_entry->name << "'");
+ context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable_item.value().source)
+ << "previous declaration here");
+ return false;
+ }
}
+
+ dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
}
return true;
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index ad3674e16774..9dd31e682937 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -521,6 +521,35 @@ TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
.Build();
auto overlayable_second = std::make_shared<Overlayable>("ThemeResources",
+ "overlay://customization");
+ OverlayableItem overlayable_item_second(overlayable_second);
+ overlayable_item_second.policies |= OverlayableItem::Policy::kProduct;
+ std::unique_ptr<ResourceTable> table_b =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.a", 0x7f)
+ .SetOverlayable("bool/foo", overlayable_item_second)
+ .Build();
+
+ ResourceTable final_table;
+ TableMergerOptions options;
+ options.auto_add_overlay = true;
+ TableMerger merger(context_.get(), &final_table, options);
+ ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+ ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
+TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
+ auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
+ "overlay://customization");
+ OverlayableItem overlayable_item_first(overlayable_first);
+ overlayable_item_first.policies |= OverlayableItem::Policy::kProduct;
+ std::unique_ptr<ResourceTable> table_a =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.a", 0x7f)
+ .SetOverlayable("bool/foo", overlayable_item_first)
+ .Build();
+
+ auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
"overlay://theme");
OverlayableItem overlayable_item_second(overlayable_second);
overlayable_item_second.policies |= OverlayableItem::Policy::kProduct;
@@ -538,7 +567,36 @@ TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
}
-TEST_F(TableMergerTest, SameResourceSameNameFail) {
+TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
+ auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
+ "overlay://customization");
+ OverlayableItem overlayable_item_first(overlayable_first);
+ overlayable_item_first.policies |= OverlayableItem::Policy::kProduct;
+ std::unique_ptr<ResourceTable> table_a =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.a", 0x7f)
+ .SetOverlayable("bool/foo", overlayable_item_first)
+ .Build();
+
+ auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
+ "overlay://customization");
+ OverlayableItem overlayable_item_second(overlayable_second);
+ overlayable_item_second.policies |= OverlayableItem::Policy::kSignature;
+ std::unique_ptr<ResourceTable> table_b =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.a", 0x7f)
+ .SetOverlayable("bool/foo", overlayable_item_second)
+ .Build();
+
+ ResourceTable final_table;
+ TableMergerOptions options;
+ options.auto_add_overlay = true;
+ TableMerger merger(context_.get(), &final_table, options);
+ ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+ ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
+TEST_F(TableMergerTest, SameResourceSameOverlayable) {
auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization");
@@ -551,7 +609,7 @@ TEST_F(TableMergerTest, SameResourceSameNameFail) {
.Build();
OverlayableItem overlayable_item_second(overlayable);
- overlayable_item_second.policies |= OverlayableItem::Policy::kSystem;
+ overlayable_item_second.policies |= OverlayableItem::Policy::kProduct;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -563,7 +621,7 @@ TEST_F(TableMergerTest, SameResourceSameNameFail) {
options.auto_add_overlay = true;
TableMerger merger(context_.get(), &final_table, options);
ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
- ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+ ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
}
} // namespace aapt