summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java9
-rw-r--r--cmds/statsd/src/atoms.proto10
-rw-r--r--core/java/android/app/ActivityManager.java63
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java1
-rw-r--r--media/java/android/mtp/MtpPropertyGroup.java6
-rw-r--r--packages/SystemUI/res/layout/controls_app_item.xml29
-rw-r--r--packages/SystemUI/res/layout/controls_base_item.xml10
-rw-r--r--packages/SystemUI/res/layout/controls_horizontal_divider_with_empty.xml12
-rw-r--r--packages/SystemUI/res/layout/controls_management.xml11
-rw-r--r--packages/SystemUI/res/layout/controls_management_apps.xml4
-rw-r--r--packages/SystemUI/res/layout/controls_management_editing.xml2
-rw-r--r--packages/SystemUI/res/layout/controls_management_favorites.xml4
-rw-r--r--packages/SystemUI/res/layout/controls_structure_page.xml2
-rw-r--r--packages/SystemUI/res/layout/controls_zone_header.xml7
-rw-r--r--packages/SystemUI/res/values/dimens.xml22
-rw-r--r--packages/SystemUI/res/values/styles.xml12
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSMediaBrowser.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt110
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt61
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java47
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java108
-rw-r--r--services/core/java/com/android/server/am/AppExitInfoTracker.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java18
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLogger.java5
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java107
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java9
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java23
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java53
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java25
-rw-r--r--services/core/java/com/android/server/wm/Task.java11
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java22
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java9
50 files changed, 877 insertions, 344 deletions
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index d22e998f6cab..a9ed6d82b873 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -1288,7 +1288,11 @@ public final class MediaParser {
}
@Override
- public int sampleData(DataReader input, int length, boolean allowEndOfInput)
+ public int sampleData(
+ DataReader input,
+ int length,
+ boolean allowEndOfInput,
+ @SampleDataPart int sampleDataPart)
throws IOException {
mScratchDataReaderAdapter.setDataReader(input, length);
long positionBeforeReading = mScratchDataReaderAdapter.getPosition();
@@ -1297,7 +1301,8 @@ public final class MediaParser {
}
@Override
- public void sampleData(ParsableByteArray data, int length) {
+ public void sampleData(
+ ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
try {
mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchParsableByteArrayAdapter);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 674978b50d91..9a73fddebad4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -427,6 +427,7 @@ message Atom {
AccessibilityShortcutReported accessibility_shortcut_reported =
266 [(module) = "framework"];
AccessibilityServiceReported accessibility_service_reported = 267 [(module) = "settings"];
+ DocsUIDragAndDropReported docs_ui_drag_and_drop_reported = 268 [(module) = "docsui"];
SdkExtensionStatus sdk_extension_status = 354;
// StatsdStats tracks platform atoms with ids upto 500.
@@ -6481,6 +6482,15 @@ message DocsUIPickResultReported {
optional int32 repeatedly_pick_times = 7;
}
+/** Logs the drag and drop of files.
+
+ * Logged from:
+ * package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIDragAndDropReported {
+ optional bool drag_initiated_from_docsui = 1;
+}
+
/**
* Logs when an app's memory is compacted.
*
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d1b6efd3e23a..49cc621cf2b2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1719,31 +1719,50 @@ public class ActivityManager {
configuration.windowConfiguration.getActivityType());
pw.println(); pw.print(" ");
- pw.print(" id=" + persistentId);
- pw.print(" stackId=" + stackId);
- pw.print(" userId=" + userId);
- pw.print(" hasTask=" + (id != -1));
- pw.print(" lastActiveTime=" + lastActiveTime);
- pw.println(); pw.print(" ");
- pw.print(" baseIntent=" + baseIntent);
- pw.println(); pw.print(" ");
- pw.print(" isExcluded="
- + ((baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0));
- pw.print(" activityType=" + activityType);
- pw.print(" windowingMode=" + windowingMode);
- pw.print(" supportsSplitScreenMultiWindow=" + supportsSplitScreenMultiWindow);
+ pw.print(" id="); pw.print(persistentId);
+ pw.print(" stackId="); pw.print(stackId);
+ pw.print(" userId="); pw.print(userId);
+ pw.print(" hasTask="); pw.print((id != -1));
+ pw.print(" lastActiveTime="); pw.println(lastActiveTime);
+ pw.print(" "); pw.print(" baseIntent="); pw.println(baseIntent);
+ if (baseActivity != null) {
+ pw.print(" "); pw.print(" baseActivity=");
+ pw.println(baseActivity.toShortString());
+ }
+ if (topActivity != null) {
+ pw.print(" "); pw.print(" topActivity="); pw.println(topActivity.toShortString());
+ }
+ if (origActivity != null) {
+ pw.print(" "); pw.print(" origActivity=");
+ pw.println(origActivity.toShortString());
+ }
+ if (realActivity != null) {
+ pw.print(" "); pw.print(" realActivity=");
+ pw.println(realActivity.toShortString());
+ }
+ pw.print(" ");
+ pw.print(" isExcluded=");
+ pw.print(((baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0));
+ pw.print(" activityType="); pw.print(activityType);
+ pw.print(" windowingMode="); pw.print(windowingMode);
+ pw.print(" supportsSplitScreenMultiWindow=");
+ pw.println(supportsSplitScreenMultiWindow);
if (taskDescription != null) {
- pw.println(); pw.print(" ");
+ pw.print(" ");
final ActivityManager.TaskDescription td = taskDescription;
pw.print(" taskDescription {");
- pw.print(" colorBackground=#" + Integer.toHexString(td.getBackgroundColor()));
- pw.print(" colorPrimary=#" + Integer.toHexString(td.getPrimaryColor()));
- pw.print(" iconRes=" + td.getIconResourcePackage() + "/" + td.getIconResource());
- pw.print(" iconBitmap=" + (td.getIconFilename() != null
- || td.getInMemoryIcon() != null));
- pw.print(" resizeMode=" + ActivityInfo.resizeModeToString(td.getResizeMode()));
- pw.print(" minWidth=" + td.getMinWidth());
- pw.print(" minHeight=" + td.getMinHeight());
+ pw.print(" colorBackground=#");
+ pw.print(Integer.toHexString(td.getBackgroundColor()));
+ pw.print(" colorPrimary=#");
+ pw.print(Integer.toHexString(td.getPrimaryColor()));
+ pw.print(" iconRes=");
+ pw.print(td.getIconResourcePackage() + "/" + td.getIconResource());
+ pw.print(" iconBitmap=");
+ pw.print(td.getIconFilename() != null || td.getInMemoryIcon() != null);
+ pw.print(" resizeMode=");
+ pw.print(ActivityInfo.resizeModeToString(td.getResizeMode()));
+ pw.print(" minWidth="); pw.print(td.getMinWidth());
+ pw.print(" minHeight="); pw.print(td.getMinHeight());
pw.println(" }");
}
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index aba74e518a22..ed56b4398c22 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -165,6 +165,7 @@ public class MtpDatabase implements AutoCloseable {
MtpConstants.PROPERTY_TRACK,
MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
MtpConstants.PROPERTY_DURATION,
+ MtpConstants.PROPERTY_GENRE,
MtpConstants.PROPERTY_COMPOSER,
MtpConstants.PROPERTY_AUDIO_WAVE_CODEC,
MtpConstants.PROPERTY_BITRATE_TYPE,
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index 5bb0c1b4ef27..aff2e1b4cf31 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -122,15 +122,21 @@ class MtpPropertyGroup {
type = MtpConstants.TYPE_STR;
break;
case MtpConstants.PROPERTY_ARTIST:
+ column = Audio.AudioColumns.ARTIST;
type = MtpConstants.TYPE_STR;
break;
case MtpConstants.PROPERTY_ALBUM_NAME:
+ column = Audio.AudioColumns.ALBUM;
type = MtpConstants.TYPE_STR;
break;
case MtpConstants.PROPERTY_ALBUM_ARTIST:
column = Audio.AudioColumns.ALBUM_ARTIST;
type = MtpConstants.TYPE_STR;
break;
+ case MtpConstants.PROPERTY_GENRE:
+ column = Audio.AudioColumns.GENRE;
+ type = MtpConstants.TYPE_STR;
+ break;
case MtpConstants.PROPERTY_COMPOSER:
column = Audio.AudioColumns.COMPOSER;
type = MtpConstants.TYPE_STR;
diff --git a/packages/SystemUI/res/layout/controls_app_item.xml b/packages/SystemUI/res/layout/controls_app_item.xml
index d54cd6db867a..a208098b59c9 100644
--- a/packages/SystemUI/res/layout/controls_app_item.xml
+++ b/packages/SystemUI/res/layout/controls_app_item.xml
@@ -16,33 +16,25 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="64dp"
android:background="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_gravity="start|top"
- android:gravity="center_vertical"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:layout_marginBottom="@dimen/controls_app_bottom_margin">
+ android:gravity="center_vertical">
<FrameLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="start|center_vertical"
- android:minWidth="56dp"
+ android:layout_height="match_parent"
android:orientation="horizontal"
- android:paddingTop="@dimen/controls_app_icon_frame_top_padding"
- android:paddingBottom="@dimen/controls_app_icon_frame_top_padding"
- android:paddingEnd="@dimen/controls_app_icon_frame_side_padding"
- android:paddingStart="@dimen/controls_app_icon_frame_side_padding" >
+ android:paddingEnd="@dimen/controls_app_icon_frame_side_padding">
<ImageView
android:id="@android:id/icon"
+ android:layout_gravity="start|center_vertical"
android:layout_width="@dimen/controls_app_icon_size"
android:layout_height="@dimen/controls_app_icon_size" />
</FrameLayout>
@@ -51,9 +43,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
- android:paddingTop="@dimen/controls_app_text_padding"
- android:paddingBottom="@dimen/controls_app_text_padding">
+ android:orientation="vertical">
<TextView
android:id="@android:id/title"
@@ -62,8 +52,7 @@
android:ellipsize="end"
android:fadingEdge="horizontal"
android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary"/>
+ android:textAppearance="@style/TextAppearance.Control.Management.Subtitle"/>
<TextView
android:id="@+id/favorites"
@@ -81,7 +70,5 @@
android:layout_width="match_parent"
android:layout_height="@dimen/controls_app_divider_height"
android:layout_gravity="center_horizontal|bottom"
- android:layout_marginStart="@dimen/controls_app_divider_side_margin"
- android:layout_marginEnd="@dimen/controls_app_divider_side_margin"
android:background="?android:attr/listDivider" />
</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index e7bb3afc25af..477a70f4c7ad 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -98,15 +98,15 @@
<CheckBox
android:id="@+id/favorite"
android:visibility="invisible"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|end"
+ android:layout_width="@dimen/controls_management_checkbox_size"
+ android:layout_height="@dimen/controls_management_checkbox_size"
+ android:minHeight="0dp"
+ android:minWidth="0dp"
+ android:gravity="center"
android:background="@android:color/transparent"
android:clickable="false"
android:selectable="false"
android:importantForAccessibility="no"
- android:layout_marginTop="4dp"
- android:layout_marginStart="4dp"
app:layout_constraintStart_toEndOf="@id/subtitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
diff --git a/packages/SystemUI/res/layout/controls_horizontal_divider_with_empty.xml b/packages/SystemUI/res/layout/controls_horizontal_divider_with_empty.xml
index 90b3398e3de2..11144f6a94b4 100644
--- a/packages/SystemUI/res/layout/controls_horizontal_divider_with_empty.xml
+++ b/packages/SystemUI/res/layout/controls_horizontal_divider_with_empty.xml
@@ -22,23 +22,17 @@
>
<View
- android:layout_width="match_parent"
- android:layout_height="@dimen/controls_management_list_margin"
- />
-
- <FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="@dimen/control_height"
android:visibility="gone"
>
- </FrameLayout>
+ </View>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
- android:layout_marginBottom="10dp"
- android:layout_marginStart="40dp"
- android:layout_marginEnd="40dp"
+ android:layout_marginBottom="@dimen/controls_management_editing_divider_margin"
+ android:layout_marginTop="@dimen/controls_management_editing_divider_margin"
android:background="#4dffffff" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_management.xml b/packages/SystemUI/res/layout/controls_management.xml
index 835e54e9e433..46f79deff109 100644
--- a/packages/SystemUI/res/layout/controls_management.xml
+++ b/packages/SystemUI/res/layout/controls_management.xml
@@ -31,18 +31,15 @@
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/controls_title_size"
+ android:textAppearance="@style/TextAppearance.Control.Management.Title"
android:textAlignment="center" />
-
-
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/controls_management_titles_margin"
- android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAppearance="@style/TextAppearance.Control.Management.Subtitle"
android:textAlignment="center" />
<ViewStub
@@ -53,7 +50,7 @@
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="64dp">
+ android:layout_height="72dp">
<View
android:layout_width="match_parent"
@@ -64,7 +61,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="4dp">
+ android:padding="@dimen/controls_management_footer_side_margin">
<Button
android:id="@+id/other_apps"
diff --git a/packages/SystemUI/res/layout/controls_management_apps.xml b/packages/SystemUI/res/layout/controls_management_apps.xml
index 94df9d8f4775..4348ffe40087 100644
--- a/packages/SystemUI/res/layout/controls_management_apps.xml
+++ b/packages/SystemUI/res/layout/controls_management_apps.xml
@@ -19,6 +19,8 @@
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginTop="@dimen/controls_management_list_margin"
+ android:layout_marginTop="@dimen/controls_management_apps_list_margin"
+ android:layout_marginStart="@dimen/controls_management_apps_extra_side_margin"
+ android:layout_marginEnd="@dimen/controls_management_apps_extra_side_margin"
/>
diff --git a/packages/SystemUI/res/layout/controls_management_editing.xml b/packages/SystemUI/res/layout/controls_management_editing.xml
index 8a14ec3666b2..7356b290380a 100644
--- a/packages/SystemUI/res/layout/controls_management_editing.xml
+++ b/packages/SystemUI/res/layout/controls_management_editing.xml
@@ -22,6 +22,6 @@
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingTop="@dimen/controls_management_list_margin"
+ android:paddingTop="@dimen/controls_management_editing_list_margin"
/>
diff --git a/packages/SystemUI/res/layout/controls_management_favorites.xml b/packages/SystemUI/res/layout/controls_management_favorites.xml
index d2ccfcb11c5c..a0d8ae42f584 100644
--- a/packages/SystemUI/res/layout/controls_management_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_management_favorites.xml
@@ -32,10 +32,10 @@
<com.android.systemui.controls.management.ManagementPageIndicator
android:id="@+id/structure_page_indicator"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_height="@dimen/controls_management_page_indicator_height"
android:layout_gravity="center"
android:layout_marginTop="@dimen/controls_management_list_margin"
- android:visibility="gone" />
+ android:visibility="invisible" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/structure_pager"
diff --git a/packages/SystemUI/res/layout/controls_structure_page.xml b/packages/SystemUI/res/layout/controls_structure_page.xml
index 047ab98eb191..f048d62d46d7 100644
--- a/packages/SystemUI/res/layout/controls_structure_page.xml
+++ b/packages/SystemUI/res/layout/controls_structure_page.xml
@@ -21,4 +21,4 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:layout_marginTop="@dimen/controls_management_list_margin"/> \ No newline at end of file
+ android:layout_marginTop="@dimen/controls_management_zone_top_margin"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_zone_header.xml b/packages/SystemUI/res/layout/controls_zone_header.xml
index 93f99b12fd31..74c020a29c60 100644
--- a/packages/SystemUI/res/layout/controls_zone_header.xml
+++ b/packages/SystemUI/res/layout/controls_zone_header.xml
@@ -18,10 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Control.Title"
- android:layout_marginStart="12dp"
- android:layout_marginEnd="2dp"
- android:layout_marginTop="8dp"
+ android:textAppearance="@style/TextAppearance.Control.Management.Subtitle"
+ android:layout_marginTop="@dimen/controls_management_zone_top_margin"
android:layout_marginBottom="4dp">
-
</TextView> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2c2e7244ce2e..c68c814532fe 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1283,13 +1283,23 @@
<!-- Home Controls management screens -->
<dimen name="controls_management_top_padding">48dp</dimen>
- <dimen name="controls_management_side_padding">8dp</dimen>
- <dimen name="controls_management_titles_margin">8dp</dimen>
+ <dimen name="controls_management_side_padding">16dp</dimen>
+ <dimen name="controls_management_titles_margin">16dp</dimen>
+ <dimen name="controls_management_footer_side_margin">8dp</dimen>
<dimen name="controls_management_list_margin">16dp</dimen>
- <dimen name="controls_title_size">26sp</dimen>
-
- <dimen name="controls_app_icon_size">32dp</dimen>
- <dimen name="controls_app_icon_frame_side_padding">8dp</dimen>
+ <dimen name="controls_management_apps_list_margin">64dp</dimen>
+ <dimen name="controls_management_editing_list_margin">48dp</dimen>
+ <dimen name="controls_management_editing_divider_margin">24dp</dimen>
+ <dimen name="controls_management_apps_extra_side_margin">8dp</dimen>
+ <dimen name="controls_management_apps_top_margin"></dimen>
+ <dimen name="controls_management_zone_top_margin">32dp</dimen>
+ <dimen name="controls_management_page_indicator_height">24dp</dimen>
+ <dimen name="controls_management_checkbox_size">25dp</dimen>
+ <dimen name="controls_title_size">24sp</dimen>
+ <dimen name="controls_subtitle_size">16sp</dimen>
+
+ <dimen name="controls_app_icon_size">24dp</dimen>
+ <dimen name="controls_app_icon_frame_side_padding">16dp</dimen>
<dimen name="controls_app_icon_frame_top_padding">4dp</dimen>
<dimen name="controls_app_icon_frame_bottom_padding">@dimen/controls_app_icon_frame_top_padding</dimen>
<dimen name="controls_app_bottom_margin">8dp</dimen>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d3a5f04b7285..6e25625d3b88 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -734,6 +734,18 @@
<item name="android:textSize">@dimen/control_text_size</item>
<item name="android:textColor">@color/control_secondary_text</item>
</style>
+ <style name="TextAppearance.Control.Management" >
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+ <style name="TextAppearance.Control.Management.Title">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:textSize">@dimen/controls_title_size</item>
+ </style>
+ <style name="TextAppearance.Control.Management.Subtitle">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textSize">@dimen/controls_subtitle_size</item>
+ </style>
+
<style name="Control.ListPopupWindow" parent="@*android:style/Widget.DeviceDefault.ListPopupWindow">
<item name="android:overlapAnchor">true</item>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 0af026eb3509..02d2b8e4ef0f 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -76,7 +76,6 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager.Keyg
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -308,7 +307,6 @@ public class Dependency {
@Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper;
@Inject Lazy<SensorPrivacyController> mSensorPrivacyController;
@Inject Lazy<DockManager> mDockManager;
- @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController;
@Inject Lazy<INotificationManager> mINotificationManager;
@Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
@Inject Lazy<AlarmManager> mAlarmManager;
@@ -498,7 +496,6 @@ public class Dependency {
mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get);
mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get);
mProviders.put(DockManager.class, mDockManager::get);
- mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get);
mProviders.put(INotificationManager.class, mINotificationManager::get);
mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
mProviders.put(AlarmManager.class, mAlarmManager::get);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 03ca3931e68c..79dd9edef0f0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -18,6 +18,7 @@ package com.android.systemui.controls.management
import android.content.ComponentName
import android.graphics.Rect
+import android.service.controls.Control
import android.service.controls.DeviceTypes
import android.view.LayoutInflater
import android.view.View
@@ -46,9 +47,9 @@ class ControlAdapter(
) : RecyclerView.Adapter<Holder>() {
companion object {
- private const val TYPE_ZONE = 0
- private const val TYPE_CONTROL = 1
- private const val TYPE_DIVIDER = 2
+ const val TYPE_ZONE = 0
+ const val TYPE_CONTROL = 1
+ const val TYPE_DIVIDER = 2
}
val spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
@@ -142,7 +143,7 @@ sealed class Holder(view: View) : RecyclerView.ViewHolder(view) {
/**
* Holder for using with [DividerWrapper] to display a divider between zones.
*
- * The divider can be shown or hidden. It also has a frame view the height of a control, that can
+ * The divider can be shown or hidden. It also has a view the height of a control, that can
* be toggled visible or gone.
*/
private class DividerHolder(view: View) : Holder(view) {
@@ -229,10 +230,25 @@ class MarginItemDecorator(
parent: RecyclerView,
state: RecyclerView.State
) {
- outRect.apply {
- top = topMargin
- left = sideMargins
- right = sideMargins
+ val position = parent.getChildAdapterPosition(view)
+ if (position == RecyclerView.NO_POSITION) return
+ val type = parent.adapter?.getItemViewType(position)
+ if (type == ControlAdapter.TYPE_CONTROL) {
+ outRect.apply {
+ top = topMargin
+ left = sideMargins
+ right = sideMargins
+ bottom = 0
+ }
+ } else if (type == ControlAdapter.TYPE_ZONE && position == 0) {
+ // add negative padding to the first zone to counteract the margin
+ val margin = (view.layoutParams as ViewGroup.MarginLayoutParams).topMargin
+ outRect.apply {
+ top = -margin
+ left = 0
+ right = 0
+ bottom = 0
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index e3175aafb1b1..bd75116984ab 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -104,7 +104,9 @@ class ControlsFavoritingActivity @Inject constructor(
override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {
if (serviceInfos.size > 1) {
- otherAppsButton.visibility = View.VISIBLE
+ otherAppsButton.post {
+ otherAppsButton.visibility = View.VISIBLE
+ }
}
}
}
@@ -170,7 +172,7 @@ class ControlsFavoritingActivity @Inject constructor(
pageIndicator.setNumPages(listOfStructures.size)
pageIndicator.setLocation(0f)
pageIndicator.visibility =
- if (listOfStructures.size > 1) View.VISIBLE else View.GONE
+ if (listOfStructures.size > 1) View.VISIBLE else View.INVISIBLE
ControlsAnimations.enterAnimation(pageIndicator).apply {
addListener(object : AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index f87605382913..557132bdf08e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -98,6 +98,7 @@ public class MediaControlPanel {
private SharedPreferences mSharedPrefs;
private boolean mCheckedForResumption = false;
private boolean mIsRemotePlayback;
+ private QSMediaBrowser mQSMediaBrowser;
// Button IDs used in notifications
protected static final int[] NOTIF_ACTION_IDS = {
@@ -232,6 +233,11 @@ public class MediaControlPanel {
String key) {
// Ensure that component names are updated if token has changed
if (mToken == null || !mToken.equals(token)) {
+ if (mQSMediaBrowser != null) {
+ Log.d(TAG, "Disconnecting old media browser");
+ mQSMediaBrowser.disconnect();
+ mQSMediaBrowser = null;
+ }
mToken = token;
mServiceComponent = null;
mCheckedForResumption = false;
@@ -618,8 +624,22 @@ public class MediaControlPanel {
ImageButton btn = mMediaNotifView.findViewById(mActionIds[0]);
btn.setOnClickListener(v -> {
Log.d(TAG, "Attempting to restart session");
- QSMediaBrowser browser = new QSMediaBrowser(mContext, null, mServiceComponent);
- browser.restart();
+ if (mQSMediaBrowser != null) {
+ mQSMediaBrowser.disconnect();
+ }
+ mQSMediaBrowser = new QSMediaBrowser(mContext, new QSMediaBrowser.Callback(){
+ @Override
+ public void onConnected() {
+ Log.d(TAG, "Successfully restarted");
+ }
+ @Override
+ public void onError() {
+ Log.e(TAG, "Error restarting");
+ mQSMediaBrowser.disconnect();
+ mQSMediaBrowser = null;
+ }
+ }, mServiceComponent);
+ mQSMediaBrowser.restart();
});
btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play));
btn.setImageTintList(ColorStateList.valueOf(mForegroundColor));
@@ -654,13 +674,18 @@ public class MediaControlPanel {
*/
private void tryUpdateResumptionList(ComponentName componentName) {
Log.d(TAG, "Testing if we can connect to " + componentName);
- QSMediaBrowser.testConnection(mContext,
+ if (mQSMediaBrowser != null) {
+ mQSMediaBrowser.disconnect();
+ }
+ mQSMediaBrowser = new QSMediaBrowser(mContext,
new QSMediaBrowser.Callback() {
@Override
public void onConnected() {
Log.d(TAG, "yes we can resume with " + componentName);
mServiceComponent = componentName;
updateResumptionList(componentName);
+ mQSMediaBrowser.disconnect();
+ mQSMediaBrowser = null;
}
@Override
@@ -671,9 +696,12 @@ public class MediaControlPanel {
// If it's not active and we can't resume, remove
removePlayer();
}
+ mQSMediaBrowser.disconnect();
+ mQSMediaBrowser = null;
}
},
componentName);
+ mQSMediaBrowser.testConnection();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaBrowser.java
index 9e532868427f..a5b73dcbd289 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaBrowser.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaBrowser.java
@@ -58,21 +58,25 @@ public class QSMediaBrowser {
mContext = context;
mCallback = callback;
mComponentName = componentName;
-
- Bundle rootHints = new Bundle();
- rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
- mMediaBrowser = new MediaBrowser(mContext,
- mComponentName,
- mConnectionCallback,
- rootHints);
}
/**
* Connects to the MediaBrowserService and looks for valid media. If a media item is returned
- * by the service, QSMediaBrowser.Callback#addTrack will be called with its MediaDescription
+ * by the service, QSMediaBrowser.Callback#addTrack will be called with its MediaDescription.
+ * QSMediaBrowser.Callback#onConnected and QSMediaBrowser.Callback#onError will also be called
+ * when the initial connection is successful, or an error occurs. Note that it is possible for
+ * the service to connect but for no playable tracks to be found later.
+ * QSMediaBrowser#disconnect will be called automatically with this function.
*/
public void findRecentMedia() {
Log.d(TAG, "Connecting to " + mComponentName);
+ disconnect();
+ Bundle rootHints = new Bundle();
+ rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
+ mMediaBrowser = new MediaBrowser(mContext,
+ mComponentName,
+ mConnectionCallback,
+ rootHints);
mMediaBrowser.connect();
}
@@ -94,20 +98,22 @@ public class QSMediaBrowser {
} else {
Log.e(TAG, "Child found but not playable for " + mComponentName);
}
- mMediaBrowser.disconnect();
+ disconnect();
}
@Override
public void onError(String parentId) {
Log.e(TAG, "Subscribe error for " + mComponentName + ": " + parentId);
- mMediaBrowser.disconnect();
+ mCallback.onError();
+ disconnect();
}
@Override
public void onError(String parentId, Bundle options) {
Log.e(TAG, "Subscribe error for " + mComponentName + ": " + parentId
+ ", options: " + options);
- mMediaBrowser.disconnect();
+ mCallback.onError();
+ disconnect();
}
};
@@ -134,6 +140,8 @@ public class QSMediaBrowser {
@Override
public void onConnectionSuspended() {
Log.d(TAG, "Connection suspended for " + mComponentName);
+ mCallback.onError();
+ disconnect();
}
/**
@@ -143,16 +151,28 @@ public class QSMediaBrowser {
public void onConnectionFailed() {
Log.e(TAG, "Connection failed for " + mComponentName);
mCallback.onError();
+ disconnect();
}
};
/**
- * Connects to the MediaBrowserService and starts playback
+ * Disconnect the media browser. This should be called after restart or testConnection have
+ * completed to close the connection.
*/
- public void restart() {
- if (mMediaBrowser.isConnected()) {
+ public void disconnect() {
+ if (mMediaBrowser != null) {
mMediaBrowser.disconnect();
}
+ mMediaBrowser = null;
+ }
+
+ /**
+ * Connects to the MediaBrowserService and starts playback. QSMediaBrowser.Callback#onError or
+ * QSMediaBrowser.Callback#onConnected will be called depending on whether it was successful.
+ * QSMediaBrowser#disconnect should be called after this to ensure the connection is closed.
+ */
+ public void restart() {
+ disconnect();
Bundle rootHints = new Bundle();
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
mMediaBrowser = new MediaBrowser(mContext, mComponentName,
@@ -165,6 +185,17 @@ public class QSMediaBrowser {
controller.getTransportControls();
controller.getTransportControls().prepare();
controller.getTransportControls().play();
+ mCallback.onConnected();
+ }
+
+ @Override
+ public void onConnectionFailed() {
+ mCallback.onError();
+ }
+
+ @Override
+ public void onConnectionSuspended() {
+ mCallback.onError();
}
}, rootHints);
mMediaBrowser.connect();
@@ -192,42 +223,44 @@ public class QSMediaBrowser {
}
/**
- * Used to test if SystemUI is allowed to connect to the given component as a MediaBrowser
- * @param mContext the context
- * @param callback methods onConnected or onError will be called to indicate whether the
- * connection was successful or not
- * @param mComponentName Component name of the MediaBrowserService this browser will connect to
+ * Used to test if SystemUI is allowed to connect to the given component as a MediaBrowser.
+ * QSMediaBrowser.Callback#onError or QSMediaBrowser.Callback#onConnected will be called
+ * depending on whether it was successful.
+ * QSMediaBrowser#disconnect should be called after this to ensure the connection is closed.
*/
- public static MediaBrowser testConnection(Context mContext, Callback callback,
- ComponentName mComponentName) {
- final MediaBrowser.ConnectionCallback mConnectionCallback =
+ public void testConnection() {
+ disconnect();
+ final MediaBrowser.ConnectionCallback connectionCallback =
new MediaBrowser.ConnectionCallback() {
@Override
public void onConnected() {
Log.d(TAG, "connected");
- callback.onConnected();
+ if (mMediaBrowser.getRoot() == null) {
+ mCallback.onError();
+ } else {
+ mCallback.onConnected();
+ }
}
@Override
public void onConnectionSuspended() {
Log.d(TAG, "suspended");
- callback.onError();
+ mCallback.onError();
}
@Override
public void onConnectionFailed() {
Log.d(TAG, "failed");
- callback.onError();
+ mCallback.onError();
}
};
Bundle rootHints = new Bundle();
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
- MediaBrowser browser = new MediaBrowser(mContext,
+ mMediaBrowser = new MediaBrowser(mContext,
mComponentName,
- mConnectionCallback,
+ connectionCallback,
rootHints);
- browser.connect();
- return browser;
+ mMediaBrowser.connect();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a3004bdc004d..e8f6c9668e9b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -270,27 +270,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
return;
}
- QSMediaPlayer player = null;
String packageName = notif.getPackageName();
- for (QSMediaPlayer p : mMediaPlayers) {
- if (p.getKey() == null) {
- // No notification key = loaded via mediabrowser, so just match on package
- if (packageName.equals(p.getMediaPlayerPackage())) {
- Log.d(TAG, "Found matching resume player by package: " + packageName);
- player = p;
- break;
- }
- } else if (p.getMediaSessionToken().equals(token)) {
- Log.d(TAG, "Found matching player by token " + packageName);
- player = p;
- break;
- } else if (packageName.equals(p.getMediaPlayerPackage()) && key.equals(p.getKey())) {
- // Also match if it's the same package and notification key
- Log.d(TAG, "Found matching player by package " + packageName + ", " + key);
- player = p;
- break;
- }
- }
+ QSMediaPlayer player = findMediaPlayer(packageName, token, key);
int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
@@ -299,7 +280,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
lp.setMarginEnd(padding);
if (player == null) {
- Log.d(TAG, "creating new player");
+ Log.d(TAG, "creating new player for " + packageName);
// Set up listener for device changes
// TODO: integrate with MediaTransferManager?
InfoMediaManager imm = new InfoMediaManager(mContext, notif.getPackageName(),
@@ -331,6 +312,35 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
+ /**
+ * Check for an existing media player using the given information
+ * @param packageName
+ * @param token
+ * @param key
+ * @return a player, or null if no match found
+ */
+ private QSMediaPlayer findMediaPlayer(String packageName, MediaSession.Token token,
+ String key) {
+ for (QSMediaPlayer player : mMediaPlayers) {
+ if (player.getKey() == null || key == null) {
+ // No notification key = loaded via mediabrowser, so just match on package
+ if (packageName.equals(player.getMediaPlayerPackage())) {
+ Log.d(TAG, "Found matching resume player by package: " + packageName);
+ return player;
+ }
+ } else if (player.getMediaSessionToken().equals(token)) {
+ Log.d(TAG, "Found matching player by token " + packageName);
+ return player;
+ } else if (packageName.equals(player.getMediaPlayerPackage())
+ && key.equals(player.getKey())) {
+ // Also match if it's the same package and notification key
+ Log.d(TAG, "Found matching player by package " + packageName + ", " + key);
+ return player;
+ }
+ }
+ return null;
+ }
+
protected View getMediaPanel() {
return mMediaCarousel;
}
@@ -369,26 +379,30 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
Log.d(TAG, "adding track from browser: " + desc + ", " + component);
- QSMediaPlayer player = new QSMediaPlayer(mContext, QSPanel.this,
- null, mForegroundExecutor, mBackgroundExecutor, mActivityStarter);
+ // Check if there's an old player for this app
String pkgName = component.getPackageName();
-
- // Add controls to carousel
- int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
- int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(playerWidth,
- LayoutParams.MATCH_PARENT);
- lp.setMarginStart(padding);
- lp.setMarginEnd(padding);
- mMediaCarousel.addView(player.getView(), lp);
- ((View) mMediaCarousel.getParent()).setVisibility(View.VISIBLE);
- mMediaPlayers.add(player);
+ MediaSession.Token token = browser.getToken();
+ QSMediaPlayer player = findMediaPlayer(pkgName, token, null);
+
+ if (player == null) {
+ player = new QSMediaPlayer(mContext, QSPanel.this,
+ null, mForegroundExecutor, mBackgroundExecutor, mActivityStarter);
+
+ // Add to carousel
+ int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
+ int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(playerWidth,
+ LayoutParams.MATCH_PARENT);
+ lp.setMarginStart(padding);
+ lp.setMarginEnd(padding);
+ mMediaCarousel.addView(player.getView(), lp);
+ ((View) mMediaCarousel.getParent()).setVisibility(View.VISIBLE);
+ mMediaPlayers.add(player);
+ }
int iconColor = Color.DKGRAY;
int bgColor = Color.LTGRAY;
-
- MediaSession.Token token = browser.getToken();
player.setMediaSession(token, desc, iconColor, bgColor, browser.getAppIntent(),
pkgName);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 90dc38f3ad12..b15c6a3e3b59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -138,6 +138,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
private Clock mClockView;
private DateView mDateView;
private BatteryMeterView mBatteryRemainingIcon;
+ private RingerModeTracker mRingerModeTracker;
// Used for RingerModeTracker
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
@@ -159,10 +160,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
mCommandQueue = commandQueue;
- ringerModeTracker.getRingerModeInternal().observe(this, ringer -> {
- mRingerMode = ringer;
- updateStatusText();
- });
+ mRingerModeTracker = ringerModeTracker;
}
@Override
@@ -429,6 +427,10 @@ public class QuickStatusBarHeader extends RelativeLayout implements
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
+ mRingerModeTracker.getRingerModeInternal().observe(this, ringer -> {
+ mRingerMode = ringer;
+ updateStatusText();
+ });
mStatusBarIconController.addIconGroup(mIconManager);
requestApplyInsets();
}
@@ -466,6 +468,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
@VisibleForTesting
public void onDetachedFromWindow() {
setListening(false);
+ mRingerModeTracker.getRingerModeInternal().removeObservers(this);
mStatusBarIconController.removeIconGroup(mIconManager);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 1dbfa32cdf41..f55ce77060a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl;
+import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
@@ -109,6 +110,7 @@ public interface NotificationsModule {
INotificationManager notificationManager,
LauncherApps launcherApps,
ShortcutManager shortcutManager,
+ ChannelEditorDialogController channelEditorDialogController,
CurrentUserContextTracker contextTracker,
Provider<PriorityOnboardingDialogController.Builder> builderProvider) {
return new NotificationGutsManager(
@@ -121,6 +123,7 @@ public interface NotificationsModule {
notificationManager,
launcherApps,
shortcutManager,
+ channelEditorDialogController,
contextTracker,
builderProvider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index e75b70511250..b163818f68a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -22,8 +22,8 @@ import android.app.NotificationChannel
import android.app.NotificationChannel.DEFAULT_CHANNEL_ID
import android.app.NotificationChannelGroup
import android.app.NotificationManager.IMPORTANCE_NONE
+import android.app.NotificationManager.Importance
import android.content.Context
-import android.content.DialogInterface
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable
@@ -37,8 +37,10 @@ import android.view.Window
import android.view.WindowInsets.Type.statusBars
import android.view.WindowManager
import android.widget.TextView
+
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
+
import javax.inject.Inject
import javax.inject.Singleton
@@ -59,11 +61,13 @@ private const val TAG = "ChannelDialogController"
@Singleton
class ChannelEditorDialogController @Inject constructor(
c: Context,
- private val noMan: INotificationManager
+ private val noMan: INotificationManager,
+ private val dialogBuilder: ChannelEditorDialog.Builder
) {
val context: Context = c.applicationContext
- lateinit var dialog: Dialog
+ private var prepared = false
+ private lateinit var dialog: ChannelEditorDialog
private var appIcon: Drawable? = null
private var appUid: Int? = null
@@ -74,13 +78,16 @@ class ChannelEditorDialogController @Inject constructor(
// Caller should set this if they care about when we dismiss
var onFinishListener: OnChannelEditorDialogFinishedListener? = null
- // Channels handed to us from NotificationInfo
@VisibleForTesting
- internal val providedChannels = mutableListOf<NotificationChannel>()
+ internal val paddedChannels = mutableListOf<NotificationChannel>()
+ // Channels handed to us from NotificationInfo
+ private val providedChannels = mutableListOf<NotificationChannel>()
// Map from NotificationChannel to importance
private val edits = mutableMapOf<NotificationChannel, Int>()
- var appNotificationsEnabled = true
+ private var appNotificationsEnabled = true
+ // System settings for app notifications
+ private var appNotificationsCurrentlyEnabled: Boolean? = null
// Keep a mapping of NotificationChannel.getGroup() to the actual group name for display
@VisibleForTesting
@@ -106,10 +113,18 @@ class ChannelEditorDialogController @Inject constructor(
this.appNotificationsEnabled = checkAreAppNotificationsOn()
this.onSettingsClickListener = onSettingsClickListener
+ // These will always start out the same
+ appNotificationsCurrentlyEnabled = appNotificationsEnabled
+
channelGroupList.clear()
channelGroupList.addAll(fetchNotificationChannelGroups())
buildGroupNameLookup()
+ providedChannels.clear()
+ providedChannels.addAll(channels)
padToFourChannels(channels)
+ initDialog()
+
+ prepared = true
}
private fun buildGroupNameLookup() {
@@ -121,21 +136,21 @@ class ChannelEditorDialogController @Inject constructor(
}
private fun padToFourChannels(channels: Set<NotificationChannel>) {
- providedChannels.clear()
+ paddedChannels.clear()
// First, add all of the given channels
- providedChannels.addAll(channels.asSequence().take(4))
+ paddedChannels.addAll(channels.asSequence().take(4))
// Then pad to 4 if we haven't been given that many
- providedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence())
- .filterNot { providedChannels.contains(it) }
+ paddedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence())
+ .filterNot { paddedChannels.contains(it) }
.distinct()
- .take(4 - providedChannels.size))
+ .take(4 - paddedChannels.size))
// If we only got one channel and it has the default miscellaneous tag, then we actually
// are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the
// channel
- if (providedChannels.size == 1 && DEFAULT_CHANNEL_ID == providedChannels[0].id) {
- providedChannels.clear()
+ if (paddedChannels.size == 1 && DEFAULT_CHANNEL_ID == paddedChannels[0].id) {
+ paddedChannels.clear()
}
}
@@ -157,7 +172,9 @@ class ChannelEditorDialogController @Inject constructor(
}
fun show() {
- initDialog()
+ if (!prepared) {
+ throw IllegalStateException("Must call prepareDialogForApp() before calling show()")
+ }
dialog.show()
}
@@ -178,8 +195,10 @@ class ChannelEditorDialogController @Inject constructor(
appUid = null
packageName = null
appName = null
+ appNotificationsCurrentlyEnabled = null
edits.clear()
+ paddedChannels.clear()
providedChannels.clear()
groupNameLookup.clear()
}
@@ -188,12 +207,27 @@ class ChannelEditorDialogController @Inject constructor(
return groupNameLookup[groupId] ?: ""
}
- fun proposeEditForChannel(channel: NotificationChannel, edit: Int) {
+ fun proposeEditForChannel(channel: NotificationChannel, @Importance edit: Int) {
if (channel.importance == edit) {
edits.remove(channel)
} else {
edits[channel] = edit
}
+
+ dialog.updateDoneButtonText(hasChanges())
+ }
+
+ fun proposeSetAppNotificationsEnabled(enabled: Boolean) {
+ appNotificationsEnabled = enabled
+ dialog.updateDoneButtonText(hasChanges())
+ }
+
+ fun areAppNotificationsEnabled(): Boolean {
+ return appNotificationsEnabled
+ }
+
+ private fun hasChanges(): Boolean {
+ return edits.isNotEmpty() || (appNotificationsEnabled != appNotificationsCurrentlyEnabled)
}
@Suppress("unchecked_cast")
@@ -241,7 +275,7 @@ class ChannelEditorDialogController @Inject constructor(
}
}
- if (appNotificationsEnabled != checkAreAppNotificationsOn()) {
+ if (appNotificationsEnabled != appNotificationsCurrentlyEnabled) {
applyAppNotificationsOn(appNotificationsEnabled)
}
}
@@ -252,7 +286,8 @@ class ChannelEditorDialogController @Inject constructor(
}
private fun initDialog() {
- dialog = Dialog(context)
+ dialogBuilder.setContext(context)
+ dialog = dialogBuilder.build()
dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
// Prevent a11y readers from reading the first element in the dialog twice
@@ -260,16 +295,21 @@ class ChannelEditorDialogController @Inject constructor(
dialog.apply {
setContentView(R.layout.notif_half_shelf)
setCanceledOnTouchOutside(true)
- setOnDismissListener(object : DialogInterface.OnDismissListener {
- override fun onDismiss(dialog: DialogInterface?) {
- onFinishListener?.onChannelEditorDialogFinished()
- }
- })
- findViewById<ChannelEditorListView>(R.id.half_shelf_container).apply {
+ setOnDismissListener { onFinishListener?.onChannelEditorDialogFinished() }
+
+ val listView = findViewById<ChannelEditorListView>(R.id.half_shelf_container)
+ listView?.apply {
controller = this@ChannelEditorDialogController
appIcon = this@ChannelEditorDialogController.appIcon
appName = this@ChannelEditorDialogController.appName
- channels = providedChannels
+ channels = paddedChannels
+ }
+
+ setOnShowListener {
+ // play a highlight animation for the given channels
+ for (channel in providedChannels) {
+ listView?.highlightChannel(channel)
+ }
}
findViewById<TextView>(R.id.done_button)?.setOnClickListener {
@@ -306,6 +346,28 @@ class ChannelEditorDialogController @Inject constructor(
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
}
+class ChannelEditorDialog(context: Context) : Dialog(context) {
+ fun updateDoneButtonText(hasChanges: Boolean) {
+ findViewById<TextView>(R.id.done_button)?.setText(
+ if (hasChanges)
+ R.string.inline_ok_button
+ else
+ R.string.inline_done_button)
+ }
+
+ class Builder @Inject constructor() {
+ private lateinit var context: Context
+ fun setContext(context: Context): Builder {
+ this.context = context
+ return this
+ }
+
+ fun build(): ChannelEditorDialog {
+ return ChannelEditorDialog(context)
+ }
+ }
+}
+
interface OnChannelEditorDialogFinishedListener {
fun onChannelEditorDialogFinished()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
index 983315ed98e7..38a1579222b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row
+import android.animation.ArgbEvaluator
+import android.animation.ValueAnimator
import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_NONE
@@ -33,8 +35,10 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.TextView
+import com.android.settingslib.Utils
import com.android.systemui.R
+import com.android.systemui.util.Assert
/**
* Half-shelf for notification channel controls
@@ -51,6 +55,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a
// The first row is for the entire app
private lateinit var appControlRow: AppControlView
+ private val channelRows = mutableListOf<ChannelRow>()
override fun onFinishInflate() {
super.onFinishInflate()
@@ -58,8 +63,21 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a
appControlRow = findViewById(R.id.app_control)
}
+ /**
+ * Play a highlight animation for the given channel (it really should exist but this will just
+ * fail silently if it doesn't)
+ */
+ fun highlightChannel(channel: NotificationChannel) {
+ Assert.isMainThread()
+ for (row in channelRows) {
+ if (row.channel == channel) {
+ row.playHighlight()
+ }
+ }
+ }
+
private fun updateRows() {
- val enabled = controller.appNotificationsEnabled
+ val enabled = controller.areAppNotificationsEnabled()
val transition = AutoTransition()
transition.duration = 200
@@ -83,13 +101,10 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a
TransitionManager.beginDelayedTransition(this, transition)
// Remove any rows
- val n = childCount
- for (i in n.downTo(0)) {
- val child = getChildAt(i)
- if (child is ChannelRow) {
- removeView(child)
- }
+ for (row in channelRows) {
+ removeView(row)
}
+ channelRows.clear()
updateAppControlRow(enabled)
@@ -105,6 +120,8 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a
val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow
row.controller = controller
row.channel = channel
+
+ channelRows.add(row)
addView(row)
}
@@ -114,7 +131,7 @@ class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, a
.getString(R.string.notification_channel_dialog_title, appName)
appControlRow.switch.isChecked = enabled
appControlRow.switch.setOnCheckedChangeListener { _, b ->
- controller.appNotificationsEnabled = b
+ controller.proposeSetAppNotificationsEnabled(b)
updateRows()
}
}
@@ -140,8 +157,14 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
private lateinit var channelName: TextView
private lateinit var channelDescription: TextView
private lateinit var switch: Switch
+ private val highlightColor: Int
var gentle = false
+ init {
+ highlightColor = Utils.getColorAttrDefaultColor(
+ context, android.R.attr.colorControlHighlight)
+ }
+
var channel: NotificationChannel? = null
set(newValue) {
field = newValue
@@ -150,6 +173,7 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
}
override fun onFinishInflate() {
+ super.onFinishInflate()
channelName = findViewById(R.id.channel_name)
channelDescription = findViewById(R.id.channel_description)
switch = findViewById(R.id.toggle)
@@ -161,6 +185,22 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
setOnClickListener { switch.toggle() }
}
+ /**
+ * Play an animation that highlights this row
+ */
+ fun playHighlight() {
+ // Use 0 for the start value because our background is given to us by our parent
+ val fadeInLoop = ValueAnimator.ofObject(ArgbEvaluator(), 0, highlightColor)
+ fadeInLoop.duration = 200L
+ fadeInLoop.addUpdateListener { animator ->
+ setBackgroundColor(animator.animatedValue as Int)
+ }
+ fadeInLoop.repeatMode = ValueAnimator.REVERSE
+ // Repeat an odd number of times to we end up normal
+ fadeInLoop.repeatCount = 5
+ fadeInLoop.start()
+ }
+
private fun updateViews() {
val nc = channel ?: return
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 75affdf20364..3f7c7ca799d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -87,6 +87,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
private final VisualStabilityManager mVisualStabilityManager;
private final AccessibilityManager mAccessibilityManager;
private final HighPriorityProvider mHighPriorityProvider;
+ private final ChannelEditorDialogController mChannelEditorDialogController;
// Dependencies:
private final NotificationLockscreenUserManager mLockscreenUserManager =
@@ -127,6 +128,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
INotificationManager notificationManager,
LauncherApps launcherApps,
ShortcutManager shortcutManager,
+ ChannelEditorDialogController channelEditorDialogController,
CurrentUserContextTracker contextTracker,
Provider<PriorityOnboardingDialogController.Builder> builderProvider) {
mContext = context;
@@ -140,6 +142,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mShortcutManager = shortcutManager;
mContextTracker = contextTracker;
mBuilderProvider = builderProvider;
+ mChannelEditorDialogController = channelEditorDialogController;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -348,6 +351,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
pmUser,
mNotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
packageName,
row.getEntry().getChannel(),
row.getUniqueChannels(),
@@ -390,6 +394,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
notificationInfoView.bindNotification(
pmUser,
mNotificationManager,
+ mChannelEditorDialogController,
packageName,
row.getEntry().getChannel(),
row.getUniqueChannels(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 12aa4dfaf6fa..08affa868073 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -174,6 +174,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
PackageManager pm,
INotificationManager iNotificationManager,
VisualStabilityManager visualStabilityManager,
+ ChannelEditorDialogController channelEditorDialogController,
String pkg,
NotificationChannel notificationChannel,
Set<NotificationChannel> uniqueChannelsInRow,
@@ -187,7 +188,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
mVisualStabilityManager = visualStabilityManager;
- mChannelEditorDialogController = Dependency.get(ChannelEditorDialogController.class);
+ mChannelEditorDialogController = channelEditorDialogController;
mPackageName = pkg;
mUniqueChannelsInRow = uniqueChannelsInRow;
mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
index 2189b872da43..cc5de6529358 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
@@ -17,10 +17,6 @@
package com.android.systemui.statusbar.notification.row;
import static android.app.Notification.EXTRA_IS_GROUP_CONVERSATION;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-
-import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -39,10 +35,6 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
-import android.transition.ChangeBounds;
-import android.transition.Fade;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -51,7 +43,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -108,6 +99,7 @@ public class PartialConversationInfo extends LinearLayout implements
public void bindNotification(
PackageManager pm,
INotificationManager iNotificationManager,
+ ChannelEditorDialogController channelEditorDialogController,
String pkg,
NotificationChannel notificationChannel,
Set<NotificationChannel> uniqueChannelsInRow,
@@ -127,7 +119,7 @@ public class PartialConversationInfo extends LinearLayout implements
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
mIsNonBlockable = isNonBlockable;
- mChannelEditorDialogController = Dependency.get(ChannelEditorDialogController.class);
+ mChannelEditorDialogController = channelEditorDialogController;
mUniqueChannelsInRow = uniqueChannelsInRow;
bindHeader();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 6061b1e73d1c..06b7d1a34b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -39,6 +39,7 @@ import android.util.Log;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -71,20 +72,38 @@ public class NavigationModeController implements Dumpable {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_OVERLAY_CHANGED");
+ }
+ updateCurrentInteractionMode(true /* notify */);
+ }
+ };
+
+ private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedCallback =
+ new DeviceProvisionedController.DeviceProvisionedListener() {
+ @Override
+ public void onUserSwitched() {
if (DEBUG) {
- Log.d(TAG, "ACTION_OVERLAY_CHANGED");
+ Log.d(TAG, "onUserSwitched: "
+ + ActivityManagerWrapper.getInstance().getCurrentUserId());
}
+
+ // Update the nav mode for the current user
updateCurrentInteractionMode(true /* notify */);
- }
- };
+ }
+ };
+
@Inject
- public NavigationModeController(Context context, @UiBackground Executor uiBgExecutor) {
+ public NavigationModeController(Context context,
+ DeviceProvisionedController deviceProvisionedController,
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mCurrentUserContext = context;
mOverlayManager = IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE));
mUiBgExecutor = uiBgExecutor;
+ deviceProvisionedController.addCallback(mDeviceProvisionedCallback);
IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
overlayFilter.addDataScheme("package");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 45e47f1f763f..f8da03a49b50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -46,6 +46,8 @@ public class KeyguardUserSwitcher {
private static final String TAG = "KeyguardUserSwitcher";
private static final boolean ALWAYS_ON = false;
+ private static final float USER_SWITCH_ENABLED_ALPHA = 1.0f;
+ private static final float USER_SWITCH_DISABLED_ALPHA = 0.38f;
private final Container mUserSwitcherContainer;
private final KeyguardStatusBarView mStatusBarView;
@@ -293,6 +295,9 @@ public class KeyguardUserSwitcher {
mCurrentUserView = convertView;
}
convertView.setTag(item);
+ convertView.setAlpha(
+ item.isCurrent || item.isSwitchToEnabled ? USER_SWITCH_ENABLED_ALPHA
+ : USER_SWITCH_DISABLED_ALPHA);
return convertView;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
index 8b81a7a29f84..64d025628754 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
@@ -36,12 +36,14 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.runner.RunWith
import org.junit.Test
+import org.mockito.Answers
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -59,11 +61,16 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
@Mock
private lateinit var mockNoMan: INotificationManager
+ @Mock(answer = Answers.RETURNS_SELF)
+ private lateinit var dialogBuilder: ChannelEditorDialog.Builder
+ @Mock
+ private lateinit var dialog: ChannelEditorDialog
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- controller = ChannelEditorDialogController(mContext, mockNoMan)
+ `when`(dialogBuilder.build()).thenReturn(dialog)
+ controller = ChannelEditorDialogController(mContext, mockNoMan, dialogBuilder)
channel1 = NotificationChannel(TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT)
channel2 = NotificationChannel(TEST_CHANNEL2, TEST_CHANNEL_NAME2, IMPORTANCE_DEFAULT)
@@ -86,7 +93,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
setOf(channel1, channel2), appIcon, clickListener)
- assertEquals(2, controller.providedChannels.size)
+ assertEquals(2, controller.paddedChannels.size)
}
@Test
@@ -97,7 +104,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
setOf(channelDefault), appIcon, clickListener)
assertEquals("No channels should be shown when there is only the miscellaneous channel",
- 0, controller.providedChannels.size)
+ 0, controller.paddedChannels.size)
}
@Test
@@ -119,7 +126,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
setOf(channel1), appIcon, clickListener)
assertEquals("ChannelEditorDialog should fetch enough channels to show 4",
- 4, controller.providedChannels.size)
+ 4, controller.paddedChannels.size)
}
@Test
@@ -147,7 +154,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
setOf(channel1, channel2), appIcon, clickListener)
- controller.appNotificationsEnabled = false
+ controller.proposeSetAppNotificationsEnabled(false)
controller.apply()
verify(mockNoMan, times(1)).setNotificationsEnabledForPackage(
@@ -162,7 +169,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
setOf(channel1, channel2), appIcon, clickListener)
- controller.appNotificationsEnabled = true
+ controller.proposeSetAppNotificationsEnabled(true)
controller.apply()
verify(mockNoMan, times(1)).setNotificationsEnabledForPackage(
@@ -171,12 +178,52 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
@Test
fun testSettingsClickListenerNull_noCrash() {
+ // GIVEN editor dialog
group.channels = listOf(channel1, channel2)
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
setOf(channel1, channel2), appIcon, null)
+ // WHEN user taps settings
// Pass in any old view, it should never actually be used
controller.launchSettings(View(context))
+
+ // THEN no crash
+ }
+
+ @Test
+ fun testDoneButtonSaysDone_noChanges() {
+ // GIVEN the editor dialog with no changes
+ `when`(dialogBuilder.build()).thenReturn(dialog)
+
+ group.channels = listOf(channel1, channel2)
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, null)
+
+ // WHEN the user proposes a change
+ controller.proposeEditForChannel(channel1, IMPORTANCE_NONE)
+
+ // THEN the "done" button has been updated to "apply"
+ verify(dialog).updateDoneButtonText(true /* hasChanges */)
+ }
+
+ @Test
+ fun testDoneButtonGoesBackToNormal_changeThenNoChange() {
+ val inOrderDialog = Mockito.inOrder(dialog)
+ // GIVEN the editor dialog with no changes
+ `when`(dialogBuilder.build()).thenReturn(dialog)
+
+ group.channels = listOf(channel1, channel2)
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, null)
+
+ // WHEN the user proposes a change
+ controller.proposeEditForChannel(channel1, IMPORTANCE_NONE)
+ // and WHEN the user sets the importance back to its original value
+ controller.proposeEditForChannel(channel1, channel1.importance)
+
+ // THEN the "done" button has been changed back to done
+ inOrderDialog.verify(dialog, times(1)).updateDoneButtonText(eq(true))
+ inOrderDialog.verify(dialog, times(1)).updateDoneButtonText(eq(false))
}
private val clickListener = object : NotificationInfo.OnSettingsClickListener {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 5813740712b6..eeb912e7aac8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -123,6 +123,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private INotificationManager mINotificationManager;
@Mock private LauncherApps mLauncherApps;
@Mock private ShortcutManager mShortcutManager;
+ @Mock private ChannelEditorDialogController mChannelEditorDialogController;
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
@Mock private CurrentUserContextTracker mContextTracker;
@Mock(answer = Answers.RETURNS_SELF)
@@ -144,7 +145,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
() -> mStatusBar, mHandler, mAccessibilityManager, mHighPriorityProvider,
- mINotificationManager, mLauncherApps, mShortcutManager, mContextTracker, mProvider);
+ mINotificationManager, mLauncherApps, mShortcutManager,
+ mChannelEditorDialogController, mContextTracker, mProvider);
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
mCheckSaveListener, mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
@@ -350,6 +352,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(PackageManager.class),
any(INotificationManager.class),
eq(mVisualStabilityManager),
+ eq(mChannelEditorDialogController),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
anySet(),
@@ -381,6 +384,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(PackageManager.class),
any(INotificationManager.class),
eq(mVisualStabilityManager),
+ eq(mChannelEditorDialogController),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
anySet(),
@@ -410,6 +414,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(PackageManager.class),
any(INotificationManager.class),
eq(mVisualStabilityManager),
+ eq(mChannelEditorDialogController),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
anySet(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 98ef691ee28c..8ee86a237e32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -30,17 +30,13 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.doCallRealMethod;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,13 +49,11 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
-import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
-import android.testing.PollingCheck;
import android.testing.TestableLooper;
import android.testing.UiThreadTest;
import android.view.LayoutInflater;
@@ -68,7 +62,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -120,6 +113,8 @@ public class NotificationInfoTest extends SysuiTestCase {
private PackageManager mMockPackageManager;
@Mock
private VisualStabilityManager mVisualStabilityManager;
+ @Mock
+ private ChannelEditorDialogController mChannelEditorDialogController;
@Before
public void setUp() throws Exception {
@@ -185,6 +180,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -208,6 +204,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -227,6 +224,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -257,6 +255,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -277,6 +276,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -304,6 +304,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -326,6 +327,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -345,6 +347,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mDefaultNotificationChannel,
mDefaultNotificationChannelSet,
@@ -368,6 +371,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mDefaultNotificationChannel,
mDefaultNotificationChannelSet,
@@ -387,6 +391,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -407,6 +412,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -432,6 +438,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -452,6 +459,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -473,6 +481,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -486,6 +495,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -506,6 +516,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME, mNotificationChannel,
createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT),
mEntry,
@@ -531,6 +542,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT),
@@ -552,6 +564,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT),
@@ -573,6 +586,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -596,6 +610,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -614,6 +629,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -632,6 +648,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -653,6 +670,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -677,6 +695,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -701,6 +720,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -726,6 +746,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -751,6 +772,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -782,6 +804,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -814,6 +837,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -846,6 +870,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -881,6 +906,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -915,6 +941,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -940,6 +967,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -968,6 +996,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -999,6 +1028,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -1025,6 +1055,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -1056,6 +1087,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -1080,6 +1112,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
index c390e3933d7a..1bfebfb412e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
@@ -98,6 +98,8 @@ public class PartialConversationInfoTest extends SysuiTestCase {
private INotificationManager mMockINotificationManager;
@Mock
private PackageManager mMockPackageManager;
+ @Mock
+ private ChannelEditorDialogController mChannelEditorDialogController;
@Mock
private Icon mIcon;
@@ -160,6 +162,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -181,6 +184,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -207,6 +211,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -223,6 +228,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -250,6 +256,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -267,6 +274,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -291,6 +299,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -310,6 +319,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -327,6 +337,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -349,6 +360,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -365,6 +377,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
@@ -383,6 +396,7 @@ public class PartialConversationInfoTest extends SysuiTestCase {
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
+ mChannelEditorDialogController,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0bd134c8dfac..8d3515202126 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10535,12 +10535,14 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mAtmInternal.dump(
DUMP_STARTER_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
- pw.println();
- if (dumpAll) {
- pw.println("-------------------------------------------------------------------------------");
+ if (dumpPackage == null) {
+ pw.println();
+ if (dumpAll) {
+ pw.println("-------------------------------------------------------------------------------");
+ }
+ mAtmInternal.dump(
+ DUMP_CONTAINERS_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
}
- mAtmInternal.dump(
- DUMP_CONTAINERS_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
// Activities section is dumped as part of the Critical priority dump. Exclude the
// section if priority is Normal.
if (!dumpNormalPriority) {
@@ -10558,6 +10560,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
}
+ pw.println();
+ if (dumpAll) {
+ pw.println("-------------------------------------------------------------------------------");
+ }
+ mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage);
if (dumpPackage == null) {
pw.println();
if (dumpAll) {
@@ -10574,17 +10581,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpLruLocked(pw, dumpPackage);
- pw.println();
- if (dumpAll) {
- pw.println("-------------------------------------------------------------------------------");
- }
- mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage);
- pw.println();
- if (dumpAll) {
- pw.println("-------------------------------------------------------------------"
- + "------------");
- }
dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
pw.println();
if (dumpAll) {
@@ -10788,7 +10784,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("oom".equals(cmd) || "o".equals(cmd)) {
synchronized (this) {
- dumpOomLocked(fd, pw, args, opti, true);
+ dumpOomLocked(fd, pw, false, args, opti, true, dumpPackage, true);
}
} else if ("lmk".equals(cmd)) {
synchronized (this) {
@@ -10796,11 +10792,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("lru".equals(cmd)) {
synchronized (this) {
- dumpLruLocked(pw, null);
+ dumpLruLocked(pw, dumpPackage, null);
}
} else if ("permissions".equals(cmd) || "perm".equals(cmd)) {
synchronized (this) {
- dumpPermissionsLocked(fd, pw, args, opti, true, null);
+ dumpPermissionsLocked(fd, pw, args, opti, true, dumpPackage);
}
} else if ("provider".equals(cmd)) {
String[] newArgs;
@@ -10820,7 +10816,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("providers".equals(cmd) || "prov".equals(cmd)) {
synchronized (this) {
- dumpProvidersLocked(fd, pw, args, opti, true, null);
+ dumpProvidersLocked(fd, pw, args, opti, true, dumpPackage);
}
} else if ("service".equals(cmd)) {
String[] newArgs;
@@ -11106,8 +11102,9 @@ public class ActivityManagerService extends IActivityManager.Stub
" Counts of Binder Proxies held by SYSTEM");
}
- void dumpLruEntryLocked(PrintWriter pw, int index, ProcessRecord proc) {
- pw.print(" #");
+ void dumpLruEntryLocked(PrintWriter pw, int index, ProcessRecord proc, String prefix) {
+ pw.print(prefix);
+ pw.print("#");
pw.print(index);
pw.print(": ");
pw.print(ProcessList.makeOomAdjString(proc.setAdj, false));
@@ -11149,9 +11146,29 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// TODO: Move to ProcessList?
- void dumpLruLocked(PrintWriter pw, String dumpPackage) {
- pw.println("ACTIVITY MANAGER LRU PROCESSES (dumpsys activity lru)");
+ boolean dumpLruLocked(PrintWriter pw, String dumpPackage, String prefix) {
final int N = mProcessList.mLruProcesses.size();
+ final String innerPrefix;
+ if (prefix == null) {
+ pw.println("ACTIVITY MANAGER LRU PROCESSES (dumpsys activity lru)");
+ innerPrefix = " ";
+ } else {
+ boolean haveAny = false;
+ for (int i = N - 1; i >= 0; i--) {
+ final ProcessRecord r = mProcessList.mLruProcesses.get(i);
+ if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
+ continue;
+ }
+ haveAny = true;
+ break;
+ }
+ if (!haveAny) {
+ return false;
+ }
+ pw.print(prefix);
+ pw.println("Raw LRU list (dumpsys activity lru):");
+ innerPrefix = prefix + " ";
+ }
int i;
boolean first = true;
for (i = N - 1; i >= mProcessList.mLruProcessActivityStart; i--) {
@@ -11160,10 +11177,11 @@ public class ActivityManagerService extends IActivityManager.Stub
continue;
}
if (first) {
- pw.println(" Activities:");
+ pw.print(innerPrefix);
+ pw.println("Activities:");
first = false;
}
- dumpLruEntryLocked(pw, i, r);
+ dumpLruEntryLocked(pw, i, r, innerPrefix);
}
first = true;
for (; i >= mProcessList.mLruProcessServiceStart; i--) {
@@ -11172,10 +11190,11 @@ public class ActivityManagerService extends IActivityManager.Stub
continue;
}
if (first) {
- pw.println(" Services:");
+ pw.print(innerPrefix);
+ pw.println("Services:");
first = false;
}
- dumpLruEntryLocked(pw, i, r);
+ dumpLruEntryLocked(pw, i, r, innerPrefix);
}
first = true;
for (; i >= 0; i--) {
@@ -11184,11 +11203,13 @@ public class ActivityManagerService extends IActivityManager.Stub
continue;
}
if (first) {
- pw.println(" Other:");
+ pw.print(innerPrefix);
+ pw.println("Other:");
first = false;
}
- dumpLruEntryLocked(pw, i, r);
+ dumpLruEntryLocked(pw, i, r, innerPrefix);
}
+ return true;
}
// TODO: Move to ProcessList?
@@ -11200,7 +11221,7 @@ public class ActivityManagerService extends IActivityManager.Stub
pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
- if (dumpAll) {
+ if (dumpAll || dumpPackage != null) {
final int NP = mProcessList.mProcessNames.getMap().size();
for (int ip=0; ip<NP; ip++) {
SparseArray<ProcessRecord> procs = mProcessList.mProcessNames.getMap().valueAt(ip);
@@ -11267,6 +11288,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ if (dumpOomLocked(fd, pw, needSep, args, opti, dumpAll, dumpPackage, false)) {
+ needSep = true;
+ }
+
+ needSep = dumpProcessesToGc(pw, needSep, dumpPackage);
+
if (mProcessList.mActiveUids.size() > 0) {
if (dumpUids(pw, dumpPackage, dumpAppId, mProcessList.mActiveUids,
"UID states:", needSep)) {
@@ -11283,6 +11310,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ if (needSep) {
+ pw.println();
+ }
+ if (dumpLruLocked(pw, dumpPackage, " ")) {
+ needSep = true;
+ }
+
if (mProcessList.getLruSizeLocked() > 0) {
if (needSep) {
pw.println();
@@ -11387,8 +11421,6 @@ public class ActivityManagerService extends IActivityManager.Stub
"OnHold Norm", "OnHold PERS", dumpPackage);
}
- needSep = dumpProcessesToGc(pw, needSep, dumpPackage);
-
needSep = mAppErrors.dumpLocked(fd, pw, needSep, dumpPackage);
needSep = mAtmInternal.dumpForProcesses(fd, pw, dumpAll, dumpPackage, dumpAppId, needSep,
@@ -11931,10 +11963,8 @@ public class ActivityManagerService extends IActivityManager.Stub
pw.println(")");
}
- boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
- boolean needSep = false;
-
+ boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String[] args,
+ int opti, boolean dumpAll, String dumpPackage, boolean inclGc) {
if (mProcessList.getLruSizeLocked() > 0) {
if (needSep) pw.println();
needSep = true;
@@ -11965,11 +11995,11 @@ public class ActivityManagerService extends IActivityManager.Stub
- mProcessList.mLruProcessServiceStart);
pw.println("):");
dumpProcessOomList(pw, this, mProcessList.mLruProcesses, " ", "Proc", "PERS", true,
- null);
+ dumpPackage);
needSep = true;
}
- dumpProcessesToGc(pw, needSep, null);
+ dumpProcessesToGc(pw, needSep, dumpPackage);
pw.println();
mAtmInternal.dumpForOom(pw);
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 0c3d02d678bd..02fb34e73f7f 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -785,7 +785,7 @@ public final class AppExitInfoTracker {
}
void dumpHistoryProcessExitInfo(PrintWriter pw, String packageName) {
- pw.println("ACTIVITY MANAGER LRU PROCESSES (dumpsys activity exit-info)");
+ pw.println("ACTIVITY MANAGER PROCESS EXIT INFO (dumpsys activity exit-info)");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
synchronized (mLock) {
pw.println("Last Timestamp of Persistence Into Persistent Storage: "
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 76acf57db408..d007b77c3203 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -235,6 +235,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
@@ -6490,7 +6491,7 @@ public class NotificationManagerService extends SystemService {
// Log event to statsd
mNotificationRecordLogger.maybeLogNotificationPosted(r, old, position,
- buzzBeepBlinkLoggingCode);
+ buzzBeepBlinkLoggingCode, getGroupInstanceId(n.getGroupKey()));
} finally {
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
@@ -6506,6 +6507,21 @@ public class NotificationManagerService extends SystemService {
}
/**
+ *
+ */
+ @GuardedBy("mNotificationLock")
+ InstanceId getGroupInstanceId(String groupKey) {
+ if (groupKey == null) {
+ return null;
+ }
+ NotificationRecord group = mSummaryByGroupKey.get(groupKey);
+ if (group == null) {
+ return null;
+ }
+ return group.getSbn().getInstanceId();
+ }
+
+ /**
* If the notification differs enough visually, consider it a new interruptive notification.
*/
@GuardedBy("mNotificationLock")
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index eba57304124a..34e6ec18be88 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -48,10 +49,12 @@ public interface NotificationRecordLogger {
* @param old The previous NotificationRecord. Null if there was no previous record.
* @param position The position at which this notification is ranked.
* @param buzzBeepBlink Logging code reflecting whether this notification alerted the user.
+ * @param groupId The instance Id of the group summary notification, or null.
*/
void maybeLogNotificationPosted(@Nullable NotificationRecord r,
@Nullable NotificationRecord old,
- int position, int buzzBeepBlink);
+ int position, int buzzBeepBlink,
+ InstanceId groupId);
/**
* Logs a notification cancel / dismiss event using UiEventReported (event ids from the
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
index 494ff314a8aa..c6ec95a2e1d5 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.FrameworkStatsLog;
@@ -30,7 +31,8 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
@Override
public void maybeLogNotificationPosted(NotificationRecord r, NotificationRecord old,
- int position, int buzzBeepBlink) {
+ int position, int buzzBeepBlink,
+ InstanceId groupId) {
NotificationRecordPair p = new NotificationRecordPair(r, old);
if (!p.shouldLogReported(buzzBeepBlink)) {
return;
@@ -43,7 +45,7 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
/* int32 notification_id_hash = 5 */ p.getNotificationIdHash(),
/* int32 channel_id_hash = 6 */ p.getChannelIdHash(),
/* string group_id_hash = 7 */ p.getGroupIdHash(),
- /* int32 group_instance_id = 8 */ 0, // TODO generate and fill instance ids
+ /* int32 group_instance_id = 8 */ (groupId == null) ? 0 : groupId.getId(),
/* bool is_group_summary = 9 */ r.getSbn().getNotification().isGroupSummary(),
/* string category = 10 */ r.getSbn().getNotification().category,
/* int32 style = 11 */ p.getStyle(),
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9edc03eaf3c3..5df84f299509 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -803,7 +803,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
pw.println(prefix + "mLastReportedConfigurations:");
- mLastReportedConfiguration.dump(pw, prefix + " ");
+ mLastReportedConfiguration.dump(pw, prefix + " ");
pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
@@ -839,7 +839,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
- pw.print(prefix + " backgroundColor=");
+ pw.print(prefix); pw.print(" backgroundColor=");
pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
pw.print(" statusBarColor=");
pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 68c6627c3d24..d71381ea0d79 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -162,6 +162,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
/**
@@ -2802,67 +2803,91 @@ class ActivityStack extends Task {
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
- String dumpPackage, boolean needSep) {
- pw.println(" Stack #" + getRootTaskId()
- + ": type=" + activityTypeToString(getActivityType())
- + " mode=" + windowingModeToString(getWindowingMode()));
- pw.println(" isSleeping=" + shouldSleepActivities());
- pw.println(" mBounds=" + getRequestedOverrideBounds());
-
- boolean printed = dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
-
- needSep = printed;
- boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep,
- " mPausingActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- pr = printThisActivity(pw, getResumedActivity(), dumpPackage, needSep,
- " mResumedActivity: ");
- if (pr) {
+ String dumpPackage, final boolean needSep) {
+ Runnable headerPrinter = () -> {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Stack #" + getRootTaskId()
+ + ": type=" + activityTypeToString(getActivityType())
+ + " mode=" + windowingModeToString(getWindowingMode()));
+ pw.println(" isSleeping=" + shouldSleepActivities());
+ pw.println(" mBounds=" + getRequestedOverrideBounds());
+ };
+
+ boolean printed = false;
+
+ if (dumpPackage == null) {
+ // If we are not filtering by package, we want to print absolutely everything,
+ // so always print the header even if there are no tasks/activities inside.
+ headerPrinter.run();
+ headerPrinter = null;
printed = true;
- needSep = false;
}
+
+ printed |= printThisActivity(pw, mPausingActivity, dumpPackage, false,
+ " mPausingActivity: ", null);
+ printed |= printThisActivity(pw, getResumedActivity(), dumpPackage, false,
+ " mResumedActivity: ", null);
if (dumpAll) {
- pr = printThisActivity(pw, mLastPausedActivity, dumpPackage, needSep,
- " mLastPausedActivity: ");
- if (pr) {
- printed = true;
- needSep = true;
- }
+ printed |= printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
+ " mLastPausedActivity: ", null);
printed |= printThisActivity(pw, mLastNoHistoryActivity, dumpPackage,
- needSep, " mLastNoHistoryActivity: ");
+ false, " mLastNoHistoryActivity: ", null);
}
+
+ printed |= dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, false, headerPrinter);
+
return printed;
}
private boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
- boolean dumpClient, String dumpPackage, boolean needSep) {
+ boolean dumpClient, String dumpPackage, boolean needSep, Runnable header) {
if (!hasChild()) {
return false;
}
- final String prefix = " ";
+ final AtomicBoolean printedHeader = new AtomicBoolean(false);
+ final AtomicBoolean printed = new AtomicBoolean(false);
forAllLeafTasks((task) -> {
- if (needSep) {
- pw.println("");
- }
- pw.println(prefix + "Task id #" + task.mTaskId);
- pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds());
- pw.println(prefix + "mMinWidth=" + task.mMinWidth);
- pw.println(prefix + "mMinHeight=" + task.mMinHeight);
- pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
- pw.println(prefix + "* " + task);
- task.dump(pw, prefix + " ");
+ final String prefix = " ";
+ Runnable headerPrinter = () -> {
+ printed.set(true);
+ if (!printedHeader.get()) {
+ if (needSep) {
+ pw.println("");
+ }
+ if (header != null) {
+ header.run();
+ }
+ printedHeader.set(true);
+ }
+ pw.print(prefix); pw.print("* "); pw.println(task);
+ pw.print(prefix); pw.print(" mBounds=");
+ pw.println(task.getRequestedOverrideBounds());
+ pw.print(prefix); pw.print(" mMinWidth="); pw.print(task.mMinWidth);
+ pw.print(" mMinHeight="); pw.println(task.mMinHeight);
+ if (mLastNonFullscreenBounds != null) {
+ pw.print(prefix);
+ pw.print(" mLastNonFullscreenBounds=");
+ pw.println(task.mLastNonFullscreenBounds);
+ }
+ task.dump(pw, prefix + " ");
+ };
+ if (dumpPackage == null) {
+ // If we are not filtering by package, we want to print absolutely everything,
+ // so always print the header even if there are no activities inside.
+ headerPrinter.run();
+ headerPrinter = null;
+ }
final ArrayList<ActivityRecord> activities = new ArrayList<>();
// Add activities by traversing the hierarchy from bottom to top, since activities
// are dumped in reverse order in {@link ActivityStackSupervisor#dumpHistoryList()}.
task.forAllActivities((Consumer<ActivityRecord>) activities::add,
false /* traverseTopToBottom */);
dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
- dumpPackage, false, null, task);
+ dumpPackage, false, headerPrinter, task);
}, true /* traverseTopToBottom */);
- return true;
+ return printed.get();
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 03ff80ae0a21..9026b81c4f2a 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1936,12 +1936,15 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
- boolean needSep, String prefix) {
+ boolean needSep, String prefix, Runnable header) {
if (activity != null) {
if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
if (needSep) {
pw.println();
}
+ if (header != null) {
+ header.run();
+ }
pw.print(prefix);
pw.println(activity);
return true;
@@ -1952,7 +1955,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
String prefix, String label, boolean complete, boolean brief, boolean client,
- String dumpPackage, boolean needNL, String header, Task lastTask) {
+ String dumpPackage, boolean needNL, Runnable header, Task lastTask) {
String innerPrefix = null;
String[] args = null;
boolean printed = false;
@@ -1972,7 +1975,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
needNL = false;
}
if (header != null) {
- pw.println(header);
+ header.run();
header = null;
}
if (lastTask != r.getTask()) {
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 7fad395fb51d..dfa3fe088770 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -549,19 +549,28 @@ public class ActivityStartController {
return mPendingRemoteAnimationRegistry;
}
- void dump(PrintWriter pw, String prefix, String dumpPackage) {
+ void dumpLastHomeActivityStartResult(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print("mLastHomeActivityStartResult=");
pw.println(mLastHomeActivityStartResult);
+ }
+
+ void dump(PrintWriter pw, String prefix, String dumpPackage) {
+ boolean dumped = false;
+
+ final boolean dumpPackagePresent = dumpPackage != null;
- if (mLastHomeActivityStartRecord != null) {
+ if (mLastHomeActivityStartRecord != null && (!dumpPackagePresent
+ || dumpPackage.equals(mLastHomeActivityStartRecord.packageName))) {
+ if (!dumped) {
+ dumped = true;
+ dumpLastHomeActivityStartResult(pw, prefix);
+ }
pw.print(prefix);
pw.println("mLastHomeActivityStartRecord:");
mLastHomeActivityStartRecord.dump(pw, prefix + " ", true /* dumpAll */);
}
- final boolean dumpPackagePresent = dumpPackage != null;
-
if (mLastStarter != null) {
final boolean dump = !dumpPackagePresent
|| mLastStarter.relatedToPackage(dumpPackage)
@@ -569,6 +578,10 @@ public class ActivityStartController {
&& dumpPackage.equals(mLastHomeActivityStartRecord.packageName));
if (dump) {
+ if (!dumped) {
+ dumped = true;
+ dumpLastHomeActivityStartResult(pw, prefix);
+ }
pw.print(prefix);
mLastStarter.dump(pw, prefix + " ");
@@ -578,7 +591,7 @@ public class ActivityStartController {
}
}
- if (dumpPackagePresent) {
+ if (!dumped) {
pw.print(prefix);
pw.println("(nothing)");
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 511baa540d5a..6a8d5d905a00 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4926,7 +4926,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean printed = ActivityStackSupervisor.printThisActivity(pw,
mRootWindowContainer.getTopResumedActivity(), dumpPackage, needSep,
- " ResumedActivity: ");
+ " ResumedActivity: ", null);
if (printed) {
printedAnything = true;
needSep = false;
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 09700c56deba..ccd51de28c88 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1718,9 +1718,31 @@ class RecentTasks {
final int size = mTasks.size();
for (int i = 0; i < size; i++) {
final Task task = mTasks.get(i);
- if (dumpPackage != null && (task.realActivity == null ||
- !dumpPackage.equals(task.realActivity.getPackageName()))) {
- continue;
+ if (dumpPackage != null) {
+ boolean match = task.intent != null
+ && task.intent.getComponent() != null
+ && dumpPackage.equals(
+ task.intent.getComponent().getPackageName());
+ if (!match) {
+ match |= task.affinityIntent != null
+ && task.affinityIntent.getComponent() != null
+ && dumpPackage.equals(
+ task.affinityIntent.getComponent().getPackageName());
+ }
+ if (!match) {
+ match |= task.origActivity != null
+ && dumpPackage.equals(task.origActivity.getPackageName());
+ }
+ if (!match) {
+ match |= task.realActivity != null
+ && dumpPackage.equals(task.realActivity.getPackageName());
+ }
+ if (!match) {
+ match |= dumpPackage.equals(task.mCallingPackage);
+ }
+ if (!match) {
+ continue;
+ }
}
if (!printedHeader) {
@@ -1743,6 +1765,31 @@ class RecentTasks {
0, true /* getTasksAllowed */, mService.getCurrentUserId(), SYSTEM_UID);
for (int i = 0; i < tasks.size(); i++) {
final ActivityManager.RecentTaskInfo taskInfo = tasks.get(i);
+ if (dumpPackage != null) {
+ boolean match = taskInfo.baseIntent != null
+ && taskInfo.baseIntent.getComponent() != null
+ && dumpPackage.equals(
+ taskInfo.baseIntent.getComponent().getPackageName());
+ if (!match) {
+ match |= taskInfo.baseActivity != null
+ && dumpPackage.equals(taskInfo.baseActivity.getPackageName());
+ }
+ if (!match) {
+ match |= taskInfo.topActivity != null
+ && dumpPackage.equals(taskInfo.topActivity.getPackageName());
+ }
+ if (!match) {
+ match |= taskInfo.origActivity != null
+ && dumpPackage.equals(taskInfo.origActivity.getPackageName());
+ }
+ if (!match) {
+ match |= taskInfo.realActivity != null
+ && dumpPackage.equals(taskInfo.realActivity.getPackageName());
+ }
+ if (!match) {
+ continue;
+ }
+ }
if (!printedHeader) {
if (printedAnything) {
// Separate from the last block if it printed
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 77841dc2c0bf..a691736e754a 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3602,31 +3602,40 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
boolean needSep = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
DisplayContent displayContent = getChildAt(displayNdx);
+ if (printed) {
+ pw.println();
+ }
pw.print("Display #"); pw.print(displayContent.mDisplayId);
pw.println(" (activities from top to bottom):");
for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
- pw.println();
- printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
- needSep = printed;
+ if (needSep) {
+ pw.println();
+ }
+ needSep = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+ printed |= needSep;
}
}
- pw.println(" (resumed activities in task display areas from top to bottom):");
for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
- printThisActivity(pw, taskDisplayArea.getFocusedActivity(), dumpPackage, needSep,
- " ResumedActivity:");
+ printed |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(),
+ dumpPackage, needSep, " Resumed: ", () -> {
+ pw.println(" Resumed activities in task display areas"
+ + " (from top to bottom):");
+ });
}
}
printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
"Fin", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to finish:", null);
+ false, dumpPackage, true,
+ () -> { pw.println(" Activities waiting to finish:"); }, null);
printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ",
"Stop", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to stop:", null);
+ false, dumpPackage, true,
+ () -> { pw.println(" Activities waiting to stop:"); }, null);
return printed;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 8f8ca7707eb5..6c872a6319d7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3875,11 +3875,12 @@ class Task extends WindowContainer<WindowContainer> {
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
- pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible());
- pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
- pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
- pw.print(" isResizeable=" + isResizeable());
- pw.print(" lastActiveTime=" + lastActiveTime);
+ pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
+ pw.print(prefix); pw.print("mResizeMode=");
+ pw.print(ActivityInfo.resizeModeToString(mResizeMode));
+ pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
+ pw.print(" isResizeable="); pw.println(isResizeable());
+ pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d5ecfeb55e95..e644f64cf307 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1772,6 +1772,28 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testGroupInstanceIds() throws Exception {
+ final NotificationRecord group1 = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group1", true);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
+ group1.getSbn().getId(), group1.getSbn().getNotification(),
+ group1.getSbn().getUserId());
+ waitForIdle();
+
+ // same group, child, should be returned
+ final NotificationRecord group1Child = generateNotificationRecord(
+ mTestNotificationChannel, 2, "group1", false);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
+ group1Child.getSbn().getId(),
+ group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
+ waitForIdle();
+
+ assertEquals(2, mNotificationRecordLogger.numCalls());
+ assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
+ mNotificationRecordLogger.get(1).groupInstanceId.getId());
+ }
+
+ @Test
public void testFindGroupNotificationsLocked() throws Exception {
// make sure the same notification can be found in both lists and returned
final NotificationRecord group1 = generateNotificationRecord(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
index 6b18cc64c5fb..64fd19e69009 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import java.util.ArrayList;
@@ -32,14 +33,16 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger {
static final int INVALID = -1;
public int position = INVALID, buzzBeepBlink = INVALID;
public boolean wasLogged;
+ public InstanceId groupInstanceId;
CallRecord(NotificationRecord r, NotificationRecord old, int position,
- int buzzBeepBlink) {
+ int buzzBeepBlink, InstanceId groupId) {
super(r, old);
this.position = position;
this.buzzBeepBlink = buzzBeepBlink;
wasLogged = shouldLogReported(buzzBeepBlink);
event = wasLogged ? NotificationReportedEvent.fromRecordPair(this) : null;
+ groupInstanceId = groupId;
}
CallRecord(NotificationRecord r, UiEventLogger.UiEventEnum event) {
@@ -67,8 +70,8 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger {
@Override
public void maybeLogNotificationPosted(NotificationRecord r, NotificationRecord old,
- int position, int buzzBeepBlink) {
- mCalls.add(new CallRecord(r, old, position, buzzBeepBlink));
+ int position, int buzzBeepBlink, InstanceId groupId) {
+ mCalls.add(new CallRecord(r, old, position, buzzBeepBlink, groupId));
}
@Override