summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageParser.java2
-rw-r--r--core/java/android/net/NetworkAgent.java24
-rw-r--r--core/java/android/provider/Settings.java12
-rw-r--r--core/java/android/view/TEST_MAPPING8
-rw-r--r--core/java/android/view/ThreadedRenderer.java24
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/jni/Android.bp6
-rw-r--r--core/res/res/values/config.xml17
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/coretests/res/values/overlayable_icons_test.xml1
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageParserTest.java8
-rw-r--r--libs/hwui/TEST_MAPPING8
-rw-r--r--media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl2
-rw-r--r--packages/InputDevices/res/values-hy/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java60
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt119
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java192
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java73
-rw-r--r--packages/overlays/Android.mk1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_aural.xml40
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/values/config.xml8
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_disable.xml37
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_enable.xml37
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml37
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_aural.xml27
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/values/config.xml8
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_disable.xml36
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_enable.xml36
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml27
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_aural.xml40
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/values/config.xml8
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_disable.xml37
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_enable.xml37
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml37
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java1
-rw-r--r--services/autofill/java/com/android/server/autofill/ViewState.java1
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java6
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java6
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java6
-rw-r--r--services/core/java/com/android/server/pm/ShareTargetInfo.java92
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java13
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java2
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java8
-rw-r--r--services/core/java/com/android/server/wm/DragState.java2
-rw-r--r--services/java/com/android/server/SystemServer.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java75
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java21
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyPermissions.java14
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java82
74 files changed, 1526 insertions, 189 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index cf858f585c85..a74c34ff4a88 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -8391,7 +8391,7 @@ public class PackageParser {
public static PackageInfo generatePackageInfoFromApex(ApexInfo apexInfo, int flags)
throws PackageParserException {
PackageParser pp = new PackageParser();
- File apexFile = new File(apexInfo.packagePath);
+ File apexFile = new File(apexInfo.modulePath);
final Package p = pp.parsePackage(apexFile, flags, false);
PackageUserState state = new PackageUserState();
PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 660cd848d1df..43ea5891d7f7 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -437,15 +437,23 @@ public abstract class NetworkAgent extends Handler {
}
/**
- * Called by the bearer to indicate this network was manually selected by the user.
+ * Called by the bearer to indicate whether the network was manually selected by the user.
* This should be called before the NetworkInfo is marked CONNECTED so that this
- * Network can be given special treatment at that time. If {@code acceptUnvalidated} is
- * {@code true}, then the system will switch to this network. If it is {@code false} and the
- * network cannot be validated, the system will ask the user whether to switch to this network.
- * If the user confirms and selects "don't ask again", then the system will call
- * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
- * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
- * {@link #saveAcceptUnvalidated} to respect the user's choice.
+ * Network can be given special treatment at that time.
+ *
+ * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true},
+ * then the system will switch to this network. If {@code explicitlySelected} is {@code true}
+ * and {@code acceptUnvalidated} is {@code false}, and the network cannot be validated, the
+ * system will ask the user whether to switch to this network. If the user confirms and selects
+ * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the
+ * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected}
+ * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also
+ * implement {@link #saveAcceptUnvalidated} to respect the user's choice.
+ *
+ * If {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is
+ * {@code true}, the system will interpret this as the user having accepted partial connectivity
+ * on this network. Thus, the system will switch to the network and consider it validated even
+ * if it only provides partial connectivity, but the network is not otherwise treated specially.
*/
public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e615988060d5..9e1bb941004a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8276,6 +8276,16 @@ public final class Settings {
BOOLEAN_VALIDATOR;
/**
+ * Whether or not media is shown automatically when bypassing as a heads up.
+ * @hide
+ */
+ public static final String SHOW_MEDIA_WHEN_BYPASSING =
+ "show_media_when_bypassing";
+
+ private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not face unlock requires attention. This is a cached value, the source of
* truth is obtained through the HAL.
* @hide
@@ -8974,6 +8984,7 @@ public final class Settings {
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
+ SHOW_MEDIA_WHEN_BYPASSING,
FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
@@ -9150,6 +9161,7 @@ public final class Settings {
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
+ VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
diff --git a/core/java/android/view/TEST_MAPPING b/core/java/android/view/TEST_MAPPING
index 87d428ab551e..4ea4310b25a4 100644
--- a/core/java/android/view/TEST_MAPPING
+++ b/core/java/android/view/TEST_MAPPING
@@ -1,10 +1,12 @@
{
"presubmit": [
{
- "name": "CtsUiRenderingTestCases"
- },
- {
"name": "CtsAccelerationTestCases"
}
+ ],
+ "imports": [
+ {
+ "path": "cts/tests/tests/uirendering"
+ }
]
} \ No newline at end of file
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 3d3d5dc7db32..f18aa81b95e5 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.HardwareRenderer;
@@ -35,6 +36,7 @@ import com.android.internal.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -300,7 +302,8 @@ public final class ThreadedRenderer extends HardwareRenderer {
private boolean mEnabled;
private boolean mRequested = true;
- private FrameDrawingCallback mNextRtFrameCallback;
+ @Nullable
+ private ArrayList<FrameDrawingCallback> mNextRtFrameCallbacks;
ThreadedRenderer(Context context, boolean translucent, String name) {
super();
@@ -441,8 +444,11 @@ public final class ThreadedRenderer extends HardwareRenderer {
*
* @param callback The callback to register.
*/
- void registerRtFrameCallback(FrameDrawingCallback callback) {
- mNextRtFrameCallback = callback;
+ void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
+ if (mNextRtFrameCallbacks == null) {
+ mNextRtFrameCallbacks = new ArrayList<>();
+ }
+ mNextRtFrameCallbacks.add(callback);
}
/**
@@ -583,10 +589,14 @@ public final class ThreadedRenderer extends HardwareRenderer {
// Consume and set the frame callback after we dispatch draw to the view above, but before
// onPostDraw below which may reset the callback for the next frame. This ensures that
// updates to the frame callback during scroll handling will also apply in this frame.
- final FrameDrawingCallback callback = mNextRtFrameCallback;
- mNextRtFrameCallback = null;
- if (callback != null) {
- setFrameCallback(callback);
+ if (mNextRtFrameCallbacks != null) {
+ final ArrayList<FrameDrawingCallback> frameCallbacks = mNextRtFrameCallbacks;
+ mNextRtFrameCallbacks = null;
+ setFrameCallback(frame -> {
+ for (int i = 0; i < frameCallbacks.size(); ++i) {
+ frameCallbacks.get(i).onFrameDraw(frame);
+ }
+ });
}
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cb51545a8a69..613ddcf577ed 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1132,7 +1132,7 @@ public final class ViewRootImpl implements ViewParent,
*
* @param callback The callback to register.
*/
- public void registerRtFrameCallback(FrameDrawingCallback callback) {
+ public void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frame -> {
try {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b21221f2efff..b50b8248ee8d 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -100,7 +100,6 @@ cc_library_shared {
],
shared_libs: [
- "libandroidicu",
"libbase",
"libcutils",
"libharfbuzz_ng",
@@ -267,6 +266,7 @@ cc_library_shared {
],
shared_libs: [
+ "libandroidicu",
"libbpf_android",
"libnetdbpf",
"libnetdutils",
@@ -344,6 +344,10 @@ cc_library_shared {
include_dirs: [
"external/vulkan-headers/include",
],
+ shared_libs: [
+ "libicui18n",
+ "libicuuc",
+ ],
static_libs: [
"libandroidfw",
"libcompiler_rt",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a62a1fb5bfef..f515b2dd45f0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3783,9 +3783,11 @@
<integer name="config_stableDeviceDisplayWidth">-1</integer>
<integer name="config_stableDeviceDisplayHeight">-1</integer>
- <!-- Decide whether to display 'No service' on status bar instead of 'Emergency calls only'
- when SIM is unready. -->
- <bool name="config_display_no_service_when_sim_unready">false</bool>
+ <!-- List of countries in which we display 'No service' on status bar
+ instead of 'Emergency calls only' when SIM is unready. -->
+ <string-array translatable="false" name="config_display_no_service_when_sim_unready">
+ <item>"DE"</item>
+ </string-array>
<!-- Class names of device specific services inheriting com.android.server.SystemService. The
classes are instantiated in the order of the array. -->
@@ -4114,6 +4116,15 @@
M9,10l-2,0l0,-2l-2,0l0,2l-2,0l0,2l2,0l0,2l2,0l0,-2l2,0z
</string>
+ <!-- X path for SignalDrawable as defined on a 24x24 canvas. -->
+ <string name="config_signalXPath" translatable="false">
+ M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09-2.08L20.59,22L22,20.59l-2.08-2.09 L22,16.41z
+ </string>
+ <!-- config_signalCutout{Height,Width}Fraction define fraction of the 24x24 canvas that
+ should be cut out to display config_signalXPath.-->
+ <item name="config_signalCutoutWidthFraction" format="float" type="dimen">11</item>
+ <item name="config_signalCutoutHeightFraction" format="float" type="dimen">11</item>
+
<!-- A dual tone battery meter draws the perimeter path twice - once to define the shape
and a second time clipped to the fill level to indicate charge -->
<bool name="config_batterymeterDualTone">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5ca77f9207f9..6c908aac1ee8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3269,6 +3269,9 @@
<java-symbol type="string" name="config_batterymeterBoltPath" />
<java-symbol type="string" name="config_batterymeterPowersavePath" />
<java-symbol type="bool" name="config_batterymeterDualTone" />
+ <java-symbol type="string" name="config_signalXPath" />
+ <java-symbol type="dimen" name="config_signalCutoutWidthFraction" />
+ <java-symbol type="dimen" name="config_signalCutoutHeightFraction" />
<java-symbol type="bool" name="config_debugEnableAutomaticSystemServerHeapDumps" />
<java-symbol type="integer" name="config_debugSystemServerPssThresholdBytes" />
@@ -3554,7 +3557,7 @@
<java-symbol type="integer" name="config_stableDeviceDisplayWidth" />
<java-symbol type="integer" name="config_stableDeviceDisplayHeight" />
- <java-symbol type="bool" name="config_display_no_service_when_sim_unready" />
+ <java-symbol type="array" name="config_display_no_service_when_sim_unready" />
<java-symbol type="layout" name="slice_grid" />
<java-symbol type="layout" name="slice_message_local" />
diff --git a/core/tests/coretests/res/values/overlayable_icons_test.xml b/core/tests/coretests/res/values/overlayable_icons_test.xml
index ce209ce90905..6503f3ee6d57 100644
--- a/core/tests/coretests/res/values/overlayable_icons_test.xml
+++ b/core/tests/coretests/res/values/overlayable_icons_test.xml
@@ -70,6 +70,7 @@
<item>@*android:drawable/ic_wifi_signal_3</item>
<item>@*android:drawable/ic_wifi_signal_4</item>
<item>@*android:drawable/perm_group_activity_recognition</item>
+ <item>@*android:drawable/perm_group_aural</item>
<item>@*android:drawable/perm_group_calendar</item>
<item>@*android:drawable/perm_group_call_log</item>
<item>@*android:drawable/perm_group_camera</item>
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 71d9a46eaa24..58c43ac2cf91 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -498,14 +498,14 @@ public class PackageParserTest {
@Test
public void testApexPackageInfoGeneration() throws Exception {
- String apexPackageName = "com.android.tzdata.apex";
- File apexFile = copyRawResourceToFile(apexPackageName,
+ String apexModuleName = "com.android.tzdata.apex";
+ File apexFile = copyRawResourceToFile(apexModuleName,
R.raw.com_android_tzdata);
ApexInfo apexInfo = new ApexInfo();
apexInfo.isActive = true;
apexInfo.isFactory = false;
- apexInfo.packageName = apexPackageName;
- apexInfo.packagePath = apexFile.getPath();
+ apexInfo.moduleName = apexModuleName;
+ apexInfo.modulePath = apexFile.getPath();
apexInfo.versionCode = 191000070;
int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES;
PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexInfo, flags);
diff --git a/libs/hwui/TEST_MAPPING b/libs/hwui/TEST_MAPPING
index d9f2acbb49d2..b1719a979ce5 100644
--- a/libs/hwui/TEST_MAPPING
+++ b/libs/hwui/TEST_MAPPING
@@ -1,13 +1,15 @@
{
"presubmit": [
{
- "name": "CtsUiRenderingTestCases"
- },
- {
"name": "CtsGraphicsTestCases"
},
{
"name": "CtsAccelerationTestCases"
}
+ ],
+ "imports": [
+ {
+ "path": "cts/tests/tests/uirendering"
+ }
]
} \ No newline at end of file
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 8238b8c4898d..7e3f2f8868fb 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -19,7 +19,9 @@ oneway interface IMediaBrowserServiceCallbacks {
* the playback of the media app.
* @param extra Extras returned by the media service.
*/
+ @UnsupportedAppUsage
void onConnect(String root, in MediaSession.Token session, in Bundle extras);
+ @UnsupportedAppUsage
void onConnectFailed();
void onLoadChildren(String mediaId, in ParceledListSlice list);
void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list,
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index c7523e391807..64ddf7ac1b20 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -40,7 +40,7 @@
<string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ÔµÕ¢Ö€Õ¡ÕµÕ¥Ö€Õ¥Õ¶"</string>
<string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Ô¼Õ«Õ¿Õ¾Õ¥Ö€Õ¥Õ¶"</string>
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ô»Õ½ÕºÕ¡Õ¶Õ¥Ö€Õ¥Õ¶ (Ô¼Õ¡Õ¿Õ«Õ¶Õ¡Õ¯Õ¡Õ¶)"</string>
- <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Õ¬Õ¡Õ¿Õ«Õ·Õ¥Ö€Õ¥Õ¶"</string>
+ <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Õ¬Õ¡Õ¿Õ¾Õ«Õ¥Ö€Õ¥Õ¶"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"ÕºÕ¡Ö€Õ½Õ¯Õ¥Ö€Õ¥Õ¶"</string>
<string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Õ¡Õ¤Ö€Õ¢Õ¥Õ»Õ¡Õ¶Õ¥Ö€Õ¥Õ¶"</string>
<string name="keyboard_layout_polish" msgid="1121588624094925325">"Õ¬Õ¥Õ°Õ¥Ö€Õ¥Õ¶"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index c7380c580e2f..5ac788e1b374 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
@@ -33,6 +34,7 @@ import android.graphics.drawable.DrawableWrapper;
import android.os.Handler;
import android.telephony.SignalStrength;
import android.util.LayoutDirection;
+import android.util.PathParser;
import com.android.settingslib.R;
import com.android.settingslib.Utils;
@@ -48,7 +50,6 @@ public class SignalDrawable extends DrawableWrapper {
private static final float VIEWPORT = 24f;
private static final float PAD = 2f / VIEWPORT;
- private static final float CUT_OUT = 7.9f / VIEWPORT;
private static final float DOT_SIZE = 3f / VIEWPORT;
private static final float DOT_PADDING = 1.5f / VIEWPORT;
@@ -65,21 +66,6 @@ public class SignalDrawable extends DrawableWrapper {
private static final long DOT_DELAY = 1000;
- private static float[][] X_PATH = new float[][]{
- {21.9f / VIEWPORT, 17.0f / VIEWPORT},
- {-1.1f / VIEWPORT, -1.1f / VIEWPORT},
- {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
- {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
- {-1.1f / VIEWPORT, 1.1f / VIEWPORT},
- {1.9f / VIEWPORT, 1.9f / VIEWPORT},
- {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
- {1.1f / VIEWPORT, 1.1f / VIEWPORT},
- {1.9f / VIEWPORT, -1.9f / VIEWPORT},
- {1.9f / VIEWPORT, 1.9f / VIEWPORT},
- {1.1f / VIEWPORT, -1.1f / VIEWPORT},
- {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
- };
-
private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mTransparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int mDarkModeFillColor;
@@ -87,7 +73,11 @@ public class SignalDrawable extends DrawableWrapper {
private final Path mCutoutPath = new Path();
private final Path mForegroundPath = new Path();
private final Path mXPath = new Path();
+ private final Matrix mXScaleMatrix = new Matrix();
+ private final Path mScaledXPath = new Path();
private final Handler mHandler;
+ private final float mCutoutWidthFraction;
+ private final float mCutoutHeightFraction;
private float mDarkIntensity = -1;
private final int mIntrinsicSize;
private boolean mAnimating;
@@ -95,6 +85,14 @@ public class SignalDrawable extends DrawableWrapper {
public SignalDrawable(Context context) {
super(context.getDrawable(com.android.internal.R.drawable.ic_signal_cellular));
+ final String xPathString = context.getString(
+ com.android.internal.R.string.config_signalXPath);
+ mXPath.set(PathParser.createPathFromPathData(xPathString));
+ updateScaledXPath();
+ mCutoutWidthFraction = context.getResources().getFloat(
+ com.android.internal.R.dimen.config_signalCutoutWidthFraction);
+ mCutoutHeightFraction = context.getResources().getFloat(
+ com.android.internal.R.dimen.config_signalCutoutHeightFraction);
mDarkModeFillColor = Utils.getColorStateListDefaultColor(context,
R.color.dark_mode_icon_color_single_tone);
mLightModeFillColor = Utils.getColorStateListDefaultColor(context,
@@ -106,6 +104,15 @@ public class SignalDrawable extends DrawableWrapper {
setDarkIntensity(0);
}
+ private void updateScaledXPath() {
+ if (getBounds().isEmpty()) {
+ mXScaleMatrix.setScale(1f, 1f);
+ } else {
+ mXScaleMatrix.setScale(getBounds().width() / VIEWPORT, getBounds().height() / VIEWPORT);
+ }
+ mXPath.transform(mXScaleMatrix, mScaledXPath);
+ }
+
@Override
public int getIntrinsicWidth() {
return mIntrinsicSize;
@@ -170,6 +177,7 @@ public class SignalDrawable extends DrawableWrapper {
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
+ updateScaledXPath();
invalidateSelf();
}
@@ -205,19 +213,15 @@ public class SignalDrawable extends DrawableWrapper {
canvas.drawPath(mCutoutPath, mTransparentPaint);
canvas.drawPath(mForegroundPath, mForegroundPaint);
} else if (isInState(STATE_CUT)) {
- float cut = (CUT_OUT * width);
- mCutoutPath.moveTo(width - padding, height - padding);
- mCutoutPath.rLineTo(-cut, 0);
- mCutoutPath.rLineTo(0, -cut);
- mCutoutPath.rLineTo(cut, 0);
- mCutoutPath.rLineTo(0, cut);
+ float cutX = (mCutoutWidthFraction * width / VIEWPORT);
+ float cutY = (mCutoutHeightFraction * height / VIEWPORT);
+ mCutoutPath.moveTo(width, height);
+ mCutoutPath.rLineTo(-cutX, 0);
+ mCutoutPath.rLineTo(0, -cutY);
+ mCutoutPath.rLineTo(cutX, 0);
+ mCutoutPath.rLineTo(0, cutY);
canvas.drawPath(mCutoutPath, mTransparentPaint);
- mXPath.reset();
- mXPath.moveTo(X_PATH[0][0] * width, X_PATH[0][1] * height);
- for (int i = 1; i < X_PATH.length; i++) {
- mXPath.rLineTo(X_PATH[i][0] * width, X_PATH[i][1] * height);
- }
- canvas.drawPath(mXPath, mForegroundPaint);
+ canvas.drawPath(mScaledXPath, mForegroundPaint);
}
if (isRtl) {
canvas.restore();
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 38675122c501..a549870ec780 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -141,6 +141,9 @@
<!-- The number of milliseconds before the heads up notification auto-dismisses. -->
<integer name="heads_up_notification_decay">5000</integer>
+ <!-- The number of milliseconds before the heads up notification sent automatically by the system auto-dismisses. -->
+ <integer name="auto_heads_up_notification_decay">3000</integer>
+
<!-- The number of milliseconds after a heads up notification is pushed back
before the app can interrupt again. -->
<integer name="heads_up_default_snooze_length_ms">60000</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 06352310b3dd..5136682bb292 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,6 +52,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -103,8 +104,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
private final Date mCurrentTime = new Date();
private final Handler mHandler;
private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
- private final HashSet<Integer> mMediaInvisibleStates;
private final Object mMediaToken = new Object();
+ private DozeParameters mDozeParameters;
@VisibleForTesting
protected SettableWakeLock mMediaWakeLock;
@VisibleForTesting
@@ -184,11 +185,6 @@ public class KeyguardSliceProvider extends SliceProvider implements
mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
mDndUri = Uri.parse(KEYGUARD_DND_URI);
mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
-
- mMediaInvisibleStates = new HashSet<>();
- mMediaInvisibleStates.add(PlaybackState.STATE_NONE);
- mMediaInvisibleStates.add(PlaybackState.STATE_STOPPED);
- mMediaInvisibleStates.add(PlaybackState.STATE_PAUSED);
}
/**
@@ -201,12 +197,14 @@ public class KeyguardSliceProvider extends SliceProvider implements
public void initDependencies(
NotificationMediaManager mediaManager,
StatusBarStateController statusBarStateController,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ DozeParameters dozeParameters) {
mMediaManager = mediaManager;
mMediaManager.addCallback(this);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mKeyguardBypassController = keyguardBypassController;
+ mDozeParameters = dozeParameters;
}
@AnyThread
@@ -231,9 +229,9 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
protected boolean needsMediaLocked() {
- boolean isBypass = mKeyguardBypassController != null
- && mKeyguardBypassController.getBypassEnabled();
- return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || isBypass);
+ boolean keepWhenAwake = mKeyguardBypassController != null
+ && mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn();
+ return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake);
}
protected void addMediaLocked(ListBuilder listBuilder) {
@@ -458,7 +456,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
synchronized (this) {
- boolean nextVisible = !mMediaInvisibleStates.contains(state);
+ boolean nextVisible = NotificationMediaManager.isPlayingState(state);
mHandler.removeCallbacksAndMessages(mMediaToken);
if (mMediaIsVisible && !nextVisible) {
// We need to delay this event for a few millis when stopping to avoid jank in the
@@ -477,7 +475,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) {
- boolean nextVisible = !mMediaInvisibleStates.contains(state);
+ boolean nextVisible = NotificationMediaManager.isPlayingState(state);
CharSequence title = null;
if (metadata != null) {
title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b9fb1a1c91c8..21f58128322d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -239,9 +239,8 @@ public class PipMenuActivity extends Activity {
});
mDismissButton = findViewById(R.id.dismiss);
mDismissButton.setAlpha(0);
- mDismissButton.setOnClickListener((v) -> {
- dismissPip();
- });
+ mDismissButton.setOnClickListener(v -> dismissPip());
+ findViewById(R.id.expand_button).setOnClickListener(v -> expandPip());
mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index a59d590c9719..f001561754aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -69,6 +69,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -91,6 +92,14 @@ public class NotificationMediaManager implements Dumpable {
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
private final KeyguardBypassController mKeyguardBypassController;
+ private static final HashSet<Integer> PAUSED_MEDIA_STATES = new HashSet<>();
+ static {
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_NONE);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_STOPPED);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_PAUSED);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_ERROR);
+ }
+
// Late binding
private NotificationEntryManager mEntryManager;
@@ -207,6 +216,10 @@ public class NotificationMediaManager implements Dumpable {
mPropertiesChangedListener);
}
+ public static boolean isPlayingState(int state) {
+ return !PAUSED_MEDIA_STATES.contains(state);
+ }
+
public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0a8b7f8aa0da..4ccd0cd3353b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
import android.content.res.Configuration;
@@ -48,8 +49,12 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import javax.inject.Inject;
+import javax.inject.Named;
+
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
@@ -63,6 +68,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
+ private final KeyguardBypassController mBypassController;
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
@@ -93,8 +99,12 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mCutoutHeight;
private int mGapHeight;
- public NotificationShelf(Context context, AttributeSet attrs) {
+ @Inject
+ public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
+ AttributeSet attrs,
+ KeyguardBypassController keyguardBypassController) {
super(context, attrs);
+ mBypassController = keyguardBypassController;
}
@Override
@@ -309,7 +319,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
colorTwoBefore = previousColor;
transitionAmount = inShelfAmount;
}
- if (isLastChild) {
+ // We don't want to modify the color if the notification is hun'd
+ boolean canModifyColor = mAmbientState.isShadeExpanded()
+ && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
+ if (isLastChild && canModifyColor) {
if (colorOfViewBeforeLast == NO_COLOR) {
colorOfViewBeforeLast = ownColorUntinted;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 787cc971e6a1..aeb85748fd1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -16,8 +16,11 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.content.Context;
import android.content.res.Resources;
+import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
@@ -44,6 +47,7 @@ import java.util.List;
import java.util.Stack;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Lazy;
@@ -59,6 +63,8 @@ import dagger.Lazy;
public class NotificationViewHierarchyManager implements DynamicPrivacyController.Listener {
private static final String TAG = "NotificationViewHierarchyManager";
+ private final Handler mHandler;
+
//TODO: change this top <Entry, List<Entry>>?
private final HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>>
mTmpChildOrderMap = new HashMap<>();
@@ -88,9 +94,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
// Used to help track down re-entrant calls to our update methods, which will cause bugs.
private boolean mPerformingUpdate;
+ // Hack to get around re-entrant call in onDynamicPrivacyChanged() until we can track down
+ // the problem.
+ private boolean mIsHandleDynamicPrivacyChangeScheduled;
@Inject
public NotificationViewHierarchyManager(Context context,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
@@ -100,6 +110,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
BubbleData bubbleData,
KeyguardBypassController bypassController,
DynamicPrivacyController privacyController) {
+ mHandler = mainHandler;
mLockscreenUserManager = notificationLockscreenUserManager;
mBypassController = bypassController;
mGroupManager = groupManager;
@@ -438,6 +449,20 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
@Override
public void onDynamicPrivacyChanged() {
+ if (mPerformingUpdate) {
+ Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
+ }
+ // This listener can be called from updateNotificationViews() via a convoluted listener
+ // chain, so we post here to prevent a re-entrant call. See b/136186188
+ // TODO: Refactor away the need for this
+ if (!mIsHandleDynamicPrivacyChangeScheduled) {
+ mIsHandleDynamicPrivacyChangeScheduled = true;
+ mHandler.post(this::onHandleDynamicPrivacyChanged);
+ }
+ }
+
+ private void onHandleDynamicPrivacyChanged() {
+ mIsHandleDynamicPrivacyChangeScheduled = false;
updateNotificationViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
new file mode 100644
index 000000000000..ea474ced7632
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.statusbar.notification
+
+import android.content.Context
+import android.media.MediaMetadata
+import android.provider.Settings
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.tuner.TunerService
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class that automatically creates heads up for important notification when bypassing the
+ * lockscreen
+ */
+@Singleton
+class BypassHeadsUpNotifier @Inject constructor(
+ private val context: Context,
+ private val bypassController: KeyguardBypassController,
+ private val statusBarStateController: StatusBarStateController,
+ private val headsUpManager: HeadsUpManagerPhone,
+ private val mediaManager: NotificationMediaManager,
+ tunerService: TunerService) : StatusBarStateController.StateListener,
+ NotificationMediaManager.MediaListener {
+
+ private lateinit var entryManager: NotificationEntryManager
+ private var currentMediaEntry: NotificationEntry? = null
+ private var enabled = true
+
+ var fullyAwake = false
+ set(value) {
+ field = value
+ if (value) {
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+ }
+
+ init {
+ statusBarStateController.addCallback(this)
+ tunerService.addTunable(
+ TunerService.Tunable { _, _ ->
+ enabled = Settings.Secure.getIntForUser(
+ context.contentResolver,
+ Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING,
+ 1 /* default */,
+ KeyguardUpdateMonitor.getCurrentUser()) != 0
+ }, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING)
+ }
+
+ fun setUp(entryManager: NotificationEntryManager) {
+ this.entryManager = entryManager
+ mediaManager.addCallback(this)
+ }
+
+ override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
+ val previous = currentMediaEntry
+ var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
+ if (!NotificationMediaManager.isPlayingState(state)) {
+ newEntry = null
+ }
+ if (newEntry?.isSensitive == true) {
+ newEntry = null
+ }
+ currentMediaEntry = newEntry
+ updateAutoHeadsUp(previous)
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+
+ private fun updateAutoHeadsUp(entry: NotificationEntry?) {
+ entry?.let {
+ val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp()
+ it.isAutoHeadsUp = autoHeadsUp
+ if (autoHeadsUp) {
+ headsUpManager.showNotification(it)
+ }
+ }
+ }
+
+ override fun onStatePostChange() {
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+
+ private fun canAutoHeadsUp() : Boolean {
+ if (!enabled) {
+ return false
+ }
+ if (!bypassController.bypassEnabled) {
+ return false
+ }
+ if (statusBarStateController.state != StatusBarState.KEYGUARD) {
+ return false
+ }
+ if (!fullyAwake) {
+ return false
+ }
+ return true
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 8a23f718ef9a..d71d40781f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -24,7 +24,6 @@ import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -119,12 +118,11 @@ public class NotificationAlertingManager {
shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
if (wasAlerting) {
- if (!shouldAlert) {
- // We don't want this to be interrupting anymore, let's remove it
- mHeadsUpManager.removeNotification(entry.key,
- false /* ignoreEarliestRemovalTime */);
- } else {
+ if (shouldAlert) {
mHeadsUpManager.updateNotification(entry.key, alertAgain);
+ } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+ // We don't want this to be interrupting anymore, let's remove it
+ mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
}
} else if (shouldAlert && alertAgain) {
// This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 1aa6bc9ae5f9..dfc64508cadf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -24,6 +24,8 @@ import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import androidx.annotation.NonNull;
+
/**
* Listener interface for changes sent by NotificationEntryManager.
*/
@@ -45,7 +47,7 @@ public interface NotificationEntryListener {
/**
* Called when a new entry is created.
*/
- default void onNotificationAdded(NotificationEntry entry) {
+ default void onNotificationAdded(@NonNull NotificationEntry entry) {
}
/**
@@ -61,7 +63,7 @@ public interface NotificationEntryListener {
/**
* Called when a notification was updated, after any filtering of notifications have occurred.
*/
- default void onPostEntryUpdated(NotificationEntry entry) {
+ default void onPostEntryUpdated(@NonNull NotificationEntry entry) {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 9db715d129a5..b19d2ca29c96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -175,6 +175,7 @@ public final class NotificationEntry {
private boolean mHighPriority;
private boolean mSensitive = true;
private Runnable mOnSensitiveChangedListener;
+ private boolean mAutoHeadsUp;
public NotificationEntry(StatusBarNotification n) {
this(n, null);
@@ -670,11 +671,25 @@ public final class NotificationEntry {
if (row != null) row.setHeadsUp(shouldHeadsUp);
}
-
public void setHeadsUpAnimatingAway(boolean animatingAway) {
if (row != null) row.setHeadsUpAnimatingAway(animatingAway);
}
+ /**
+ * Set that this notification was automatically heads upped. This happens for example when
+ * the user bypasses the lockscreen and media is playing.
+ */
+ public void setAutoHeadsUp(boolean autoHeadsUp) {
+ mAutoHeadsUp = autoHeadsUp;
+ }
+
+ /**
+ * @return if this notification was automatically heads upped. This happens for example when
+ * * the user bypasses the lockscreen and media is playing.
+ */
+ public boolean isAutoHeadsUp() {
+ return mAutoHeadsUp;
+ }
public boolean mustStayOnScreen() {
return row != null && row.mustStayOnScreen();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index ae534d278116..a8327f63dcf7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2698,6 +2698,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
l.setAlpha(1.0f);
l.setLayerType(LAYER_TYPE_NONE, null);
}
+ } else {
+ setHeadsUpAnimatingAway(false);
}
}
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 e2cb8d4517ff..58e639924f4f 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
@@ -837,7 +837,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
break;
}
}
- if (!mAmbientState.isDozing() || anySectionHasVisibleChild) {
+ boolean shouldDrawBackground;
+ if (mKeyguardBypassController.getBypassEnabled() && onKeyguard()) {
+ shouldDrawBackground = isPulseExpanding();
+ } else {
+ shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild;
+ }
+ if (shouldDrawBackground) {
drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
}
@@ -3396,10 +3402,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
ExpandableNotificationRow row = eventPair.first;
boolean isHeadsUp = eventPair.second;
+ if (isHeadsUp != row.isHeadsUp()) {
+ // For cases where we have a heads up showing and appearing again we shouldn't
+ // do the animations at all.
+ continue;
+ }
int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
boolean onBottom = false;
boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
- if (!mIsExpanded && !isHeadsUp) {
+ boolean performDisappearAnimation = !mIsExpanded
+ // Only animate if we still have pinned heads up, otherwise we just have the
+ // regular collapse animation of the lock screen
+ || (mKeyguardBypassController.getBypassEnabled() && onKeyguard()
+ && mHeadsUpManager.hasPinnedHeadsUp());
+ if (performDisappearAnimation && !isHeadsUp) {
type = row.wasJustClicked()
? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
: AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
@@ -6246,6 +6262,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mAmbientState.onDragFinished(animView);
updateContinuousShadowDrawing();
updateContinuousBackgroundDrawing();
+ if (animView instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
+ if (row.isPinned() && !canChildBeDismissed(row)
+ && row.getStatusBarNotification().getNotification().fullScreenIntent
+ == null) {
+ mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
+ true /* removeImmediately */);
+ }
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 09c6968867b8..35ba801c75ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -546,12 +546,12 @@ public class StackScrollAlgorithm {
ExpandableViewState topState =
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
if (topState != null && !isTopEntry && (!mIsExpanded
- || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
+ || unmodifiedEndLocation > topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
childState.height = row.getIntrinsicHeight();
- childState.yTranslation = topState.yTranslation + topState.height
- - childState.height;
+ childState.yTranslation = Math.min(topState.yTranslation + topState.height
+ - childState.height, childState.yTranslation);
}
// heads up notification show and this row is the top entry of heads up
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 4f169eb50f88..0996ff27e9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -28,6 +28,7 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -451,7 +452,11 @@ public class StackStateAnimator {
if (row.isDismissed()) {
needsAnimation = false;
}
- StatusBarIconView icon = row.getEntry().icon;
+ NotificationEntry entry = row.getEntry();
+ StatusBarIconView icon = entry.icon;
+ if (entry.centeredIcon != null && entry.centeredIcon.getParent() != null) {
+ icon = entry.centeredIcon;
+ }
if (icon.getParent() != null) {
icon.getLocationOnScreen(mTmpLocation);
float iconPosition = mTmpLocation[0] - icon.getTranslationX()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index ade855e755e3..c44f953615e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -32,7 +32,6 @@ import android.view.ViewTreeObserver;
import androidx.collection.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
@@ -67,6 +66,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
final int mExtensionTime;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mBypassController;
+ private final int mAutoHeadsUpNotificationDecay;
private View mStatusBarWindowView;
private NotificationGroupManager mGroupManager;
private VisualStabilityManager mVisualStabilityManager;
@@ -81,6 +81,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
private boolean mTrackingHeadsUp;
private HashSet<String> mSwipedOutKeys = new HashSet<>();
private HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
+ private HashSet<String> mKeysToRemoveWhenLeavingKeyguard = new HashSet<>();
private ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
= new ArraySet<>();
private boolean mIsExpanded;
@@ -121,6 +122,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
mAutoDismissNotificationDecayDozing = resources.getInteger(
R.integer.heads_up_notification_decay_dozing);
mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
+ mAutoHeadsUpNotificationDecay = resources.getInteger(
+ R.integer.auto_heads_up_notification_decay);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mBypassController = bypassController;
@@ -231,7 +234,16 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
public void onStateChanged(int newState) {
+ boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
+ boolean isKeyguard = newState == StatusBarState.KEYGUARD;
mStatusBarState = newState;
+ if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
+ String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
+ for (String key : keys) {
+ removeAlertEntry(key);
+ }
+ mKeysToRemoveWhenLeavingKeyguard.clear();
+ }
}
@Override
@@ -245,6 +257,15 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
}
+ @Override
+ public boolean isEntryAutoHeadsUpped(String key) {
+ HeadsUpEntryPhone headsUpEntryPhone = getHeadsUpEntryPhone(key);
+ if (headsUpEntryPhone == null) {
+ return false;
+ }
+ return headsUpEntryPhone.isAutoHeadsUp();
+ }
+
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a sane state.
@@ -420,6 +441,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
protected void onAlertEntryRemoved(AlertEntry alertEntry) {
+ mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
super.onAlertEntryRemoved(alertEntry);
mEntryPool.release((HeadsUpEntryPhone) alertEntry);
}
@@ -479,6 +501,11 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
*/
private boolean extended;
+ /**
+ * Was this entry received while on keyguard
+ */
+ private boolean mIsAutoHeadsUp;
+
@Override
protected boolean isSticky() {
@@ -494,10 +521,12 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
mEntriesToRemoveWhenReorderingAllowed.add(entry);
mVisualStabilityManager.addReorderingAllowedCallback(
HeadsUpManagerPhone.this);
- } else if (!mTrackingHeadsUp) {
- removeAlertEntry(entry.key);
- } else {
+ } else if (mTrackingHeadsUp) {
mEntriesToRemoveAfterExpand.add(entry);
+ } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
+ mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+ } else {
+ removeAlertEntry(entry.key);
}
};
@@ -506,6 +535,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
public void updateEntry(boolean updatePostTime) {
+ mIsAutoHeadsUp = mEntry.isAutoHeadsUp();
super.updateEntry(updatePostTime);
if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
@@ -514,6 +544,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
}
+ mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
}
@Override
@@ -548,6 +579,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
super.reset();
mMenuShownPinned = false;
extended = false;
+ mIsAutoHeadsUp = false;
}
private void extendPulse() {
@@ -558,13 +590,35 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
@Override
+ public int compareTo(AlertEntry alertEntry) {
+ HeadsUpEntryPhone headsUpEntry = (HeadsUpEntryPhone) alertEntry;
+ boolean autoShown = isAutoHeadsUp();
+ boolean otherAutoShown = headsUpEntry.isAutoHeadsUp();
+ if (autoShown && !otherAutoShown) {
+ return 1;
+ } else if (!autoShown && otherAutoShown) {
+ return -1;
+ }
+ return super.compareTo(alertEntry);
+ }
+
+ @Override
protected long calculateFinishTime() {
return mPostTime + getDecayDuration() + (extended ? mExtensionTime : 0);
}
private int getDecayDuration() {
- return mStatusBarStateController.isDozing() ? mAutoDismissNotificationDecayDozing
- : getRecommendedHeadsUpTimeoutMs();
+ if (mStatusBarStateController.isDozing()) {
+ return mAutoDismissNotificationDecayDozing;
+ } else if (isAutoHeadsUp()) {
+ return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay);
+ } else {
+ return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
+ }
+ }
+
+ private boolean isAutoHeadsUp() {
+ return mIsAutoHeadsUp;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 1e7c44cdba2f..49afae7415ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import java.lang.annotation.Retention;
@@ -67,7 +68,8 @@ import javax.inject.Named;
public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
- NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener {
+ NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener,
+ OnHeadsUpChangedListener {
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
@@ -82,6 +84,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private final KeyguardMonitor mKeyguardMonitor;
private final KeyguardBypassController mBypassController;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+ private final HeadsUpManagerPhone mHeadsUpManager;
private int mLastState = 0;
private boolean mForceUpdate;
@@ -92,9 +95,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private boolean mPulsing;
private boolean mDozing;
private boolean mDocked;
+ private boolean mBlockUpdates;
private int mIconColor;
private float mDozeAmount;
- private boolean mBouncerShowing;
+ private boolean mBouncerShowingScrimmed;
private boolean mWakeAndUnlockRunning;
private boolean mKeyguardShowing;
private boolean mShowingLaunchAffordance;
@@ -104,8 +108,22 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
new KeyguardMonitor.Callback() {
@Override
public void onKeyguardShowingChanged() {
+ boolean force = false;
+ boolean wasShowing = mKeyguardShowing;
mKeyguardShowing = mKeyguardMonitor.isShowing();
- update();
+ if (!wasShowing && mKeyguardShowing && mBlockUpdates) {
+ mBlockUpdates = false;
+ force = true;
+ }
+ update(force);
+ }
+
+ @Override
+ public void onKeyguardFadingAwayChanged() {
+ if (!mKeyguardMonitor.isKeyguardFadingAway() && mBlockUpdates) {
+ mBlockUpdates = false;
+ update(true /* force */);
+ }
}
};
private final DockManager.DockEventListener mDockEventListener =
@@ -155,7 +173,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
KeyguardBypassController bypassController,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardMonitor keyguardMonitor,
- @Nullable DockManager dockManager) {
+ @Nullable DockManager dockManager,
+ HeadsUpManagerPhone headsUpManager) {
super(context, attrs);
mContext = context;
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
@@ -167,6 +186,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mWakeUpCoordinator = wakeUpCoordinator;
mKeyguardMonitor = keyguardMonitor;
mDockManager = dockManager;
+ mHeadsUpManager = headsUpManager;
}
@Override
@@ -256,7 +276,11 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mIsFaceUnlockState = state == STATE_SCANNING_FACE;
mLastState = state;
- if (lastState != state || mForceUpdate) {
+ boolean shouldUpdate = lastState != state || mForceUpdate;
+ if (mBlockUpdates && canBlockUpdates()) {
+ shouldUpdate = false;
+ }
+ if (shouldUpdate) {
mForceUpdate = false;
@LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState,
state, mPulsing, mDozing);
@@ -296,11 +320,13 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
|| mShowingLaunchAffordance;
- if (mBypassController.getBypassEnabled()
- && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
- && !mWakeUpCoordinator.getNotificationsFullyHidden()
- && !mBouncerShowing) {
- invisible = true;
+ if (mBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) {
+ if (mHeadsUpManager.isHeadsUpGoingAway()
+ || mHeadsUpManager.hasPinnedHeadsUp()
+ || (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+ && !mWakeUpCoordinator.getNotificationsFullyHidden())) {
+ invisible = true;
+ }
}
boolean wasInvisible = getVisibility() == INVISIBLE;
if (invisible != wasInvisible) {
@@ -323,6 +349,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
return true;
}
+ private boolean canBlockUpdates() {
+ return mKeyguardShowing || mKeyguardMonitor.isKeyguardFadingAway();
+ }
+
private void updateClickability() {
if (mAccessibilityController == null) {
return;
@@ -408,8 +438,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
}
- public void setBouncerShowing(boolean bouncerShowing) {
- mBouncerShowing = bouncerShowing;
+ public void setBouncerShowingScrimmed(boolean bouncerShowing) {
+ mBouncerShowingScrimmed = bouncerShowing;
if (mBypassController.getBypassEnabled()) {
update();
}
@@ -529,11 +559,17 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
/**
* We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
* icon on top of the black front scrim.
+ * @param wakeAndUnlock are we wake and unlocking
+ * @param isUnlock are we currently unlocking
*/
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
if (wakeAndUnlock) {
mWakeAndUnlockRunning = true;
}
+ if (isUnlock && mBypassController.getBypassEnabled() && canBlockUpdates()) {
+ // We don't want the icon to change while we are unlocking
+ mBlockUpdates = true;
+ }
update();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index cd9772237d59..d2159ca15b24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -248,7 +248,7 @@ public class NotificationIconAreaController implements DarkReceiver,
if (onlyShowCenteredIcon) {
return isCenteredNotificationIcon;
}
- if (hideCenteredIcon && isCenteredNotificationIcon) {
+ if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
return false;
}
if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9d1043850426..55f61fa8a6a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -80,6 +80,7 @@ import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -193,6 +194,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -373,6 +375,8 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardBypassController mKeyguardBypassController;
@Inject
protected HeadsUpManagerPhone mHeadsUpManager;
+ @Inject
+ BypassHeadsUpNotifier mBypassHeadsUpNotifier;
@Nullable
@Inject
protected KeyguardLiftController mKeyguardLiftController;
@@ -633,6 +637,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mGutsManager = Dependency.get(NotificationGutsManager.class);
mMediaManager = Dependency.get(NotificationMediaManager.class);
mEntryManager = Dependency.get(NotificationEntryManager.class);
+ mBypassHeadsUpNotifier.setUp(mEntryManager);
mNotificationInterruptionStateProvider =
Dependency.get(NotificationInterruptionStateProvider.class);
mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
@@ -649,7 +654,7 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
if (sliceProvider != null) {
sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
- mKeyguardBypassController);
+ mKeyguardBypassController, DozeParameters.getInstance(mContext));
} else {
Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
}
@@ -1154,8 +1159,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private void inflateShelf() {
mNotificationShelf =
- (NotificationShelf) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_notification_shelf, mStackScroller, false);
+ (NotificationShelf) mInjectionInflater.injectable(
+ LayoutInflater.from(mContext)).inflate(
+ R.layout.status_bar_notification_shelf, mStackScroller, false);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -3576,7 +3582,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mBouncerShowing = bouncerShowing;
mKeyguardBypassController.setBouncerShowing(bouncerShowing);
mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
- mStatusBarWindow.setBouncerShowing(bouncerShowing);
+ mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
updateHideIconsForBouncer(true /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3629,6 +3635,7 @@ public class StatusBar extends SystemUI implements DemoMode,
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
mWakeUpCoordinator.setFullyAwake(false);
+ mBypassHeadsUpNotifier.setFullyAwake(false);
mKeyguardBypassController.onStartedGoingToSleep();
}
@@ -3653,6 +3660,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onFinishedWakingUp() {
mWakeUpCoordinator.setFullyAwake(true);
+ mBypassHeadsUpNotifier.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);
@@ -3826,7 +3834,8 @@ public class StatusBar extends SystemUI implements DemoMode,
public void notifyBiometricAuthModeChanged() {
updateDozing();
updateScrimController();
- mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock());
+ mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
+ mBiometricUnlockController.isBiometricUnlock());
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6dc2c8cab055..462b65f37ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -814,7 +814,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
public boolean shouldSubtleWindowAnimationsForUnlock() {
return mStatusBar.mKeyguardBypassController.getBypassEnabled()
- && mStatusBar.mState == StatusBarState.KEYGUARD;
+ && mStatusBar.mState == StatusBarState.KEYGUARD && !mBouncer.isAnimatingAway();
}
public boolean isGoingToNotificationShade() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a82e14efca2f..94054188d769 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -272,10 +272,11 @@ public class StatusBarWindowView extends FrameLayout {
/**
* Called when the biometric authentication mode changes.
* @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+ * @param isUnlock If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
*/
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
if (mLockIcon != null) {
- mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+ mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
}
}
@@ -525,9 +526,9 @@ public class StatusBarWindowView extends FrameLayout {
mBypassController = bypassController;
}
- public void setBouncerShowing(boolean bouncerShowing) {
+ public void setBouncerShowingScrimmed(boolean bouncerShowing) {
if (mLockIcon != null) {
- mLockIcon.setBouncerShowing(bouncerShowing);
+ mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 40d5e4dcfd64..b84dc476dd6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -356,6 +356,10 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
public void onDensityOrFontScaleChanged() {
}
+ public boolean isEntryAutoHeadsUpped(String key) {
+ return false;
+ }
+
/**
* This represents a notification and how long it is in a heads up mode. It also manages its
* lifecycle automatically when created.
@@ -416,16 +420,17 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
@Override
protected long calculateFinishTime() {
- return mPostTime + getRecommendedHeadsUpTimeoutMs();
+ return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
}
/**
* Get user-preferred or default timeout duration. The larger one will be returned.
* @return milliseconds before auto-dismiss
+ * @param requestedTimeout
*/
- protected int getRecommendedHeadsUpTimeoutMs() {
+ protected int getRecommendedHeadsUpTimeoutMs(int requestedTimeout) {
return mAccessibilityMgr.getRecommendedTimeoutMillis(
- mAutoDismissNotificationDecay,
+ requestedTimeout,
AccessibilityManager.FLAG_CONTENT_CONTROLS
| AccessibilityManager.FLAG_CONTENT_ICONS
| AccessibilityManager.FLAG_CONTENT_TEXT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 01498e6bd54d..f61b556e22ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -50,5 +50,6 @@ public interface KeyguardMonitor extends CallbackController<Callback> {
interface Callback {
void onKeyguardShowingChanged();
+ default void onKeyguardFadingAwayChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index b53ff0e45cea..68d00708b0d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -141,14 +141,24 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
}
public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
- mKeyguardFadingAway = true;
+ setKeyguardFadingAway(true);
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
}
+ private void setKeyguardFadingAway(boolean keyguardFadingAway) {
+ if (mKeyguardFadingAway != keyguardFadingAway) {
+ mKeyguardFadingAway = keyguardFadingAway;
+ ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks);
+ for (int i = 0; i < callbacks.size(); i++) {
+ callbacks.get(i).onKeyguardFadingAwayChanged();
+ }
+ }
+ }
+
public void notifyKeyguardDoneFading() {
- mKeyguardFadingAway = false;
mKeyguardGoingAway = false;
+ setKeyguardFadingAway(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index d521e5534ad4..ede30046d6c3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -32,6 +32,7 @@ import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -138,6 +139,11 @@ public class InjectionInflationController {
QSCarrierGroup createQSCarrierGroup();
/**
+ * Creates the Shelf.
+ */
+ NotificationShelf creatNotificationShelf();
+
+ /**
* Creates the KeyguardClockSwitch.
*/
KeyguardClockSwitch createKeyguardClockSwitch();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java b/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
new file mode 100644
index 000000000000..ccc9afcd4296
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+
+import android.annotation.DrawableRes;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+import android.util.TypedValue;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.XmlUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class IconPackOverlayTest extends SysuiTestCase {
+
+ private static final String[] ICON_PACK_OVERLAY_PACKAGES = {
+ "com.android.theme.icon_pack.circular.systemui",
+ "com.android.theme.icon_pack.rounded.systemui",
+ "com.android.theme.icon_pack.filled.systemui",
+ };
+
+ private static final int[] VECTOR_ATTRIBUTES = {
+ android.R.attr.tint,
+ android.R.attr.height,
+ android.R.attr.width,
+ android.R.attr.alpha,
+ android.R.attr.autoMirrored,
+ };
+
+ private final TypedValue mTargetTypedValue = new TypedValue();
+ private final TypedValue mOverlayTypedValue = new TypedValue();
+
+ private Resources mResources;
+ private TypedArray mOverlayableIcons;
+
+ @Before
+ public void setup() {
+ mResources = mContext.getResources();
+ mOverlayableIcons = mResources.obtainTypedArray(R.array.overlayable_icons);
+ }
+
+ @After
+ public void teardown() {
+ mOverlayableIcons.recycle();
+ }
+
+ /**
+ * Ensure that all icons contained in overlayable_icons_test.xml exist in all 3 overlay icon
+ * packs for systemui. This test fails if you remove or rename an overlaid icon. If so,
+ * make the same change to the corresponding drawables in {@link #ICON_PACK_OVERLAY_PACKAGES}.
+ */
+ @Test
+ public void testIconPack_containAllOverlayedIcons() {
+ StringBuilder errors = new StringBuilder();
+
+ for (String overlayPackage : ICON_PACK_OVERLAY_PACKAGES) {
+ Resources overlayResources;
+ try {
+ overlayResources = mContext.getPackageManager()
+ .getResourcesForApplication(overlayPackage);
+ } catch (PackageManager.NameNotFoundException e) {
+ continue; // No need to test overlay resources if apk is not on the system.
+ }
+
+ for (int i = 0; i < mOverlayableIcons.length(); i++) {
+ int sysuiRid = mOverlayableIcons.getResourceId(i, 0);
+ String sysuiResourceName = mResources.getResourceName(sysuiRid);
+ String overlayResourceName = sysuiResourceName
+ .replace(mContext.getPackageName(), overlayPackage);
+ if (overlayResources.getIdentifier(overlayResourceName, null, null)
+ == Resources.ID_NULL) {
+ errors.append(String.format("[%s] is not contained in overlay package [%s]",
+ overlayResourceName, overlayPackage));
+ }
+ }
+ }
+
+ if (!TextUtils.isEmpty(errors)) {
+ fail(errors.toString());
+ }
+ }
+
+ /**
+ * Ensures that all overlay icons have the same values for {@link #VECTOR_ATTRIBUTES} as the
+ * underlying drawable in systemui. To fix this test, make the attribute change to all of the
+ * corresponding drawables in {@link #ICON_PACK_OVERLAY_PACKAGES}.
+ */
+ @Test
+ public void testIconPacks_haveEqualVectorDrawableAttributes() {
+ StringBuilder errors = new StringBuilder();
+
+ for (String overlayPackage : ICON_PACK_OVERLAY_PACKAGES) {
+ Resources overlayResources;
+ try {
+ overlayResources = mContext.getPackageManager()
+ .getResourcesForApplication(overlayPackage);
+ } catch (PackageManager.NameNotFoundException e) {
+ continue; // No need to test overlay resources if apk is not on the system.
+ }
+
+ for (int i = 0; i < mOverlayableIcons.length(); i++) {
+ int sysuiRid = mOverlayableIcons.getResourceId(i, 0);
+ String sysuiResourceName = mResources.getResourceName(sysuiRid);
+ TypedArray sysuiAttrs = getAVDAttributes(mResources, sysuiRid);
+ if (sysuiAttrs == null) {
+ errors.append(String.format("[%s] does not exist or is not a valid AVD.",
+ sysuiResourceName));
+ continue;
+ }
+
+ String overlayResourceName = sysuiResourceName
+ .replace(mContext.getPackageName(), overlayPackage);
+ int overlayRid = overlayResources.getIdentifier(overlayResourceName, null, null);
+ TypedArray overlayAttrs = getAVDAttributes(overlayResources, overlayRid);
+ if (overlayAttrs == null) {
+ errors.append(String.format("[%s] does not exist or is not a valid AVD.",
+ overlayResourceName));
+ continue;
+ }
+
+ if (!attributesEquals(sysuiAttrs, overlayAttrs)) {
+ errors.append(String.format("[%s] AVD attributes do not match [%s]\n",
+ sysuiResourceName, overlayResourceName));
+ }
+ sysuiAttrs.recycle();
+ overlayAttrs.recycle();
+ }
+ }
+
+ if (!TextUtils.isEmpty(errors)) {
+ fail(errors.toString());
+ }
+ }
+
+ private TypedArray getAVDAttributes(Resources resources, @DrawableRes int rid) {
+ try {
+ XmlResourceParser parser = resources.getXml(rid);
+ XmlUtils.nextElement(parser);
+ return resources.obtainAttributes(parser, VECTOR_ATTRIBUTES);
+ } catch (XmlPullParserException | IOException | Resources.NotFoundException e) {
+ return null;
+ }
+ }
+
+ private boolean attributesEquals(TypedArray target, TypedArray overlay) {
+ assertEquals(target.length(), overlay.length());
+ for (int i = 0; i < target.length(); i++) {
+ target.getValue(i, mTargetTypedValue);
+ overlay.getValue(i, mOverlayTypedValue);
+ if (!attributesEquals(mTargetTypedValue, mOverlayTypedValue)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean attributesEquals(TypedValue target, TypedValue overlay) {
+ return target.type == overlay.type && target.data == overlay.data;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index bf067947f2b9..893f3d184acb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -84,6 +85,8 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
private SettableWakeLock mMediaWakeLock;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private DozeParameters mDozeParameters;
private TestableKeyguardSliceProvider mProvider;
private boolean mIsZenMode;
@@ -94,7 +97,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
mProvider = new TestableKeyguardSliceProvider();
mProvider.attachInfo(getContext(), null);
mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController,
- mKeyguardBypassController);
+ mKeyguardBypassController, mDozeParameters);
SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
}
@@ -130,6 +133,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
MediaMetadata metadata = mock(MediaMetadata.class);
when(metadata.getText(any())).thenReturn("metadata");
when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ when(mDozeParameters.getAlwaysOn()).thenReturn(true);
mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
mProvider.onBindSlice(mProvider.getUri());
verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 010b85edacdd..58fb53aae7bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -20,12 +20,16 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -79,13 +83,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private ShadeController mShadeController;
+ private TestableLooper mTestableLooper;
+ private Handler mHandler;
private NotificationViewHierarchyManager mViewHierarchyManager;
private NotificationTestHelper mHelper;
+ private boolean mMadeReentrantCall = false;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- Assert.sMainLooper = TestableLooper.get(this).getLooper();
+ mTestableLooper = TestableLooper.get(this);
+ Assert.sMainLooper = mTestableLooper.getLooper();
+ mHandler = Handler.createAsync(mTestableLooper.getLooper());
+
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mLockscreenUserManager);
@@ -98,7 +108,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
- mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
+ mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
mock(StatusBarStateControllerImpl.class), mEntryManager,
() -> mShadeController, new BubbleData(mContext),
mock(KeyguardBypassController.class),
@@ -215,9 +225,60 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
verify(entry0.getRow(), times(1)).showAppOpsIcons(any());
}
+ @Test
+ public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() {
+ // GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews()
+ mMadeReentrantCall = false;
+ doAnswer((invocation) -> {
+ if (!mMadeReentrantCall) {
+ mMadeReentrantCall = true;
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ return null;
+ }).when(mListContainer).setMaxDisplayedNotifications(anyInt());
+
+ // WHEN we call updateNotificationViews()
+ mViewHierarchyManager.updateNotificationViews();
+
+ // THEN onNotificationViewUpdateFinished() is only called once
+ verify(mListContainer).onNotificationViewUpdateFinished();
+
+ // WHEN we drain the looper
+ mTestableLooper.processAllMessages();
+
+ // THEN updateNotificationViews() is called a second time (for the reentrant call)
+ verify(mListContainer, times(2)).onNotificationViewUpdateFinished();
+ }
+
+ @Test
+ public void testMultipleReentrantCallsToOnDynamicPrivacyChangedOnlyPostOnce() {
+ // GIVEN a ListContainer that will make many re-entrant calls to updateNotificationViews()
+ mMadeReentrantCall = false;
+ doAnswer((invocation) -> {
+ if (!mMadeReentrantCall) {
+ mMadeReentrantCall = true;
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ return null;
+ }).when(mListContainer).setMaxDisplayedNotifications(anyInt());
+
+ // WHEN we call updateNotificationViews() and drain the looper
+ mViewHierarchyManager.updateNotificationViews();
+ verify(mListContainer).onNotificationViewUpdateFinished();
+ clearInvocations(mListContainer);
+ mTestableLooper.processAllMessages();
+
+ // THEN updateNotificationViews() is called only one more time
+ verify(mListContainer).onNotificationViewUpdateFinished();
+ }
+
private class FakeListContainer implements NotificationListContainer {
final LinearLayout mLayout = new LinearLayout(mContext);
final List<View> mRows = Lists.newArrayList();
+ private boolean mMakeReentrantCallDuringSetMaxDisplayedNotifications;
@Override
public void setChildTransferInProgress(boolean childTransferInProgress) {}
@@ -266,7 +327,11 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
}
@Override
- public void setMaxDisplayedNotifications(int maxNotifications) {}
+ public void setMaxDisplayedNotifications(int maxNotifications) {
+ if (mMakeReentrantCallDuringSetMaxDisplayedNotifications) {
+ mViewHierarchyManager.onDynamicPrivacyChanged();
+ }
+ }
@Override
public ViewGroup getViewParentForNotification(NotificationEntry entry) {
@@ -301,5 +366,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
return false;
}
+ @Override
+ public void onNotificationViewUpdateFinished() { }
}
}
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 3f16c128f664..3eb90491f902 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -44,7 +44,6 @@ LOCAL_REQUIRED_MODULES := \
IconPackRoundedSystemUIOverlay \
IconPackRoundedThemePickerUIOverlay \
IconShapeRoundedRectOverlay \
- IconShapeSquareOverlay \
IconShapeSquircleOverlay \
IconShapeTeardropOverlay \
NavigationBarMode3ButtonOverlay \
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_aural.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_aural.xml
new file mode 100644
index 000000000000..64802640a9ec
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_aural.xml
@@ -0,0 +1,40 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M12.64,3 L12.64,8.82352941 C12.2536,8.5 11.772,8.29411765 11.24,8.29411765 C10.0024,8.29411765 9,9.34705882 9,10.6470588 C9,11.9470588 10.0024,13 11.24,13 C12.4776,13 13.48,11.9470588 13.48,10.6470588 L13.48,5.00157166 L15.02,5.00157166 C15.5576,5.00157166 16,4.53686577 16,3.97215989 L16,3 L12.64,3 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,2 C20,0.9 19.1,0 18,0 L6,0 C4.9,0 4,0.9 4,2 L4,14 C4,15.1 4.9,16 6,16 L18,16 C19.1,16 20,15.1 20,14 L20,2 Z M18.5,14 C18.5,14.28 18.28,14.5 18,14.5 L6,14.5 C5.72,14.5 5.5,14.28 5.5,14 L5.5,2 C5.5,1.72 5.72,1.5 6,1.5 L18,1.5 C18.28,1.5 18.5,1.72 18.5,2 L18.5,14 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M0.5,4.75 L0.5,16.75 C0.5,18.27 1.73,19.5 3.25,19.5 L15.25,19.5 C15.66,19.5 16,19.16 16,18.75 C16,18.34 15.66,18 15.25,18 L3.25,18 C2.56,18 2,17.44 2,16.75 L2,4.75 C2,4.34 1.66,4 1.25,4 C0.84,4 0.5,4.34 0.5,4.75 Z"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/values/config.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/values/config.xml
index ae5cc2bf9883..30f29f778858 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/values/config.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/values/config.xml
@@ -30,4 +30,12 @@
<string name="config_batterymeterPowersavePath" translatable="false">
M 3.75,11.25 H 5.25 V 12.75 C 5.25,13.16 5.59,13.5 6,13.5 6.41,13.5 6.75,13.16 6.75,12.75 V 11.25 H 8.25 C 8.66,11.25 9,10.91 9,10.5 9,10.09 8.6601,9.75 8.25,9.75 H 6.75 V 8.25 C 6.75,7.84 6.41,7.5 6,7.5 5.59,7.5 5.25,7.84 5.25,8.25 V 9.75 H 3.75 C 3.34,9.75 3,10.09 3,10.5 3,10.91 3.34,11.25 3.75,11.25 Z
</string>
+ <!-- X path for SignalDrawable as defined on a 24x24 canvas. -->
+ <string name="config_signalXPath" translatable="false">
+ M 17.81,18.75 L 19.81,16.75 C 20.01,16.56 20.09,16.28 20.02,16.02 C 19.96,15.75 19.75,15.54 19.48,15.47 C 19.22,15.41 18.94,15.49 18.75,15.69 L 16.75,17.69 L 14.75,15.69 C 14.56,15.49 14.28,15.41 14.02,15.47 C 13.75,15.54 13.54,15.75 13.47,16.02 C 13.41,16.28 13.49,16.56 13.69,16.75 L 15.69,18.75 L 13.69,20.75 C 13.4,21.04 13.4,21.52 13.69,21.81 C 13.98,22.1 14.46,22.1 14.75,21.81 L 16.75,19.81 L 18.75,21.81 C 19.04,22.1 19.52,22.1 19.81,21.81 C 20.1,21.52 20.1,21.04 19.81,20.75 Z
+ </string>
+ <!-- config_signalCutout{Height,Width}Fraction define fraction of the 24x24 canvas that
+ should be cut out to display config_signalXPath.-->
+ <item name="config_signalCutoutWidthFraction" format="float" type="dimen">10.5</item>
+ <item name="config_signalCutoutHeightFraction" format="float" type="dimen">11</item>
</resources>
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_disable.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_disable.xml
new file mode 100644
index 000000000000..0572fb72f82e
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_disable.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="1.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M11,18.5 C6.313,18.5 2.5,14.687 2.5,10 C2.5,8.182 3.078,6.498 4.055,5.114 L15.887,16.945 C14.503,17.922 12.818,18.5 11,18.5 M20.031,18.969 L2.032,0.971 C1.739,0.678 1.264,0.678 0.971,0.971 C0.678,1.264 0.678,1.738 0.971,2.031 L2.983,4.043 C1.742,5.707 1,7.765 1,10 C1,15.522 5.477,20 11,20 C13.236,20 15.293,19.258 16.957,18.017 L18.971,20.029 C19.117,20.176 19.309,20.249 19.501,20.249 C19.693,20.249 19.885,20.176 20.031,20.029 C20.324,19.736 20.324,19.262 20.031,18.969"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M11,1.5 C15.687,1.5 19.5,5.313 19.5,10 C19.5,11.782 18.946,13.436 18.006,14.804 L19.078,15.877 C20.281,14.226 21,12.199 21,10 C21,4.478 16.522,0 11,0 C8.801,0 6.774,0.719 5.124,1.922 L6.196,2.994 C7.564,2.054 9.218,1.5 11,1.5"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_enable.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_enable.xml
new file mode 100644
index 000000000000..41962b27b270
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_enable.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M12.25,0.2637 L12.25,1.8127 C15.847,2.8017 18.5,6.0927 18.5,9.9997 C18.5,14.6867 14.687,18.4997 10,18.4997 C5.313,18.4997 1.5,14.6867 1.5,9.9997 C1.5,6.0927 4.153,2.8017 7.75,1.8127 L7.75,0.2637 C3.312,1.2847 0,5.2517 0,9.9997 C0,15.5227 4.477,19.9997 10,19.9997 C15.523,19.9997 20,15.5227 20,9.9997 C20,5.2517 16.687,1.2847 12.25,0.2637"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M15.0303,9.9697 C14.7373,9.6767 14.2623,9.6767 13.9693,9.9697 L10.7503,13.1897 L10.7503,0.7387 C10.7503,0.3307 10.4143,-0.0003 10.0003,-0.0003 C9.5863,-0.0003 9.2503,0.3307 9.2503,0.7387 L9.2503,13.1897 L6.0303,9.9697 C5.7373,9.6767 5.2623,9.6767 4.9693,9.9697 C4.6763,10.2627 4.6763,10.7377 4.9693,11.0307 L10.0003,16.0607 L15.0303,11.0307 C15.3233,10.7377 15.3233,10.2627 15.0303,9.9697"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
new file mode 100644
index 000000000000..a0233ba8acc9
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M12.9902,13.5098 C12.9902,13.7858 12.7652,14.0098 12.4902,14.0098 C12.2142,14.0098 11.9902,13.7858 11.9902,13.5098 L11.9902,11.5098 C11.9902,11.2348 12.2142,11.0098 12.4902,11.0098 C12.7652,11.0098 12.9902,11.2348 12.9902,11.5098 L12.9902,13.5098 Z M12.4902,16.0098 C12.2142,16.0098 11.9902,15.7858 11.9902,15.5098 C11.9902,15.2348 12.2142,15.0098 12.4902,15.0098 C12.7652,15.0098 12.9902,15.2348 12.9902,15.5098 C12.9902,15.7858 12.7652,16.0098 12.4902,16.0098 L12.4902,16.0098 Z M15.5182,11.7848 C15.8372,10.9048 16.0102,9.9558 16.0102,8.9698 C16.0102,6.0698 14.5002,3.4798 12.1102,2.0098 L14.5102,2.0098 C14.9102,1.9998 15.2502,1.6598 15.2502,1.2498 C15.2502,0.8398 14.9102,0.4998 14.5002,0.4998 L9.2502,0.4998 L9.2502,6.2498 C9.2502,6.6598 9.5902,6.9998 10.0002,6.9998 C10.4102,6.9998 10.7502,6.6598 10.7502,6.2498 L10.7502,2.9398 C13.0302,4.0598 14.5002,6.3698 14.5002,8.9698 C14.5002,9.5068 14.4172,10.0238 14.2982,10.5268 C13.7682,10.2048 13.1542,10.0098 12.4902,10.0098 C10.5562,10.0098 8.9902,11.5768 8.9902,13.5098 C8.9902,15.4438 10.5562,17.0098 12.4902,17.0098 C14.4232,17.0098 15.9902,15.4438 15.9902,13.5098 C15.9902,12.8798 15.8092,12.2958 15.5182,11.7848 L15.5182,11.7848 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M6.3901,1.04 C2.6301,1.91 0.0001,5.21 0.0001,9.07 C0.0001,11.65 1.2001,13.98 3.1301,15.5 L1.5001,15.5 C1.0901,15.5 0.7501,15.84 0.7501,16.25 C0.7501,16.66 1.0901,17 1.5001,17 L6.7501,17 L6.7501,11.75 C6.7501,11.34 6.4101,11 6.0001,11 C5.5901,11 5.2501,11.34 5.2501,11.75 L5.2501,15.09 C2.9701,13.97 1.5001,11.66 1.5001,9.06 C1.5001,5.91 3.6501,3.21 6.7301,2.5 C7.1301,2.41 7.3901,2 7.2901,1.6 C7.2001,1.2 6.8001,0.95 6.3901,1.04"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_aural.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_aural.xml
new file mode 100644
index 000000000000..3f5c75b66f4c
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_aural.xml
@@ -0,0 +1,27 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20 2H8c-1.1 0-2 0.9-2 2v12c0 1.1 0.9 2 2 2h12c1.1 0 2-0.9 2-2V4c0-1.1-0.9-2-2-2zm-2 5h-3v5.5c0 1.38-1.12 2.5-2.5 2.5S10 13.88 10 12.5s1.12-2.5 2.5-2.5c0.57 0 1.08 0.19 1.5 0.51 V5h4v2zM4 6H2v14c0 1.1 0.9 2 2 2h14v-2H4V6z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/values/config.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/values/config.xml
index 6b59b6265c54..f1d8c7345396 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/values/config.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/values/config.xml
@@ -33,4 +33,12 @@
M 9,11 C 9,11.55 8.55,12 8,12 H 7 V 13 C 7,13.55 6.55,14 6,14 5.45,14 5,13.55 5,13 V 12 H 4 C 3.45,12 3,11.55 3,11 3,10.45 3.45,10.005 4,10 H 5 V 9 C 5,8.45 5.45,8 6,8 6.55,8 7,8.45 7,9 V 10 H 8 C 8.55,10 9,10.45 9,11 Z
</string>
<bool name="config_batterymeterDualTone">true</bool>
+ <!-- X path for SignalDrawable as defined on a 24x24 canvas. -->
+ <string name="config_signalXPath" translatable="false">
+ M 21.7,20.28 L 19.92,18.5 L 21.7,16.72 C 22.1,16.32 22.1,15.68 21.71,15.29 C 21.32,14.9 20.68,14.9 20.28,15.3 L 18.5,17.08 L 16.72,15.3 C 16.32,14.9 15.68,14.9 15.29,15.29 C 14.9,15.68 14.9,16.32 15.3,16.72 L 17.08,18.5 L 15.3,20.28 C 14.9,20.68 14.9,21.32 15.29,21.71 C 15.68,22.1 16.32,22.1 16.72,21.7 L 18.5,19.92 L 20.28,21.7 C 20.68,22.1 21.32,22.1 21.71,21.71 C 22.1,21.32 22.1,20.68 21.7,20.28
+ </string>
+ <!-- config_signalCutout{Height,Width}Fraction define fraction of the 24x24 canvas that
+ should be cut out to display config_signalXPath.-->
+ <item name="config_signalCutoutWidthFraction" format="float" type="dimen">11</item>
+ <item name="config_signalCutoutHeightFraction" format="float" type="dimen">11</item>
</resources>
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_disable.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_disable.xml
new file mode 100644
index 000000000000..b816e4e838fe
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_disable.xml
@@ -0,0 +1,36 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:scaleX="-1"
+ android:translateX="-12.000000"
+ android:translateY="-12.000000" >
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z"
+ android:strokeWidth="1" />
+ </group>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.11,2 C10.33,2 8.67,2.46 7.22,3.28 L8.7,4.76 C9.74,4.28 10.89,4 12.11,4 C16.52,4 20.11,7.59 20.11,12 C20.11,13.22 19.83,14.37 19.35,15.41 L20.83,16.89 C21.65,15.44 22.11,13.78 22.11,12 C22.11,6.48 17.63,2 12.11,2 Z M18.23,17.13 L6.98,5.87 L4.12750442,3.01750442 C3.73635677,2.62635677 3.10252735,2.62523693 2.71,3.015 C2.31926097,3.40298735 2.31703029,4.0342698 2.70501764,4.42500883 C2.70584509,4.42584216 2.70667402,4.42667402 2.70750442,4.42750442 L4.19,5.91 C2.88,7.59 2.11,9.71 2.11,12 C2.11,17.52 6.59,22 12.11,22 C14.4,22 16.52,21.23 18.2,19.92 L19.685,21.405 C20.0743607,21.7943607 20.7056393,21.7943607 21.095,21.405 C21.4843607,21.0156393 21.4843607,20.3843607 21.095,19.995 L18.23,17.13 Z M12.11,20 C7.7,20 4.11,16.41 4.11,12 C4.11,10.26 4.67,8.65 5.62,7.34 L16.77,18.49 C15.46,19.44 13.85,20 12.11,20 Z M8.7,4.76 L7.22,3.28 L8.7,4.76 Z"
+ android:strokeWidth="1" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_enable.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_enable.xml
new file mode 100644
index 000000000000..d0b6209b38ad
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_enable.xml
@@ -0,0 +1,36 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:scaleX="-1"
+ android:translateX="-12.000000"
+ android:translateY="-12.000000" >
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z"
+ android:strokeWidth="1" />
+ </group>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.0016705,11.5012475 L15.3917467,11.5012475 C15.9314188,11.5012475 16.206996,12.1426752 15.8165949,12.5140281 L12.4292913,15.822445 C12.1961989,16.0553846 11.8138355,16.0598858 11.5761501,15.8314475 C11.5738536,15.8280716 11.5704089,15.8258209 11.5681124,15.822445 L8.17851232,12.5117775 C7.79729714,12.1392993 8.06713319,11.5012475 8.60565705,11.5012475 L11.002341,11.5012475 L11.002341,2.99966471 C11.002341,2.44756514 11.4499062,2 12.0020057,2 C12.5541053,2 13.0016705,2.44756514 13.0016705,2.99966471 L13.0016705,11.5012475 Z M15,2.46 L15,4.59 C17.93,5.78 20,8.65 20,12 C20,16.41 16.41,20 12,20 C7.59,20 4,16.41 4,12 C4,8.65 6.07,5.78 9,4.59 L9,2.46 C4.94,3.74 2,7.53 2,12 C2,17.52 6.48,22 12,22 C17.52,22 22,17.52 22,12 C22,7.53 19.06,3.74 15,2.46 Z"
+ android:strokeWidth="1" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
new file mode 100644
index 000000000000..f2dd9e818fc4
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
@@ -0,0 +1,27 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3 12c0 2.21 0.91 4.2 2.36 5.64L3 20h6v-6l-2.24 2.24C5.68 15.15 5 13.66 5 12c0-2.61 1.67-4.83 4-5.65V4.26C5.55 5.15 3 8.27 3 12zm8 5h2v-2h-2v2zM21 4h-6v6l2.24-2.24C18.32 8.85 19 10.34 19 12c0 2.61-1.67 4.83-4 5.65v2.09c3.45-0.89 6-4.01 6-7.74 0-2.21-0.91-4.2-2.36-5.64L21 4zm-10 9h2V7h-2v6z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_aural.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_aural.xml
new file mode 100644
index 000000000000..8cd240d47b2d
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_aural.xml
@@ -0,0 +1,40 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,0 L6,0 C4.9,0 4,0.9 4,2 L4,14 C4,15.1 4.9,16 6,16 L18,16 C19.1,16 20,15.1 20,14 L20,2 C20,0.9 19.1,0 18,0 Z M18.5,14 C18.5,14.28 18.28,14.5 18,14.5 L6,14.5 C5.72,14.5 5.5,14.28 5.5,14 L5.5,2 C5.5,1.72 5.72,1.5 6,1.5 L18,1.5 C18.28,1.5 18.5,1.72 18.5,2 L18.5,14 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M15.86,3.10740288 C15.7704,3.02963963 15.6528,2.990758 15.5352,3.00186703 L13.0152,3.27959295 C12.8024,3.30736554 12.64,3.48511013 12.64,3.69618182 L12.64,9.056292 C12.2536,8.75079349 11.772,8.55638535 11.24,8.55638535 C10.0024,8.55638535 9,9.55064413 9,10.7781927 C9,12.0057412 10.0024,13 11.24,13 C12.4776,13 13.48,12.0057412 13.48,10.7781927 L13.48,5.01241596 L15.6248,4.77912619 C15.8376,4.7513536 16,4.57360901 16,4.36253732 L16,3.41845591 C16,3.30181102 15.9496,3.18516614 15.86,3.10740288 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15.25,18 L3.25,18 C2.56,18 2,17.44 2,16.75 L2,4.75 C2,4.34 1.66,4 1.25,4 C0.84,4 0.5,4.34 0.5,4.75 L0.5,16.75 C0.5,18.27 1.73,19.5 3.25,19.5 L15.25,19.5 C15.66,19.5 16,19.16 16,18.75 C16,18.34 15.66,18 15.25,18 Z"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/values/config.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/values/config.xml
index ebcac82c695f..b7bfaad56249 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/values/config.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/values/config.xml
@@ -30,4 +30,12 @@
<string name="config_batterymeterPowersavePath" translatable="false">
M 3.75,11.25 H 5.25 V 12.75 C 5.25,13.16 5.59,13.5 6,13.5 6.41,13.5 6.75,13.16 6.75,12.75 V 11.25 H 8.25 C 8.66,11.25 9,10.91 9,10.5 9,10.09 8.66,9.7499 8.25,9.7499 H 6.75 V 8.2499 C 6.75,7.8399 6.41,7.4999 6,7.4999 5.59,7.4999 5.2794,7.841 5.25,8.2499 V 9.7499 H 3.75 C 3.34,9.7499 3,10.09 3,10.5 3,10.91 3.3401,11.25 3.75,11.25 Z
</string>
+ <!-- X path for SignalDrawable as defined on a 24x24 canvas. -->
+ <string name="config_signalXPath" translatable="false">
+ M 20.72,16.22 L 19,17.94 L 17.28,16.22 C 16.99,15.93 16.51,15.93 16.22,16.22 C 15.93,16.51 15.93,16.99 16.22,17.28 L 17.94,19 L 16.22,20.72 C 15.93,21.01 15.93,21.49 16.22,21.78 C 16.37,21.93 16.56,22 16.75,22 C 16.94,22 17.13,21.93 17.28,21.78 L 19,20.06 L 20.72,21.78 C 20.87,21.93 21.06,22 21.25,22 C 21.44,22 21.63,21.93 21.78,21.78 C 22.07,21.49 22.07,21.01 21.78,20.72 L 20.06,19 L 21.78,17.28 C 22.07,16.99 22.07,16.51 21.78,16.22 C 21.49,15.93 21.01,15.93 20.72,16.22 Z
+ </string>
+ <!-- config_signalCutout{Height,Width}Fraction define fraction of the 24x24 canvas that
+ should be cut out to display config_signalXPath.-->
+ <item name="config_signalCutoutWidthFraction" format="float" type="dimen">10</item>
+ <item name="config_signalCutoutHeightFraction" format="float" type="dimen">10</item>
</resources>
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_disable.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_disable.xml
new file mode 100644
index 000000000000..0572fb72f82e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_disable.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="1.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M11,18.5 C6.313,18.5 2.5,14.687 2.5,10 C2.5,8.182 3.078,6.498 4.055,5.114 L15.887,16.945 C14.503,17.922 12.818,18.5 11,18.5 M20.031,18.969 L2.032,0.971 C1.739,0.678 1.264,0.678 0.971,0.971 C0.678,1.264 0.678,1.738 0.971,2.031 L2.983,4.043 C1.742,5.707 1,7.765 1,10 C1,15.522 5.477,20 11,20 C13.236,20 15.293,19.258 16.957,18.017 L18.971,20.029 C19.117,20.176 19.309,20.249 19.501,20.249 C19.693,20.249 19.885,20.176 20.031,20.029 C20.324,19.736 20.324,19.262 20.031,18.969"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M11,1.5 C15.687,1.5 19.5,5.313 19.5,10 C19.5,11.782 18.946,13.436 18.006,14.804 L19.078,15.877 C20.281,14.226 21,12.199 21,10 C21,4.478 16.522,0 11,0 C8.801,0 6.774,0.719 5.124,1.922 L6.196,2.994 C7.564,2.054 9.218,1.5 11,1.5"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_enable.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_enable.xml
new file mode 100644
index 000000000000..ec608cdf67dd
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_enable.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M12.2502,0.2637 L12.2502,1.8127 C15.8472,2.8017 18.5002,6.0927 18.5002,9.9997 C18.5002,14.6867 14.6872,18.4997 10.0002,18.4997 C5.3132,18.4997 1.5002,14.6867 1.5002,9.9997 C1.5002,6.0927 4.1532,2.8017 7.7502,1.8127 L7.7502,0.2637 C3.3122,1.2847 0.0002,5.2517 0.0002,9.9997 C0.0002,15.5227 4.4772,19.9997 10.0002,19.9997 C15.5222,19.9997 20.0002,15.5227 20.0002,9.9997 C20.0002,5.2517 16.6872,1.2847 12.2502,0.2637"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M15.0304,9.9697 C14.7374,9.6767 14.2624,9.6767 13.9694,9.9697 L10.7504,13.1897 L10.7504,0.7387 C10.7504,0.3307 10.4144,-0.0003 10.0004,-0.0003 C9.5864,-0.0003 9.2504,0.3307 9.2504,0.7387 L9.2504,13.1897 L6.0304,9.9697 C5.7374,9.6767 5.2624,9.6767 4.9694,9.9697 C4.6764,10.2627 4.6764,10.7377 4.9694,11.0307 L9.4694,15.5307 C9.6164,15.6767 9.8074,15.7497 10.0004,15.7497 C10.1924,15.7497 10.3844,15.6767 10.5304,15.5307 L15.0304,11.0307 C15.3234,10.7377 15.3234,10.2627 15.0304,9.9697"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
new file mode 100644
index 000000000000..e9a07cc3b988
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync_problem_24dp.xml
@@ -0,0 +1,37 @@
+<?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:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="3.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M16.7178,12.626 C17.2378,11.522 17.5288,10.291 17.5288,9 C17.5288,6.119 16.1088,3.539 13.8488,2 L15.7588,2 C16.1578,2 16.4988,1.659 16.4988,1.25 C16.4988,0.84 16.1578,0.5 15.7488,0.5 L10.7488,0.5 C10.3388,0.5 9.9988,0.84 9.9988,1.25 L9.9988,6.25 C9.9988,6.659 10.3388,7 10.7488,7 C11.1578,7 11.4988,6.659 11.4988,6.25 L11.4988,2.47 C14.1978,3.489 16.0188,6.039 16.0188,9 C16.0188,9.785 15.8828,10.542 15.6438,11.252 C15.0498,10.788 14.3108,10.5 13.4988,10.5 C11.5658,10.5 9.9988,12.066 9.9988,14 C9.9988,15.933 11.5658,17.5 13.4988,17.5 C15.4318,17.5 16.9988,15.933 16.9988,14 C16.9988,13.512 16.8978,13.048 16.7178,12.626 L16.7178,12.626 Z M13.4988,16.5 C13.2228,16.5 12.9988,16.275 12.9988,16 C12.9988,15.723 13.2228,15.5 13.4988,15.5 C13.7748,15.5 13.9988,15.723 13.9988,16 C13.9988,16.275 13.7748,16.5 13.4988,16.5 L13.4988,16.5 Z M13.9988,14 C13.9988,14.275 13.7748,14.5 13.4988,14.5 C13.2228,14.5 12.9988,14.275 12.9988,14 L12.9988,12 C12.9988,11.723 13.2228,11.5 13.4988,11.5 C13.7748,11.5 13.9988,11.723 13.9988,12 L13.9988,14 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M7.0811,0.7197 C3.1901,1.6097 0.4801,5.0097 0.4801,8.9997 C0.4801,11.8797 1.9011,14.4587 4.1611,15.9987 L2.2511,15.9987 C1.8411,15.9987 1.5011,16.3397 1.5011,16.7497 C1.5011,17.1577 1.8411,17.4997 2.2511,17.4997 L7.2511,17.4997 C7.6621,17.4997 8.0011,17.1577 8.0011,16.7497 L8.0011,11.7487 C8.0011,11.3397 7.6621,10.9997 7.2511,10.9997 C6.8411,10.9997 6.5021,11.3397 6.5021,11.7487 L6.5021,15.5287 C3.8011,14.5107 1.9811,11.9587 1.9811,8.9997 C1.9811,5.7197 4.2111,2.9097 7.4211,2.1807 C7.8221,2.0907 8.0811,1.6797 7.9801,1.2797 C7.9041,0.9347 7.5961,0.7017 7.2491,0.7017 C7.1941,0.7017 7.1381,0.7067 7.0811,0.7197"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3764ca4b7906..988db6a87100 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2924,6 +2924,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (sVerbose) {
Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
}
+ viewState.setCurrentValue(findValueLocked(id));
mViewStates.put(id, viewState);
}
if ((state & ViewState.STATE_AUTOFILLED) != 0) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index e1b089cf28b2..84886f83027d 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -227,6 +227,7 @@ final class ViewState {
if (mVirtualBounds != null) {
builder.append(", virtualBounds:" ).append(mVirtualBounds);
}
+ builder.append("]");
return builder.toString();
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f0321c190b5f..4f7900eefee2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2579,8 +2579,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai.everConnected) {
loge("ERROR: cannot call explicitlySelected on already-connected network");
}
- nai.networkMisc.explicitlySelected = (msg.arg1 == 1);
- nai.networkMisc.acceptUnvalidated = (msg.arg1 == 1) && (msg.arg2 == 1);
+ nai.networkMisc.explicitlySelected = toBool(msg.arg1);
+ nai.networkMisc.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
// Mark the network as temporarily accepting partial connectivity so that it
// will be validated (and possibly become default) even if it only provides
// partial internet access. Note that if user connects to partial connectivity
@@ -2588,7 +2588,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// out of wifi coverage) and if the same wifi is available again, the device
// will auto connect to this wifi even though the wifi has "no internet".
// TODO: Evaluate using a separate setting in IpMemoryStore.
- nai.networkMisc.acceptPartialConnectivity = (msg.arg2 == 1);
+ nai.networkMisc.acceptPartialConnectivity = toBool(msg.arg2);
break;
}
case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 35fbfe1d4044..9cf342c0e4fb 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -150,11 +150,9 @@ final class HistoricalRegistry {
/**
* Whether history is enabled.
- *
- * <p>The feature is permanently disabled in Android Q
*/
@GuardedBy("mInMemoryLock")
- private final int mMode = AppOpsManager.HISTORICAL_MODE_DISABLED;
+ private int mMode = AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE;
/**
* This granularity has been chosen to allow clean delineation for intervals
@@ -453,7 +451,6 @@ final class HistoricalRegistry {
void setHistoryParameters(@HistoricalMode int mode,
long baseSnapshotInterval, long intervalCompressionMultiplier) {
- /*
synchronized (mOnDiskLock) {
synchronized (mInMemoryLock) {
// NOTE: We allow this call if persistence is not initialized as
@@ -482,7 +479,6 @@ final class HistoricalRegistry {
}
}
}
- */
}
void offsetHistory(long offsetMillis) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 3a74798a2ad8..03224d1939b9 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -117,7 +117,7 @@ class ApexManager {
for (ApexInfo ai : allPkgs) {
// If the device is using flattened APEX, don't report any APEX
// packages since they won't be managed or updated by PackageManager.
- if ((new File(ai.packagePath)).isDirectory()) {
+ if ((new File(ai.modulePath)).isDirectory()) {
break;
}
try {
@@ -131,7 +131,7 @@ class ApexManager {
"Two active packages have the same name: "
+ pkg.packageName);
}
- activePackagesSet.add(ai.packageName);
+ activePackagesSet.add(pkg.packageName);
}
if (ai.isFactory) {
if (factoryPackagesSet.contains(pkg.packageName)) {
@@ -139,7 +139,7 @@ class ApexManager {
"Two factory packages have the same name: "
+ pkg.packageName);
}
- factoryPackagesSet.add(ai.packageName);
+ factoryPackagesSet.add(pkg.packageName);
}
} catch (PackageParserException pe) {
throw new IllegalStateException("Unable to parse: " + ai, pe);
diff --git a/services/core/java/com/android/server/pm/ShareTargetInfo.java b/services/core/java/com/android/server/pm/ShareTargetInfo.java
index 9e8b73e36f69..fdfee773ea74 100644
--- a/services/core/java/com/android/server/pm/ShareTargetInfo.java
+++ b/services/core/java/com/android/server/pm/ShareTargetInfo.java
@@ -15,12 +15,36 @@
*/
package com.android.server.pm;
+import android.annotation.NonNull;
import android.text.TextUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
/**
* Represents a Share Target definition, read from the application's manifest (shortcuts.xml)
*/
class ShareTargetInfo {
+
+ private static final String TAG_SHARE_TARGET = "share-target";
+ private static final String ATTR_TARGET_CLASS = "targetClass";
+
+ private static final String TAG_DATA = "data";
+ private static final String ATTR_SCHEME = "scheme";
+ private static final String ATTR_HOST = "host";
+ private static final String ATTR_PORT = "port";
+ private static final String ATTR_PATH = "path";
+ private static final String ATTR_PATH_PATTERN = "pathPattern";
+ private static final String ATTR_PATH_PREFIX = "pathPrefix";
+ private static final String ATTR_MIME_TYPE = "mimeType";
+
+ private static final String TAG_CATEGORY = "category";
+ private static final String ATTR_NAME = "name";
+
static class TargetData {
final String mScheme;
final String mHost;
@@ -98,4 +122,72 @@ class ShareTargetInfo {
return strBuilder.toString();
}
+
+ void saveToXml(@NonNull XmlSerializer out) throws IOException {
+ out.startTag(null, TAG_SHARE_TARGET);
+
+ ShortcutService.writeAttr(out, ATTR_TARGET_CLASS, mTargetClass);
+
+ for (int i = 0; i < mTargetData.length; i++) {
+ out.startTag(null, TAG_DATA);
+ ShortcutService.writeAttr(out, ATTR_SCHEME, mTargetData[i].mScheme);
+ ShortcutService.writeAttr(out, ATTR_HOST, mTargetData[i].mHost);
+ ShortcutService.writeAttr(out, ATTR_PORT, mTargetData[i].mPort);
+ ShortcutService.writeAttr(out, ATTR_PATH, mTargetData[i].mPath);
+ ShortcutService.writeAttr(out, ATTR_PATH_PATTERN, mTargetData[i].mPathPattern);
+ ShortcutService.writeAttr(out, ATTR_PATH_PREFIX, mTargetData[i].mPathPrefix);
+ ShortcutService.writeAttr(out, ATTR_MIME_TYPE, mTargetData[i].mMimeType);
+ out.endTag(null, TAG_DATA);
+ }
+
+ for (int i = 0; i < mCategories.length; i++) {
+ out.startTag(null, TAG_CATEGORY);
+ ShortcutService.writeAttr(out, ATTR_NAME, mCategories[i]);
+ out.endTag(null, TAG_CATEGORY);
+ }
+
+ out.endTag(null, TAG_SHARE_TARGET);
+ }
+
+ static ShareTargetInfo loadFromXml(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ final String targetClass = ShortcutService.parseStringAttribute(parser, ATTR_TARGET_CLASS);
+ final ArrayList<ShareTargetInfo.TargetData> targetData = new ArrayList<>();
+ final ArrayList<String> categories = new ArrayList<>();
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG) {
+ switch (parser.getName()) {
+ case TAG_DATA:
+ targetData.add(parseTargetData(parser));
+ break;
+ case TAG_CATEGORY:
+ categories.add(ShortcutService.parseStringAttribute(parser, ATTR_NAME));
+ break;
+ }
+ } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_SHARE_TARGET)) {
+ break;
+ }
+ }
+ if (targetData.isEmpty() || targetClass == null || categories.isEmpty()) {
+ return null;
+ }
+ return new ShareTargetInfo(
+ targetData.toArray(new ShareTargetInfo.TargetData[targetData.size()]),
+ targetClass, categories.toArray(new String[categories.size()]));
+ }
+
+ private static ShareTargetInfo.TargetData parseTargetData(XmlPullParser parser) {
+ final String scheme = ShortcutService.parseStringAttribute(parser, ATTR_SCHEME);
+ final String host = ShortcutService.parseStringAttribute(parser, ATTR_HOST);
+ final String port = ShortcutService.parseStringAttribute(parser, ATTR_PORT);
+ final String path = ShortcutService.parseStringAttribute(parser, ATTR_PATH);
+ final String pathPattern = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PATTERN);
+ final String pathPrefix = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PREFIX);
+ final String mimeType = ShortcutService.parseStringAttribute(parser, ATTR_MIME_TYPE);
+
+ return new ShareTargetInfo.TargetData(scheme, host, port, path, pathPattern, pathPrefix,
+ mimeType);
+ }
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d6e87aab35fe..06c71baade42 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -73,6 +73,7 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String TAG_INTENT = "intent";
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
+ private static final String TAG_SHARE_TARGET = "share-target";
private static final String TAG_CATEGORIES = "categories";
private static final String TAG_PERSON = "person";
@@ -1453,8 +1454,9 @@ class ShortcutPackage extends ShortcutPackageItem {
public void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException {
final int size = mShortcuts.size();
+ final int shareTargetSize = mShareTargets.size();
- if (size == 0 && mApiCallCount == 0) {
+ if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
return; // nothing to write.
}
@@ -1470,6 +1472,12 @@ class ShortcutPackage extends ShortcutPackageItem {
getPackageInfo().isBackupAllowed());
}
+ if (!forBackup) {
+ for (int j = 0; j < shareTargetSize; j++) {
+ mShareTargets.get(j).saveToXml(out);
+ }
+ }
+
out.endTag(null, TAG_ROOT);
}
@@ -1627,6 +1635,9 @@ class ShortcutPackage extends ShortcutPackageItem {
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
continue;
+ case TAG_SHARE_TARGET:
+ ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ continue;
}
}
ShortcutService.warnForInvalidTag(depth, tag);
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 18bbfed3364f..f9a019703f4d 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -170,7 +170,7 @@ public class StagingManager {
PackageManager.GET_META_DATA);
} catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + newPackage.packagePath, e);
+ "Failed to parse APEX package " + newPackage.modulePath, e);
}
final PackageInfo activePackage = mApexManager.getPackageInfo(pkg.packageName,
ApexManager.MATCH_ACTIVE_PACKAGE);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 602cc553f870..ab531899b496 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2524,11 +2524,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final int resource;
- if (onWallpaper) {
- resource = R.anim.lock_screen_behind_enter_wallpaper;
- } else if (subtleAnimation) {
+ if (subtleAnimation) {
resource = R.anim.lock_screen_behind_enter_subtle;
- } else {
+ } else if (onWallpaper) {
+ resource = R.anim.lock_screen_behind_enter_wallpaper;
+ } else {
resource = R.anim.lock_screen_behind_enter;
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 6127303141f4..553b0ffa6999 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -176,6 +176,8 @@ class DragState {
mTransaction.transferTouchFocus(mTransferTouchFromToken, h.token);
mTransferTouchFromToken = null;
+ // syncInputWindows here to ensure the input channel isn't removed before the transfer.
+ mTransaction.syncInputWindows();
mTransaction.apply();
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ec8b2efa8a2..47539d3adcb8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1893,6 +1893,10 @@ public final class SystemServer {
mSystemServiceManager.startService(IncidentCompanionService.class);
t.traceEnd();
+ if (safeMode) {
+ mActivityManagerService.enterSafeMode();
+ }
+
// MMS service broker
t.traceBegin("StartMmsService");
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 504d981af53f..06366cf7d143 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -63,7 +63,6 @@ import com.android.server.LocalServices;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;
@@ -234,7 +233,6 @@ public class AppOpsServiceTest {
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
}
- @Ignore("Historical appops are disabled in Android Q")
@Test
public void testGetOpsForPackage() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
@@ -276,7 +274,7 @@ public class AppOpsServiceTest {
assertThat(getLoggedOps()).isNull();
}
- @Ignore("Historical appops are disabled in Android Q")
+
@Test
public void testPackageRemovedHistoricalOps() throws InterruptedException {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 7e6b7da4a058..6c917b7f8636 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -97,16 +97,25 @@ import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.SparseArray;
+import android.util.Xml;
import com.android.frameworks.servicestests.R;
+import com.android.internal.util.FastXmlSerializer;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import com.android.server.pm.ShortcutUser.PackageWithUser;
import org.mockito.ArgumentCaptor;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -8089,4 +8098,70 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
}
}
+
+ public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
+ List<ShareTargetInfo> expectedValues = new ArrayList<>();
+ expectedValues.add(new ShareTargetInfo(
+ new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
+ "http", "www.google.com", "1234", "somePath", "somePathPattern",
+ "somePathPrefix", "text/plain")}, "com.test.directshare.TestActivity1",
+ new String[]{"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"}));
+ expectedValues.add(new ShareTargetInfo(new ShareTargetInfo.TargetData[]{
+ new ShareTargetInfo.TargetData(null, null, null, null, null, null, "video/mp4"),
+ new ShareTargetInfo.TargetData("content", null, null, null, null, null, "video/*")},
+ "com.test.directshare.TestActivity5",
+ new String[]{"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}));
+
+ // Write ShareTargets to Xml
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ final XmlSerializer outXml = new FastXmlSerializer();
+ outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
+ outXml.startDocument(null, true);
+ for (int i = 0; i < expectedValues.size(); i++) {
+ expectedValues.get(i).saveToXml(outXml);
+ }
+ outXml.endDocument();
+ outXml.flush();
+
+ // Read ShareTargets from Xml
+ ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new InputStreamReader(inStream));
+ List<ShareTargetInfo> shareTargets = new ArrayList<>();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG && parser.getName().equals("share-target")) {
+ shareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ }
+ }
+
+ // Assert two lists are equal
+ assertNotNull(shareTargets);
+ assertEquals(expectedValues.size(), shareTargets.size());
+
+ for (int i = 0; i < expectedValues.size(); i++) {
+ ShareTargetInfo expected = expectedValues.get(i);
+ ShareTargetInfo actual = shareTargets.get(i);
+
+ assertEquals(expected.mTargetData.length, actual.mTargetData.length);
+ for (int j = 0; j < expected.mTargetData.length; j++) {
+ assertEquals(expected.mTargetData[j].mScheme, actual.mTargetData[j].mScheme);
+ assertEquals(expected.mTargetData[j].mHost, actual.mTargetData[j].mHost);
+ assertEquals(expected.mTargetData[j].mPort, actual.mTargetData[j].mPort);
+ assertEquals(expected.mTargetData[j].mPath, actual.mTargetData[j].mPath);
+ assertEquals(expected.mTargetData[j].mPathPrefix,
+ actual.mTargetData[j].mPathPrefix);
+ assertEquals(expected.mTargetData[j].mPathPattern,
+ actual.mTargetData[j].mPathPattern);
+ assertEquals(expected.mTargetData[j].mMimeType, actual.mTargetData[j].mMimeType);
+ }
+
+ assertEquals(expected.mTargetClass, actual.mTargetClass);
+
+ assertEquals(expected.mCategories.length, actual.mCategories.length);
+ for (int j = 0; j < expected.mCategories.length; j++) {
+ assertEquals(expected.mCategories[j], actual.mCategories[j]);
+ }
+ }
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 484fd3b17c02..4a9b174cedbb 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2121,24 +2121,27 @@ public class SubscriptionManager {
* @hide
*/
@UnsupportedAppUsage
- public @NonNull int[] getActiveSubscriptionIdList() {
- int[] subId = null;
+ public static @NonNull int[] getActiveSubscriptionIdList() {
+ return getActiveSubscriptionIdList(true);
+ }
+ /**
+ * @return a non-null list of subId's that are active.
+ *
+ * @hide
+ */
+ public static @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
+ int[] subId = iSub.getActiveSubIdList(visibleOnly);
+ if (subId != null) return subId;
}
} catch (RemoteException ex) {
// ignore it
}
- if (subId == null) {
- subId = new int[0];
- }
-
- return subId;
-
+ return new int[0];
}
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 7a0ab9ca6a28..5b57c9d7554c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -605,15 +605,11 @@ public final class TelephonyPermissions {
*/
private static boolean checkCarrierPrivilegeForAnySubId(Context context,
Supplier<ITelephony> telephonySupplier, int uid) {
- SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- int[] activeSubIds = sm.getActiveSubscriptionIdList();
- if (activeSubIds != null) {
- for (int activeSubId : activeSubIds) {
- if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return true;
- }
+ int[] activeSubIds = SubscriptionManager.getActiveSubscriptionIdList(/*visibleOnly*/ false);
+ for (int activeSubId : activeSubIds) {
+ if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
}
}
return false;
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 42328baf5265..1b2a12887aa5 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -652,8 +652,8 @@ public class ConnectivityServiceTest {
return mScore;
}
- public void explicitlySelected(boolean acceptUnvalidated) {
- mNetworkAgent.explicitlySelected(acceptUnvalidated);
+ public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
+ mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
}
public void addCapability(int capability) {
@@ -756,6 +756,11 @@ public class ConnectivityServiceTest {
connect(false);
}
+ public void connectWithPartialValidConnectivity() {
+ setNetworkPartialValid();
+ connect(false);
+ }
+
public void suspend() {
mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -2389,7 +2394,7 @@ public class ConnectivityServiceTest {
// Bring up unvalidated wifi with explicitlySelected=true.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2412,7 +2417,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2423,7 +2428,7 @@ public class ConnectivityServiceTest {
// Reconnect, again with explicitlySelected=true, but this time validate.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
@@ -2438,14 +2443,36 @@ public class ConnectivityServiceTest {
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
+ // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
+ // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
+ // wifi immediately.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(true, true);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mEthernetNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ mEthernetNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+
+ // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
+ // Check that the network is not scored specially and that the device prefers cell data.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false, true);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
// Clean up.
mWiFiNetworkAgent.disconnect();
mCellNetworkAgent.disconnect();
- mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
}
private int[] makeIntArray(final int size, final int value) {
@@ -2690,6 +2717,7 @@ public class ConnectivityServiceTest {
// NetworkMonitor#setAcceptPartialConnectivity() should be called too.
waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
@@ -2720,8 +2748,10 @@ public class ConnectivityServiceTest {
// NET_CAPABILITY_PARTIAL_CONNECTIVITY.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
// acceptUnvalidated is also used as setting for accepting partial networks.
- mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
+ mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+ true /* acceptUnvalidated */);
mWiFiNetworkAgent.connect(true);
+
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
// ConnectivityService#updateNetworkInfo().
@@ -2731,20 +2761,18 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+
// Wifi should be the default network.
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- // If user accepted partial connectivity before, and now the device reconnects to the
- // partial connectivity network. The network should be valid and contain
- // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
+ // The user accepted partial connectivity and selected "don't ask again". Now the user
+ // reconnects to the partial connectivity network. Switch to wifi as soon as partial
+ // connectivity is detected.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
- // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
- // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
- // to ConnectivityService first then send VALID. Once NetworkMonitor support
- // multi-testResult, this test case also need to be changed to meet the new design.
+ mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+ true /* acceptUnvalidated */);
mWiFiNetworkAgent.connectWithPartialConnectivity();
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
@@ -2753,17 +2781,35 @@ public class ConnectivityServiceTest {
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
- // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
- // NetworkMonitor detects partial connectivity
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
mWiFiNetworkAgent.setNetworkValid();
+
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // If the user accepted partial connectivity, and the device auto-reconnects to the partial
+ // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
+ true /* acceptUnvalidated */);
+
+ // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
+ // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
+ // notifyNetworkConnected.
+ mWiFiNetworkAgent.connectWithPartialValidConnectivity();
+ waitForIdle();
+ verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCapabilitiesWith(
+ NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
}
@Test