Merge "Make Markup fade in from screenshots" into sc-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5fa75dd..0bb12c8 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1113,6 +1113,10 @@
method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String);
}
+ public abstract class CameraMetadata<TKey> {
+ field public static final int SENSOR_TEST_PATTERN_MODE_BLACK = 5; // 0x5
+ }
+
}
package android.hardware.devicestate {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 854c9f2..db5dcc5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3866,9 +3866,26 @@
}
/**
- * Called when the activity has detected the user's press of the back
- * key. The default implementation simply finishes the current activity,
- * but you can override this to do whatever you want.
+ * Called when the activity has detected the user's press of the back key. The default
+ * implementation depends on the platform version:
+ *
+ * <ul>
+ * <li>On platform versions prior to {@link android.os.Build.VERSION_CODES#S}, it
+ * finishes the current activity, but you can override this to do whatever you want.
+ *
+ * <li><p>Starting with platform version {@link android.os.Build.VERSION_CODES#S}, for
+ * activities that are the root activity of the task and also declare an
+ * {@link android.content.IntentFilter} with {@link Intent#ACTION_MAIN} and
+ * {@link Intent#CATEGORY_LAUNCHER} in the manifest, the current activity and its
+ * task will be moved to the back of the activity stack instead of being finished.
+ * Other activities will simply be finished.
+ *
+ * <p>If you target version {@link android.os.Build.VERSION_CODES#S} or later and
+ * override this method, it is strongly recommended to call through to the superclass
+ * implementation after you finish handling navigation within the app.
+ * </ul>
+ *
+ * @see #moveTaskToBack(boolean)
*/
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index d4da3b9..9501994 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -17,6 +17,7 @@
package android.hardware.camera2;
import android.annotation.NonNull;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
@@ -2922,10 +2923,10 @@
* respective color channel provided in
* {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}.</p>
* <p>For example:</p>
- * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
+ * <pre><code>{@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData} = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All green pixels are 100% green. All red/blue pixels are black.</p>
- * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
+ * <pre><code>{@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData} = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All red pixels are 100% red. Only the odd green pixels
* are 100% green. All blue pixels are 100% black.</p>
@@ -3002,6 +3003,20 @@
public static final int SENSOR_TEST_PATTERN_MODE_PN9 = 4;
/**
+ * <p>All pixel data is replaced by 0% intensity (black) values.</p>
+ * <p>This test pattern is identical to SOLID_COLOR with a value of <code>[0, 0, 0, 0]</code> for
+ * {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}. It is recommended that devices implement full
+ * SOLID_COLOR support instead, but BLACK can be used to provide minimal support for a
+ * test pattern suitable for privacy use cases.</p>
+ *
+ * @see CaptureRequest#SENSOR_TEST_PATTERN_DATA
+ * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
+ * @hide
+ */
+ @TestApi
+ public static final int SENSOR_TEST_PATTERN_MODE_BLACK = 5;
+
+ /**
* <p>The first custom test pattern. All custom patterns that are
* available only on this camera device are at least this numeric
* value.</p>
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 8912997..a1f7aa1 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -53,7 +53,8 @@
|| pickupGestureEnabled(user)
|| tapGestureEnabled(user)
|| doubleTapGestureEnabled(user)
- || quickPickupSensorEnabled(user);
+ || quickPickupSensorEnabled(user)
+ || screenOffUdfpsEnabled(user);
}
/** {@hide} */
@@ -106,6 +107,12 @@
}
/** {@hide} */
+ public boolean screenOffUdfpsEnabled(int user) {
+ return !TextUtils.isEmpty(udfpsLongPressSensorType())
+ && boolSettingDefaultOff("screen_off_udfps_enabled", user);
+ }
+
+ /** {@hide} */
public boolean wakeScreenGestureAvailable() {
return mContext.getResources()
.getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING
index 97e03e9..55b1f940 100644
--- a/core/java/android/os/TEST_MAPPING
+++ b/core/java/android/os/TEST_MAPPING
@@ -40,7 +40,12 @@
]
},
{
- "file_patterns": ["BatteryStats.java"],
+ "file_patterns": [
+ "BatteryStats[^/]*\\.java",
+ "BatteryUsageStats[^/]*\\.java",
+ "PowerComponents\\.java",
+ "[^/]*BatteryConsumer[^/]*\\.java"
+ ],
"name": "FrameworksCoreTests",
"options": [
{ "include-filter": "com.android.internal.os.BatteryStatsTests" },
@@ -48,13 +53,26 @@
]
},
{
- "file_patterns": ["BatteryStats.java"],
+ "file_patterns": [
+ "BatteryStats[^/]*\\.java",
+ "BatteryUsageStats[^/]*\\.java",
+ "PowerComponents\\.java",
+ "[^/]*BatteryConsumer[^/]*\\.java"
+ ],
"name": "FrameworksServicesTests",
"options": [
{ "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
{ "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" },
{ "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
]
+ },
+ {
+ "file_patterns": [
+ "BatteryUsageStats[^/]*\\.java",
+ "PowerComponents\\.java",
+ "[^/]*BatteryConsumer[^/]*\\.java"
+ ],
+ "name": "BatteryUsageStatsProtoTests"
}
],
"postsubmit": [
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 055e71f..8b4c0d9 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -229,6 +229,7 @@
protected abstract void onStopListening(Callback listener);
@Override
+ @SuppressLint("MissingNullability")
public Context createContext(@NonNull ContextParams contextParams) {
if (contextParams.getNextAttributionSource() != null) {
if (mHandler.getLooper().equals(Looper.myLooper())) {
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index ac45541..1b1dc4a 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -25,8 +25,12 @@
import android.graphics.Insets;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.SpannableString;
import android.util.Log;
import android.view.autofill.AutofillId;
+import android.view.inputmethod.BaseInputConnection;
import com.android.internal.util.Preconditions;
@@ -132,6 +136,9 @@
@Retention(RetentionPolicy.SOURCE)
public @interface EventType{}
+ /** @hide */
+ public static final int MAX_INVALID_VALUE = -1;
+
private final int mSessionId;
private final int mType;
private final long mEventTime;
@@ -143,6 +150,11 @@
private @Nullable ContentCaptureContext mClientContext;
private @Nullable Insets mInsets;
+ private int mComposingStart = MAX_INVALID_VALUE;
+ private int mComposingEnd = MAX_INVALID_VALUE;
+ private int mSelectionStartIndex = MAX_INVALID_VALUE;
+ private int mSelectionEndIndex = MAX_INVALID_VALUE;
+
/** Only used in the main Content Capture session, no need to parcel */
private boolean mTextHasComposingSpan;
@@ -246,19 +258,75 @@
/** @hide */
@NonNull
- public ContentCaptureEvent setText(@Nullable CharSequence text, boolean hasComposingSpan) {
+ public ContentCaptureEvent setText(@Nullable CharSequence text) {
mText = text;
- mTextHasComposingSpan = hasComposingSpan;
return this;
}
- /**
- * The value is not parcelled, become false after parcelled.
- * @hide
- */
+ /** @hide */
@NonNull
- public boolean getTextHasComposingSpan() {
- return mTextHasComposingSpan;
+ public ContentCaptureEvent setComposingIndex(int start, int end) {
+ mComposingStart = start;
+ mComposingEnd = end;
+ return this;
+ }
+
+ /** @hide */
+ @NonNull
+ public boolean hasComposingSpan() {
+ return mComposingStart > MAX_INVALID_VALUE;
+ }
+
+ /** @hide */
+ @NonNull
+ public ContentCaptureEvent setSelectionIndex(int start, int end) {
+ mSelectionStartIndex = start;
+ mSelectionEndIndex = end;
+ return this;
+ }
+
+ private int getComposingStart() {
+ return mComposingStart;
+ }
+
+ private int getComposingEnd() {
+ return mComposingEnd;
+ }
+
+ private int getSelectionStart() {
+ return mSelectionStartIndex;
+ }
+
+ private int getSelectionEnd() {
+ return mSelectionEndIndex;
+ }
+
+ private void restoreComposingSpan() {
+ if (mComposingStart <= MAX_INVALID_VALUE
+ || mComposingEnd <= MAX_INVALID_VALUE) {
+ return;
+ }
+ if (mText instanceof Spannable) {
+ BaseInputConnection.setComposingSpans((Spannable) mText, mComposingStart,
+ mComposingEnd);
+ } else {
+ Log.w(TAG, "Text is not a Spannable.");
+ }
+ }
+
+ private void restoreSelectionSpans() {
+ if (mSelectionStartIndex <= MAX_INVALID_VALUE
+ || mSelectionEndIndex <= MAX_INVALID_VALUE) {
+ return;
+ }
+
+ if (mText instanceof SpannableString) {
+ SpannableString ss = (SpannableString) mText;
+ ss.setSpan(Selection.SELECTION_START, mSelectionStartIndex, mSelectionStartIndex, 0);
+ ss.setSpan(Selection.SELECTION_END, mSelectionEndIndex, mSelectionEndIndex, 0);
+ } else {
+ Log.w(TAG, "Text is not a SpannableString.");
+ }
}
/** @hide */
@@ -374,7 +442,9 @@
throw new IllegalArgumentException("mergeEvent(): got "
+ "TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
} else if (eventType == TYPE_VIEW_TEXT_CHANGED) {
- setText(event.getText(), event.getTextHasComposingSpan());
+ setText(event.getText());
+ setComposingIndex(event.getComposingStart(), event.getComposingEnd());
+ setSelectionIndex(event.getSelectionStart(), event.getSelectionEnd());
} else {
Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType)
+ ") does not support this event type.");
@@ -409,6 +479,14 @@
if (mInsets != null) {
pw.print(", insets="); pw.println(mInsets);
}
+ if (mComposingStart > MAX_INVALID_VALUE) {
+ pw.print(", composing("); pw.print(mComposingStart);
+ pw.print(", "); pw.print(mComposingEnd); pw.print(")");
+ }
+ if (mSelectionStartIndex > MAX_INVALID_VALUE) {
+ pw.print(", selection("); pw.print(mSelectionStartIndex);
+ pw.print(", "); pw.print(mSelectionEndIndex); pw.print(")");
+ }
}
@NonNull
@@ -443,6 +521,12 @@
if (mInsets != null) {
string.append(", insets=").append(mInsets);
}
+ if (mComposingStart > MAX_INVALID_VALUE) {
+ string.append(", hasComposing");
+ }
+ if (mSelectionStartIndex > MAX_INVALID_VALUE) {
+ string.append(", hasSelection");
+ }
return string.append(']').toString();
}
@@ -469,6 +553,12 @@
if (mType == TYPE_VIEW_INSETS_CHANGED) {
parcel.writeParcelable(mInsets, flags);
}
+ if (mType == TYPE_VIEW_TEXT_CHANGED) {
+ parcel.writeInt(mComposingStart);
+ parcel.writeInt(mComposingEnd);
+ parcel.writeInt(mSelectionStartIndex);
+ parcel.writeInt(mSelectionEndIndex);
+ }
}
public static final @android.annotation.NonNull Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -493,7 +583,7 @@
if (node != null) {
event.setViewNode(node);
}
- event.setText(parcel.readCharSequence(), false);
+ event.setText(parcel.readCharSequence());
if (type == TYPE_SESSION_STARTED || type == TYPE_SESSION_FINISHED) {
event.setParentSessionId(parcel.readInt());
}
@@ -503,6 +593,12 @@
if (type == TYPE_VIEW_INSETS_CHANGED) {
event.setInsets(parcel.readParcelable(null));
}
+ if (type == TYPE_VIEW_TEXT_CHANGED) {
+ event.setComposingIndex(parcel.readInt(), parcel.readInt());
+ event.restoreComposingSpan();
+ event.setSelectionIndex(parcel.readInt(), parcel.readInt());
+ event.restoreSelectionSpans();
+ }
return event;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index aee540f..d8ac779 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -43,6 +43,7 @@
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.RemoteException;
+import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
@@ -347,8 +348,8 @@
// 2.2 last event doesn't have composing span: add.
// Otherwise, merge.
final CharSequence text = event.getText();
- final boolean textHasComposingSpan = event.getTextHasComposingSpan();
- if (textHasComposingSpan) {
+ final boolean hasComposingSpan = event.hasComposingSpan();
+ if (hasComposingSpan) {
ContentCaptureEvent lastEvent = null;
for (int index = mEvents.size() - 1; index >= 0; index--) {
final ContentCaptureEvent tmpEvent = mEvents.get(index);
@@ -357,7 +358,7 @@
break;
}
}
- if (lastEvent != null && lastEvent.getTextHasComposingSpan()) {
+ if (lastEvent != null && lastEvent.hasComposingSpan()) {
final CharSequence lastText = lastEvent.getText();
final boolean bothNonEmpty = !TextUtils.isEmpty(lastText)
&& !TextUtils.isEmpty(text);
@@ -705,12 +706,24 @@
// a copy of its content so that its value will not be changed by subsequent updates
// in the TextView.
final CharSequence eventText = stringOrSpannedStringWithoutNoCopySpans(text);
- final boolean textHasComposingSpan =
- text instanceof Spannable && BaseInputConnection.getComposingSpanStart(
- (Spannable) text) >= 0;
+
+ final int composingStart;
+ final int composingEnd;
+ if (text instanceof Spannable) {
+ composingStart = BaseInputConnection.getComposingSpanStart((Spannable) text);
+ composingEnd = BaseInputConnection.getComposingSpanEnd((Spannable) text);
+ } else {
+ composingStart = ContentCaptureEvent.MAX_INVALID_VALUE;
+ composingEnd = ContentCaptureEvent.MAX_INVALID_VALUE;
+ }
+
+ final int startIndex = Selection.getSelectionStart(text);
+ final int endIndex = Selection.getSelectionEnd(text);
mHandler.post(() -> sendEvent(
new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED)
- .setAutofillId(id).setText(eventText, textHasComposingSpan)));
+ .setAutofillId(id).setText(eventText)
+ .setComposingIndex(composingStart, composingEnd)
+ .setSelectionIndex(startIndex, endIndex)));
}
private CharSequence stringOrSpannedStringWithoutNoCopySpans(CharSequence source) {
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index 2b22f08..5a5165d 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -14,6 +14,14 @@
},
{
"file_patterns": [
+ "Battery[^/]*\\.java",
+ "Kernel[^/]*\\.java",
+ "[^/]*Power[^/]*\\.java"
+ ],
+ "name": "BatteryUsageStatsProtoTests"
+ },
+ {
+ "file_patterns": [
"BinderDeathDispatcher\\.java"
],
"name": "FrameworksCoreTests",
@@ -23,7 +31,11 @@
]
},
{
- "file_patterns": ["Battery[^/]*\\.java"],
+ "file_patterns": [
+ "Battery[^/]*\\.java",
+ "Kernel[^/]*\\.java",
+ "[^/]*Power[^/]*\\.java"
+ ],
"name": "FrameworksServicesTests",
"options": [
{ "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml
index c419e46..e4c2a34 100644
--- a/core/res/res/layout/floating_popup_menu_button.xml
+++ b/core/res/res/layout/floating_popup_menu_button.xml
@@ -51,7 +51,7 @@
android:gravity="center"
android:singleLine="true"
android:ellipsize="end"
- android:fontFamily="sans-serif-medium"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
android:textSize="@dimen/floating_toolbar_text_size"
android:textColor="?attr/floatingToolbarForegroundColor"
android:background="@null"
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index e6a25d0..f28ee46 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -236,13 +236,13 @@
@Test
public void testMergeEvent_typeViewTextChanged() {
final ContentCaptureEvent event = new ContentCaptureEvent(42, TYPE_VIEW_TEXT_CHANGED)
- .setText("test", false);
+ .setText("test");
final ContentCaptureEvent event2 = new ContentCaptureEvent(43, TYPE_VIEW_TEXT_CHANGED)
- .setText("empty", true);
+ .setText("composing").setComposingIndex(0, 1);
event.mergeEvent(event2);
assertThat(event.getText()).isEqualTo(event2.getText());
- assertThat(event.getTextHasComposingSpan()).isEqualTo(event2.getTextHasComposingSpan());
+ assertThat(event.hasComposingSpan()).isEqualTo(event2.hasComposingSpan());
}
@Test
@@ -283,18 +283,18 @@
@Test
public void testMergeEvent_differentEventTypes() {
final ContentCaptureEvent event = new ContentCaptureEvent(42, TYPE_VIEW_DISAPPEARED)
- .setText("test", false).setAutofillId(new AutofillId(1));
+ .setText("test").setAutofillId(new AutofillId(1));
final ContentCaptureEvent event2 = new ContentCaptureEvent(17, TYPE_VIEW_TEXT_CHANGED)
- .setText("empty", true).setAutofillId(new AutofillId(2));
+ .setText("composing").setAutofillId(new AutofillId(2)).setComposingIndex(0, 1);
event.mergeEvent(event2);
assertThat(event.getText()).isEqualTo("test");
- assertThat(event.getTextHasComposingSpan()).isFalse();
+ assertThat(event.hasComposingSpan()).isFalse();
assertThat(event.getId()).isEqualTo(new AutofillId(1));
event2.mergeEvent(event);
- assertThat(event2.getText()).isEqualTo("empty");
- assertThat(event2.getTextHasComposingSpan()).isTrue();
+ assertThat(event2.getText()).isEqualTo("composing");
+ assertThat(event2.hasComposingSpan()).isTrue();
assertThat(event2.getId()).isEqualTo(new AutofillId(2));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 8c8a56a..dfd878f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -368,6 +368,13 @@
return;
}
}
+ for (Bubble b : mBubbleData.getOverflowBubbles()) {
+ if (task.taskId == b.getTaskId()) {
+ promoteBubbleFromOverflow(b);
+ mBubbleData.setExpanded(true);
+ return;
+ }
+ }
}
});
@@ -815,7 +822,35 @@
setIsBubble(bubble, true /* isBubble */);
}
- @VisibleForTesting
+ /**
+ * Expands and selects the provided bubble as long as it already exists in the stack or the
+ * overflow.
+ *
+ * This is currently only used when opening a bubble via clicking on a conversation widget.
+ */
+ public void expandStackAndSelectBubble(Bubble b) {
+ if (b == null) {
+ return;
+ }
+ if (mBubbleData.hasBubbleInStackWithKey(b.getKey())) {
+ // already in the stack
+ mBubbleData.setSelectedBubble(b);
+ mBubbleData.setExpanded(true);
+ } else if (mBubbleData.hasOverflowBubbleWithKey(b.getKey())) {
+ // promote it out of the overflow
+ promoteBubbleFromOverflow(b);
+ }
+ }
+
+ /**
+ * Expands and selects a bubble based on the provided {@link BubbleEntry}. If no bubble
+ * exists for this entry, and it is able to bubble, a new bubble will be created.
+ *
+ * This is the method to use when opening a bubble via a notification or in a state where
+ * the device might not be unlocked.
+ *
+ * @param entry the entry to use for the bubble.
+ */
public void expandStackAndSelectBubble(BubbleEntry entry) {
if (mIsStatusBarShade) {
mNotifEntryToExpandOnShadeUnlock = null;
@@ -1383,6 +1418,21 @@
}
@Override
+ public void expandStackAndSelectBubble(Bubble bubble) {
+ mMainExecutor.execute(() -> {
+ BubbleController.this.expandStackAndSelectBubble(bubble);
+ });
+ }
+
+ @Override
+ @Nullable
+ public Bubble getBubbleWithShortcutId(String shortcutId) {
+ return mMainExecutor.executeBlockingForResult(() -> {
+ return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId);
+ }, Bubble.class);
+ }
+
+ @Override
public void onTaskbarChanged(Bundle b) {
mMainExecutor.execute(() -> {
BubbleController.this.onTaskbarChanged(b);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 69a741c..6f5cfd1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.LocusId;
import android.content.pm.ShortcutInfo;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -874,6 +875,34 @@
return b;
}
+ /** @return any bubble (in the stack or the overflow) that matches the provided shortcutId. */
+ @Nullable
+ Bubble getAnyBubbleWithShortcutId(String shortcutId) {
+ if (TextUtils.isEmpty(shortcutId)) {
+ return null;
+ }
+ for (int i = 0; i < mBubbles.size(); i++) {
+ Bubble bubble = mBubbles.get(i);
+ String bubbleShortcutId = bubble.getShortcutInfo() != null
+ ? bubble.getShortcutInfo().getId()
+ : bubble.getMetadataShortcutId();
+ if (shortcutId.equals(bubbleShortcutId)) {
+ return bubble;
+ }
+ }
+
+ for (int i = 0; i < mOverflowBubbles.size(); i++) {
+ Bubble bubble = mOverflowBubbles.get(i);
+ String bubbleShortcutId = bubble.getShortcutInfo() != null
+ ? bubble.getShortcutInfo().getId()
+ : bubble.getMetadataShortcutId();
+ if (shortcutId.equals(bubbleShortcutId)) {
+ return bubble;
+ }
+ }
+ return null;
+ }
+
@VisibleForTesting(visibility = PRIVATE)
@Nullable
public Bubble getBubbleInStackWithKey(String key) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 16b8150..c71f123 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -50,7 +50,6 @@
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.FrameLayout;
@@ -1018,7 +1017,10 @@
removeView(mDismissView);
}
mDismissView = new DismissView(getContext());
+ int elevation = getResources().getDimensionPixelSize(R.dimen.bubble_elevation);
+
addView(mDismissView);
+ mDismissView.setElevation(elevation);
final ContentResolver contentResolver = getContext().getContentResolver();
final int dismissRadius = Settings.Secure.getInt(
@@ -1028,6 +1030,8 @@
// MagnetizedObjects.
mMagneticTarget = new MagnetizedObject.MagneticTarget(
mDismissView.getCircle(), dismissRadius);
+
+ mBubbleContainer.bringToFront();
}
// TODO: Create ManageMenuView and move setup / animations there
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index a93ce01..c73b5ee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -118,6 +118,19 @@
*/
void expandStackAndSelectBubble(BubbleEntry entry);
+ /**
+ * Request the stack expand if needed, then select the specified Bubble as current.
+ *
+ * @param bubble the bubble to be selected
+ */
+ void expandStackAndSelectBubble(Bubble bubble);
+
+ /**
+ * @return a bubble that matches the provided shortcutId, if one exists.
+ */
+ @Nullable
+ Bubble getBubbleWithShortcutId(String shortcutId);
+
/** Called for any taskbar changes. */
void onTaskbarChanged(Bundle b);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 32553f9..841edef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -536,8 +536,9 @@
mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, callback);
}
+ final float magnetRadiusPercent = (float) mLastResizeBounds.width() / mMinSize.x / 2.f;
mPipDismissTargetHandler
- .setMagneticFieldRadiusPercent((float) mLastResizeBounds.width() / mMinSize.x);
+ .setMagneticFieldRadiusPercent(magnetRadiusPercent);
mPipUiEventLogger.log(
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
} else {
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 46e8060..ded2b06 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -210,6 +210,14 @@
}
}
+void CacheManager::performDeferredCleanup(nsecs_t cleanupOlderThanMillis) {
+ if (mGrContext) {
+ mGrContext->performDeferredCleanup(
+ std::chrono::milliseconds(cleanupOlderThanMillis),
+ /* scratchResourcesOnly */true);
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 713ea99..af82672 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -23,6 +23,7 @@
#include <SkSurface.h>
#include <utils/String8.h>
#include <vector>
+#include "utils/TimeUtils.h"
namespace android {
@@ -53,6 +54,8 @@
size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
void onFrameCompleted();
+ void performDeferredCleanup(nsecs_t cleanupOlderThanMillis);
+
private:
friend class RenderThread;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a0d93e9..8bfc2c1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -461,6 +461,7 @@
}
void CanvasContext::stopDrawing() {
+ cleanupResources();
mRenderThread.removeFrameCallback(this);
mAnimationContext->pauseAnimators();
mGenerationID++;
@@ -619,10 +620,25 @@
}
}
+ cleanupResources();
mRenderThread.cacheManager().onFrameCompleted();
return mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration);
}
+void CanvasContext::cleanupResources() {
+ auto& tracker = mJankTracker.frames();
+ auto size = tracker.size();
+ auto capacity = tracker.capacity();
+ if (size == capacity) {
+ nsecs_t nowNanos = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t frameCompleteNanos =
+ tracker[0].get(FrameInfoIndex::FrameCompleted);
+ nsecs_t frameDiffNanos = nowNanos - frameCompleteNanos;
+ nsecs_t cleanupMillis = ns2ms(std::max(frameDiffNanos, 10_s));
+ mRenderThread.cacheManager().performDeferredCleanup(cleanupMillis);
+ }
+}
+
void CanvasContext::reportMetricsWithPresentTime() {
if (mFrameMetricsReporter == nullptr) {
return;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6f90e81..4bdc251 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -312,6 +312,7 @@
bool mExpectSurfaceStats = false;
std::function<void(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback;
+ void cleanupResources();
};
} /* namespace renderthread */
diff --git a/location/java/android/location/provider/LocationProviderBase.java b/location/java/android/location/provider/LocationProviderBase.java
index eada22c..88a2479 100644
--- a/location/java/android/location/provider/LocationProviderBase.java
+++ b/location/java/android/location/provider/LocationProviderBase.java
@@ -62,6 +62,10 @@
* <p>The service should have an intent filter in place for the location provider it wishes to
* implements. Defaults for some providers are specified as constants in this class.
*
+ * <p>Location providers are identified by their UID / package name / attribution tag. Based on this
+ * identity, location providers may be given some special privileges (such as making special
+ * requests to other location providers).
+ *
* @hide
*/
@SystemApi
@@ -95,14 +99,14 @@
public static final String ACTION_FUSED_PROVIDER =
"com.android.location.service.FusedLocationProvider";
- private final String mTag;
- private final @Nullable String mAttributionTag;
- private final IBinder mBinder;
+ final String mTag;
+ final @Nullable String mAttributionTag;
+ final IBinder mBinder;
// write locked on mBinder, read lock is optional depending on atomicity requirements
- private @Nullable volatile ILocationProviderManager mManager;
- private volatile ProviderProperties mProperties;
- private volatile boolean mAllowed;
+ volatile @Nullable ILocationProviderManager mManager;
+ volatile ProviderProperties mProperties;
+ volatile boolean mAllowed;
public LocationProviderBase(@NonNull Context context, @NonNull String tag,
@NonNull ProviderProperties properties) {
diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml
deleted file mode 100644
index 7e2db63..0000000
--- a/packages/SystemUI/res/drawable/people_space_activity_card.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/people_tile_background" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml b/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml
index aa940bd..29a014a 100644
--- a/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml
+++ b/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
- <solid android:color="?android:attr/colorBackgroundFloating" />
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
<corners android:radius="40dp" />
</shape>
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
index 4f97ca4..21b177b 100644
--- a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
@@ -32,7 +32,7 @@
android:gravity="center_vertical|right"
android:height="@dimen/rounded_slider_icon_size"
android:width="@dimen/rounded_slider_icon_size"
- android:right="@dimen/rounded_slider_icon_inset">
+ android:right="@dimen/volume_slider_icon_inset">
<rotate
android:fromDegrees="-270"
android:toDegrees="-270">
diff --git a/packages/SystemUI/res/layout/people_space_activity.xml b/packages/SystemUI/res/layout/people_space_activity.xml
index fa19943..7102375 100644
--- a/packages/SystemUI/res/layout/people_space_activity.xml
+++ b/packages/SystemUI/res/layout/people_space_activity.xml
@@ -15,6 +15,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/top_level"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -41,7 +42,8 @@
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
- android:padding="24dp" />
+ android:paddingVertical="24dp"
+ android:paddingHorizontal="48dp"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
@@ -65,8 +67,8 @@
android:id="@+id/priority_header"
android:text="@string/priority_conversations"
android:layout_width="wrap_content"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/colorAccent"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
+ android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="14sp"
android:paddingStart="16dp"
android:layout_height="wrap_content"/>
@@ -92,8 +94,8 @@
android:gravity="start"
android:text="@string/recent_conversations"
android:layout_width="wrap_content"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/colorAccent"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
+ android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="14sp"
android:paddingStart="16dp"
android:layout_height="wrap_content"/>
diff --git a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml
index 232cd72..2a4a21f 100644
--- a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml
+++ b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml
@@ -55,6 +55,7 @@
android:background="@drawable/rounded_bg_full_large_radius"
android:onClick="dismissActivity"
android:text="@string/okay"
+ android:textColor="?android:attr/textColorPrimary"
android:layout_marginBottom="60dp"
android:layout_alignParentBottom="true" />
diff --git a/packages/SystemUI/res/layout/people_space_tile_view.xml b/packages/SystemUI/res/layout/people_space_tile_view.xml
index 3e90180..2a2c35d 100644
--- a/packages/SystemUI/res/layout/people_space_tile_view.xml
+++ b/packages/SystemUI/res/layout/people_space_tile_view.xml
@@ -13,7 +13,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/tile_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -21,7 +23,7 @@
<LinearLayout
android:orientation="vertical"
- android:background="@drawable/people_space_activity_card"
+ android:background="?androidprv:attr/colorSurface"
android:padding="12dp"
android:elevation="4dp"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 76a4c5f..0ccde60 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -486,6 +486,9 @@
<dimen name="volume_dialog_slider_height">116dp</dimen>
+ <!-- (volume_dialog_panel_width - rounded_slider_icon_size) / 2 -->
+ <dimen name="volume_slider_icon_inset">11dp</dimen>
+
<dimen name="volume_dialog_track_width">4dp</dimen>
<dimen name="volume_dialog_track_corner_radius">2dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3d51f23..f3a6d63 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -66,10 +66,8 @@
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
@@ -243,21 +241,14 @@
private final boolean mIsPrimaryUser;
private final boolean mIsAutomotive;
private final AuthController mAuthController;
- private final PowerManager mPowerManager;
private final StatusBarStateController mStatusBarStateController;
private int mStatusBarState;
- private boolean mDozing;
private final StatusBarStateController.StateListener mStatusBarStateControllerListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
mStatusBarState = newState;
}
-
- @Override
- public void onDozingChanged(boolean dozing) {
- mDozing = dozing;
- }
};
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
@@ -1330,19 +1321,16 @@
private final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
= new AuthenticationCallback() {
- private boolean mIsUdfpsRunningWhileDozing;
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
- cancelAodInterrupt();
}
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
- cancelAodInterrupt();
Trace.endSection();
}
@@ -1354,7 +1342,6 @@
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
- cancelAodInterrupt();
}
@Override
@@ -1365,25 +1352,12 @@
@Override
public void onUdfpsPointerDown(int sensorId) {
Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId);
-
- if (mDozing) {
- mIsUdfpsRunningWhileDozing = true;
- }
}
@Override
public void onUdfpsPointerUp(int sensorId) {
Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId);
}
-
- private void cancelAodInterrupt() {
- if (mIsUdfpsRunningWhileDozing) {
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
- "com.android.systemui:AOD_INTERRUPT_END");
- }
- mAuthController.onCancelUdfps();
- mIsUdfpsRunningWhileDozing = false;
- }
};
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
@@ -1676,7 +1650,6 @@
LockPatternUtils lockPatternUtils,
AuthController authController,
TelephonyListenerManager telephonyListenerManager,
- PowerManager powerManager,
FeatureFlags featureFlags) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
@@ -1689,10 +1662,8 @@
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
mStatusBarState = mStatusBarStateController.getState();
- mDozing = mStatusBarStateController.isDozing();
mLockPatternUtils = lockPatternUtils;
mAuthController = authController;
- mPowerManager = powerManager;
dumpManager.registerDumpable(getClass().getName(), this);
mHandler = new Handler(mainLooper) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 5e6b904..7947241 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -43,6 +43,7 @@
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
+import android.hardware.fingerprint.IUdfpsHbmListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -100,6 +101,8 @@
@Nullable
private UdfpsController mUdfpsController;
@Nullable
+ private IUdfpsHbmListener mUdfpsHbmListener;
+ @Nullable
private SidefpsController mSidefpsController;
@VisibleForTesting
TaskStackListener mTaskStackListener;
@@ -470,6 +473,24 @@
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
}
+ /**
+ * Stores the listener received from {@link com.android.server.display.DisplayModeDirector}.
+ *
+ * DisplayModeDirector implements {@link IUdfpsHbmListener} and registers it with this class by
+ * calling {@link CommandQueue#setUdfpsHbmListener(IUdfpsHbmListener)}.
+ */
+ @Override
+ public void setUdfpsHbmListener(IUdfpsHbmListener listener) {
+ mUdfpsHbmListener = listener;
+ }
+
+ /**
+ * @return IUdfpsHbmListener that can be set by DisplayModeDirector.
+ */
+ @Nullable public IUdfpsHbmListener getUdfpsHbmListener() {
+ return mUdfpsHbmListener;
+ }
+
@Override
public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver,
int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 39adabb..23c4413 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -70,6 +70,7 @@
private final Consumer<Boolean> mProxCallback;
private final SecureSettings mSecureSettings;
private final Callback mCallback;
+ private final boolean mScreenOffUdfpsEnabled;
@VisibleForTesting
protected TriggerSensor[] mSensors;
@@ -116,6 +117,8 @@
mProximitySensor = proximitySensor;
mSelectivelyRegisterProxSensors = dozeParameters.getSelectivelyRegisterSensorsUsingProx();
mListeningProxSensors = !mSelectivelyRegisterProxSensors;
+ mScreenOffUdfpsEnabled =
+ config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser());
boolean udfpsEnrolled =
authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
@@ -171,7 +174,7 @@
findSensorWithType(config.udfpsLongPressSensorType()),
"doze_pulse_on_auth",
true /* settingDef */,
- udfpsEnrolled,
+ udfpsEnrolled && (alwaysOn || mScreenOffUdfpsEnabled),
DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
true /* reports touch coordinates */,
true /* touchscreen */,
@@ -369,6 +372,7 @@
pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors);
pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors);
pw.println("mListeningProxSensors=" + mListeningProxSensors);
+ pw.println("mScreenOffUdfpsEnabled=" + mScreenOffUdfpsEnabled);
IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
idpw.increaseIndent();
for (TriggerSensor s : mSensors) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 6a025a7..d9e2648 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -91,8 +91,8 @@
// than the activity's background.
LinearLayout item = findViewById(R.id.item);
GradientDrawable shape = (GradientDrawable) item.getBackground();
- final TypedArray ta = mContext.obtainStyledAttributes(
- new int[]{android.R.attr.colorBackgroundFloating});
+ final TypedArray ta = mContext.getTheme().obtainStyledAttributes(
+ new int[]{com.android.internal.R.attr.colorSurface});
shape.setColor(ta.getColor(0, Color.WHITE));
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
index c416b5e..b031637 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
@@ -35,9 +35,11 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.people.PeopleSpaceUtils;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.wmshell.BubblesManager;
+import com.android.wm.shell.bubbles.Bubble;
import java.util.Optional;
@@ -53,14 +55,35 @@
private final UserManager mUserManager;
private boolean mIsForTesting;
private IStatusBarService mIStatusBarService;
+ private CommandQueue mCommandQueue;
+ private Bubble mBubble;
+ private NotificationEntry mEntryToBubble;
@Inject
public LaunchConversationActivity(NotificationEntryManager notificationEntryManager,
- Optional<BubblesManager> bubblesManagerOptional, UserManager userManager) {
+ Optional<BubblesManager> bubblesManagerOptional, UserManager userManager,
+ CommandQueue commandQueue) {
super();
mNotificationEntryManager = notificationEntryManager;
mBubblesManagerOptional = bubblesManagerOptional;
mUserManager = userManager;
+ mCommandQueue = commandQueue;
+ mCommandQueue.addCallback(new CommandQueue.Callbacks() {
+ // (b/190833924) Wait for the app transition to finish before showing the bubble,
+ // opening the bubble while the transition is happening can mess with the placement
+ // of the bubble's surface.
+ @Override
+ public void appTransitionFinished(int displayId) {
+ if (mBubblesManagerOptional.isPresent()) {
+ if (mBubble != null) {
+ mBubblesManagerOptional.get().expandStackAndSelectBubble(mBubble);
+ } else if (mEntryToBubble != null) {
+ mBubblesManagerOptional.get().expandStackAndSelectBubble(mEntryToBubble);
+ }
+ }
+ mCommandQueue.removeCallback(this);
+ }
+ });
}
@Override
@@ -95,14 +118,28 @@
return;
}
- NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(
- notificationKey);
- if (entry != null && entry.canBubble() && mBubblesManagerOptional.isPresent()) {
- if (DEBUG) Log.d(TAG, "Open bubble for conversation");
- mBubblesManagerOptional.get().expandStackAndSelectBubble(entry);
- // Just opt-out and don't cancel the notification for bubbles.
- finish();
- return;
+ // We can potentially bubble without a notification, so rather than rely on
+ // notificationKey here (which could be null if there's no notification or if the
+ // bubble is suppressing the notification), so we'll use the shortcutId for lookups.
+ // This misses one specific case: a bubble that was never opened & still has a
+ // visible notification, but the bubble was dismissed & aged out of the overflow.
+ // So it wouldn't exist in the stack or overflow to be looked up BUT the notif entry
+ // would still exist & be bubbleable. So if we don't get a bubble from the
+ // shortcutId, fallback to notificationKey if it exists.
+ if (mBubblesManagerOptional.isPresent()) {
+ mBubble = mBubblesManagerOptional.get().getBubbleWithShortcutId(tileId);
+ NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(
+ notificationKey);
+ if (mBubble != null || (entry != null && entry.canBubble())) {
+ mEntryToBubble = entry;
+ if (DEBUG) {
+ Log.d(TAG,
+ "Opening bubble: " + mBubble + ", entry: " + mEntryToBubble);
+ }
+ // Just opt-out and don't cancel the notification for bubbles.
+ finish();
+ return;
+ }
}
if (mIStatusBarService == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 08a68bc..7cc6ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -266,10 +266,9 @@
private void updateAlphaAnimator() {
TouchAnimator.Builder builder = new TouchAnimator.Builder()
- // The following two views have to be hidden manually, so as not to hide the
- // Privacy chip in QQS
- .addFloat(mDateView, "alpha", 0, 1)
.addFloat(mSecurityHeaderView, "alpha", 0, 1)
+ // These views appear on expanding down
+ .addFloat(mClockView, "alpha", 0, 1)
.addFloat(mQSCarriers, "alpha", 0, 1)
.setListener(new TouchAnimator.ListenerAdapter() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 32a6c6c..24b9208 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -103,6 +103,8 @@
state.state = (isRecording || isStarting) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
state.label = mContext.getString(R.string.quick_settings_screen_record_label);
state.icon = ResourceIcon.get(R.drawable.ic_screenrecord);
+ // Show expand icon when clicking will open a dialog
+ state.forceExpandIcon = state.state == Tile.STATE_INACTIVE;
if (isRecording) {
state.secondaryLabel = mContext.getString(R.string.quick_settings_screen_record_stop);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 085a076..baac254 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -259,11 +259,9 @@
final float inShelfAmount = updateShelfTransformation(i, child, scrollingFast,
expandingAnimated, isLastChild);
- final float stackEnd = mAmbientState.getStackY()
- + mAmbientState.getStackHeight();
// TODO(b/172289889) scale mPaddingBetweenElements with expansion amount
if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
- notificationClipEnd = stackEnd;
+ notificationClipEnd = shelfStart + getIntrinsicHeight();
} else {
notificationClipEnd = shelfStart - mPaddingBetweenElements;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 298d4f0..8e24890 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -115,13 +115,18 @@
}
public class FooterViewState extends ExpandableViewState {
+ /**
+ * used to hide the content of the footer to animate.
+ * #hide is applied without animation, but #hideContent has animation.
+ */
+ public boolean hideContent;
+
@Override
public void applyToView(View view) {
super.applyToView(view);
if (view instanceof FooterView) {
FooterView footerView = (FooterView) view;
- boolean visible = this.clipTopAmount < mClearAllTopPadding;
- footerView.setContentVisible(visible && footerView.isVisible());
+ footerView.setContentVisible(!hideContent);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 8277fae..f90b4c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4550,6 +4550,12 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setQsExpansionFraction(float qsExpansionFraction) {
mQsExpansionFraction = qsExpansionFraction;
+
+ // If notifications are scrolled,
+ // clear out scrollY by the time we push notifications offscreen
+ if (mOwnScrollY > 0) {
+ setOwnScrollY((int) MathUtils.lerp(mOwnScrollY, 0, mQsExpansionFraction));
+ }
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index a02ebbf..e5fd103 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -411,8 +411,8 @@
final float footerEnd = algorithmState.mCurrentExpandedYPosition
+ view.getIntrinsicHeight();
final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
-
- viewState.hidden = shadeClosed || isShelfShowing || noSpaceForFooter;
+ ((FooterView.FooterViewState) viewState).hideContent =
+ shadeClosed || isShelfShowing || noSpaceForFooter;
} else if (view != ambientState.getTrackedHeadsUpRow()) {
if (ambientState.isExpansionChanging()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index b3569d0..528827f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -101,6 +101,7 @@
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingManager.FalsingTapListener;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -108,6 +109,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.qs.QSDetailDisplayer;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.GestureRecorder;
@@ -581,6 +583,11 @@
* The alpha of the views which only show on the keyguard but not in shade / shade locked
*/
private float mKeyguardOnlyContentAlpha = 1.0f;
+
+ /**
+ * Are we currently in gesture navigation
+ */
+ private boolean mIsGestureNavigation;
private int mOldLayoutDirection;
private NotificationShelfController mNotificationShelfController;
private int mScrimCornerRadius;
@@ -669,6 +676,7 @@
KeyguardMediaController keyguardMediaController,
PrivacyDotViewController privacyDotViewController,
TapAgainViewController tapAgainViewController,
+ NavigationModeController navigationModeController,
FragmentService fragmentService,
QuickAccessWalletController quickAccessWalletController,
@Main Executor uiExecutor,
@@ -769,6 +777,9 @@
mAuthController = authController;
mLockIconViewController = lockIconViewController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ int currentMode = navigationModeController.addListener(
+ mode -> mIsGestureNavigation = QuickStepContract.isGesturalMode(mode));
+ mIsGestureNavigation = QuickStepContract.isGesturalMode(currentMode);
mView.setBackgroundColor(Color.TRANSPARENT);
OnAttachStateChangeListener onAttachStateChangeListener = new OnAttachStateChangeListener();
@@ -1808,9 +1819,15 @@
}
private boolean isInQsArea(float x, float y) {
- return (x >= mQsFrame.getX() && x <= mQsFrame.getX() + mQsFrame.getWidth()) && (
- y <= mNotificationStackScrollLayoutController.getBottomMostNotificationBottom()
- || y <= mQs.getView().getY() + mQs.getView().getHeight());
+ if (x < mQsFrame.getX() || x > mQsFrame.getX() + mQsFrame.getWidth()) {
+ return false;
+ }
+ // Let's reject anything at the very bottom around the home handle in gesture nav
+ if (mIsGestureNavigation && y > mView.getHeight() - mNavigationBarBottomHeight) {
+ return false;
+ }
+ return y <= mNotificationStackScrollLayoutController.getBottomMostNotificationBottom()
+ || y <= mQs.getView().getY() + mQs.getView().getHeight();
}
private boolean isOpenQsEvent(MotionEvent event) {
@@ -2200,8 +2217,9 @@
}
private void updateQSExpansionEnabledAmbient() {
+ final float scrollRangeToTop = mAmbientState.getTopPadding() - mQuickQsOffsetHeight;
mQsExpansionEnabledAmbient =
- mAmbientState.getScrollY() <= 0 && !mAmbientState.isShadeOpening();
+ mAmbientState.getScrollY() <= scrollRangeToTop && !mAmbientState.isShadeOpening();
setQsExpansionEnabled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 10c4a55..5441bd4 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -84,6 +84,7 @@
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.wm.shell.bubbles.Bubble;
import com.android.wm.shell.bubbles.BubbleEntry;
import com.android.wm.shell.bubbles.Bubbles;
@@ -657,6 +658,22 @@
mBubbles.expandStackAndSelectBubble(notifToBubbleEntry(entry));
}
+ /**
+ * Request the stack expand if needed, then select the specified Bubble as current.
+ *
+ * @param bubble the bubble to be selected
+ */
+ public void expandStackAndSelectBubble(Bubble bubble) {
+ mBubbles.expandStackAndSelectBubble(bubble);
+ }
+
+ /**
+ * @return a bubble that matches the provided shortcutId, if one exists.
+ */
+ public Bubble getBubbleWithShortcutId(String shortcutId) {
+ return mBubbles.getBubbleWithShortcutId(shortcutId);
+ }
+
/** See {@link NotifCallback}. */
public void addNotifCallback(NotifCallback callback) {
mCallbacks.add(callback);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 0342796..3d4da27 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -62,7 +62,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
-import android.os.PowerManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.ServiceState;
@@ -166,8 +165,6 @@
@Mock
private AuthController mAuthController;
@Mock
- private PowerManager mPowerManager;
- @Mock
private TelephonyListenerManager mTelephonyListenerManager;
@Mock
private FeatureFlags mFeatureFlags;
@@ -526,46 +523,6 @@
}
@Test
- public void testFingerprintCancelAodInterrupt_onAuthenticationFailed() {
- // GIVEN on keyguard and listening for fingerprint authentication
- mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor =
- ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class);
- verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(),
- any(), anyInt(), anyInt());
- FingerprintManager.AuthenticationCallback authCallback =
- fingerprintCallbackCaptor.getValue();
-
- // WHEN authentication fails
- authCallback.onAuthenticationFailed();
-
- // THEN aod interrupt is cancelled
- verify(mAuthController).onCancelUdfps();
- }
-
- @Test
- public void testFingerprintCancelAodInterrupt_onAuthenticationError() {
- // GIVEN on keyguard and listening for fingerprint authentication
- mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor =
- ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class);
- verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(),
- any(), anyInt(), anyInt());
- FingerprintManager.AuthenticationCallback authCallback =
- fingerprintCallbackCaptor.getValue();
-
- // WHEN authentication errors
- authCallback.onAuthenticationError(0, "");
-
- // THEN aod interrupt is cancelled
- verify(mAuthController).onCancelUdfps();
- }
-
- @Test
public void skipsAuthentication_whenStatusBarShadeLocked() {
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
@@ -1022,7 +979,7 @@
mBroadcastDispatcher, mDumpManager,
mRingerModeTracker, mBackgroundExecutor,
mStatusBarStateController, mLockPatternUtils,
- mAuthController, mTelephonyListenerManager, mPowerManager, mFeatureFlags);
+ mAuthController, mTelephonyListenerManager, mFeatureFlags);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 724f8a3..d6226aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -73,6 +73,7 @@
when(config.dozePickupSensorAvailable()).thenReturn(false);
when(config.wakeScreenGestureAvailable()).thenReturn(false);
when(config.quickPickupSensorEnabled(anyInt())).thenReturn(false);
+ when(config.screenOffUdfpsEnabled(anyInt())).thenReturn(false);
doneHolder[0] = true;
return config;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
index ccb40e1..5f4d90b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java
@@ -16,11 +16,14 @@
package com.android.systemui.people.widget;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -39,9 +42,11 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.wmshell.BubblesManager;
+import com.android.wm.shell.bubbles.Bubble;
import org.junit.Before;
import org.junit.Test;
@@ -87,6 +92,8 @@
@Mock
private UserManager mUserManager;
+ private CommandQueue mCommandQueue;
+
@Captor
private ArgumentCaptor<NotificationVisibility> mNotificationVisibilityCaptor;
@@ -95,8 +102,9 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mCommandQueue = new CommandQueue(mContext);
mActivity = new LaunchConversationActivity(mNotificationEntryManager,
- Optional.of(mBubblesManager), mUserManager);
+ Optional.of(mBubblesManager), mUserManager, mCommandQueue);
mActivity.setIsForTesting(true, mIStatusBarService);
mIntent = new Intent();
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, "tile ID");
@@ -159,9 +167,13 @@
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
+ assertThat(mActivity.isFinishing()).isTrue();
+ mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY);
+
verify(mIStatusBarService, times(1)).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), mNotificationVisibilityCaptor.capture());
- verify(mBubblesManager, never()).expandStackAndSelectBubble(any());
+ verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class));
+ verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class));
NotificationVisibility nv = mNotificationVisibilityCaptor.getValue();
assertThat(nv.count).isEqualTo(NOTIF_COUNT);
@@ -175,6 +187,9 @@
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
+ assertThat(mActivity.isFinishing()).isTrue();
+ mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY);
+
// Don't clear the notification for bubbles.
verify(mIStatusBarService, never()).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), any());
@@ -190,8 +205,27 @@
mActivity.onCreate(new Bundle());
assertThat(mActivity.isFinishing()).isTrue();
+ mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY);
+
verify(mIStatusBarService, never()).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), any());
- verify(mBubblesManager, never()).expandStackAndSelectBubble(any());
+ verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class));
+ verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class));
+ }
+
+ @Test
+ public void testBubbleWithNoNotifOpensBubble() throws Exception {
+ Bubble bubble = mock(Bubble.class);
+ when(mBubblesManager.getBubbleWithShortcutId(any())).thenReturn(bubble);
+
+ mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
+ EMPTY_STRING);
+ mActivity.setIntent(mIntent);
+ mActivity.onCreate(new Bundle());
+
+ assertThat(mActivity.isFinishing()).isTrue();
+ mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY);
+
+ verify(mBubblesManager, times(1)).expandStackAndSelectBubble(eq(bubble));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index e4af21a..3b4e863 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -19,6 +19,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -167,4 +168,37 @@
assertTrue(mTile.getState().contentDescription.toString().contains(mTile.getState().label));
}
+
+ @Test
+ public void testForceExpandIcon_notRecordingNotStarting() {
+ when(mController.isStarting()).thenReturn(false);
+ when(mController.isRecording()).thenReturn(false);
+
+ mTile.refreshState();
+ mTestableLooper.processAllMessages();
+
+ assertTrue(mTile.getState().forceExpandIcon);
+ }
+
+ @Test
+ public void testForceExpandIcon_recordingNotStarting() {
+ when(mController.isStarting()).thenReturn(false);
+ when(mController.isRecording()).thenReturn(true);
+
+ mTile.refreshState();
+ mTestableLooper.processAllMessages();
+
+ assertFalse(mTile.getState().forceExpandIcon);
+ }
+
+ @Test
+ public void testForceExpandIcon_startingNotRecording() {
+ when(mController.isStarting()).thenReturn(true);
+ when(mController.isRecording()).thenReturn(false);
+
+ mTile.refreshState();
+ mTestableLooper.processAllMessages();
+
+ assertFalse(mTile.getState().forceExpandIcon);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index c6e5697..9e939ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -82,6 +82,7 @@
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSDetailDisplayer;
@@ -261,6 +262,8 @@
@Mock
private PrivacyDotViewController mPrivacyDotViewController;
@Mock
+ private NavigationModeController mNavigationModeController;
+ @Mock
private SecureSettings mSecureSettings;
@Mock
private TapAgainViewController mTapAgainViewController;
@@ -391,6 +394,7 @@
mKeyguardMediaController,
mPrivacyDotViewController,
mTapAgainViewController,
+ mNavigationModeController,
mFragmentService,
mQuickAccessWalletController,
new FakeExecutor(new FakeSystemClock()),
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8aea4a9..9f831d2 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -122,6 +122,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerExemptionManager;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.Process;
import android.os.RemoteCallback;
@@ -1850,7 +1851,6 @@
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
r.foregroundNoti = notification;
r.foregroundServiceType = foregroundServiceType;
- boolean enterForeground = false;
if (!r.isForeground) {
final ServiceMap smap = getServiceMapLocked(r.userId);
if (smap != null) {
@@ -1877,7 +1877,12 @@
}
r.isForeground = true;
r.mLogEntering = true;
- enterForeground = true;
+ // The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could
+ // be deferred, make a copy of mAllowStartForeground and
+ // mAllowWhileInUsePermissionInFgs.
+ r.mAllowStartForegroundAtEntering = r.mAllowStartForeground;
+ r.mAllowWhileInUsePermissionInFgsAtEntering =
+ r.mAllowWhileInUsePermissionInFgs;
r.mStartForegroundCount++;
r.mFgsEnterTime = SystemClock.uptimeMillis();
if (!stopProcStatsOp) {
@@ -6235,12 +6240,22 @@
r.packageName, mAm.mConstants.mFgsAtomSampleRate)) {
return;
}
+ boolean allowWhileInUsePermissionInFgs;
+ @PowerExemptionManager.ReasonCode int fgsStartReasonCode;
+ if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER
+ || state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
+ allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering;
+ fgsStartReasonCode = r.mAllowStartForegroundAtEntering;
+ } else {
+ allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgs;
+ fgsStartReasonCode = r.mAllowStartForeground;
+ }
FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid,
r.shortInstanceName,
state,
- r.mAllowWhileInUsePermissionInFgs,
- r.mAllowStartForeground,
+ allowWhileInUsePermissionInFgs,
+ fgsStartReasonCode,
r.appInfo.targetSdkVersion,
r.mRecentCallingUid,
r.mRecentCallerApplicationInfo != null
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 0757e7b..d71919e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -102,7 +102,6 @@
import com.android.server.compat.PlatformCompat;
import java.io.BufferedReader;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -806,8 +805,7 @@
return -1;
}
- File file = new File(filename);
- file.delete();
+ // Writes an error message to stderr on failure
ParcelFileDescriptor fd = openFileForSystem(filename, "w");
if (fd == null) {
return -1;
@@ -961,16 +959,16 @@
String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime);
heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof";
}
- pw.println("File: " + heapFile);
- pw.flush();
- File file = new File(heapFile);
- file.delete();
+ // Writes an error message to stderr on failure
ParcelFileDescriptor fd = openFileForSystem(heapFile, "w");
if (fd == null) {
return -1;
}
+ pw.println("File: " + heapFile);
+ pw.flush();
+
final CountDownLatch latch = new CountDownLatch(1);
final RemoteCallback finishCallback = new RemoteCallback(new OnResultListener() {
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index dd1ddd7..3ba07af 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -18,7 +18,7 @@
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
+import static android.os.PowerExemptionManager.REASON_DENIED;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -37,7 +37,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
-import android.os.PowerWhitelistManager;
+import android.os.PowerExemptionManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -153,6 +153,8 @@
// allow while-in-use permissions in foreground service or not.
// while-in-use permissions in FGS started from background might be restricted.
boolean mAllowWhileInUsePermissionInFgs;
+ // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state.
+ boolean mAllowWhileInUsePermissionInFgsAtEntering;
// the most recent package that start/bind this service.
String mRecentCallingPackage;
@@ -172,7 +174,9 @@
// allow the service becomes foreground service? Service started from background may not be
// allowed to become a foreground service.
- @PowerWhitelistManager.ReasonCode int mAllowStartForeground = REASON_DENIED;
+ @PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED;
+ // A copy of mAllowStartForeground's value when the service is entering FGS state.
+ @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED;
// Debug info why mAllowStartForeground is allowed or denied.
String mInfoAllowStartForeground;
// Debug info if mAllowStartForeground is allowed because of a temp-allowlist.
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index ce8cbaf..104bc9b 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1029,7 +1029,7 @@
if (isStarted && mInProgressEvents == null) {
mInProgressEvents = new ArrayMap<>(1);
- } else if (mPausedInProgressEvents == null) {
+ } else if (!isStarted && mPausedInProgressEvents == null) {
mPausedInProgressEvents = new ArrayMap<>(1);
}
ArrayMap<IBinder, InProgressStartOpEvent> events = isStarted
@@ -1231,11 +1231,13 @@
*/
void onClientDeath(@NonNull IBinder clientId) {
synchronized (AppOpsService.this) {
- if (mInProgressEvents == null) {
+ if (mInProgressEvents == null && mPausedInProgressEvents == null) {
return;
}
- InProgressStartOpEvent deadEvent = mInProgressEvents.get(clientId);
+ ArrayMap<IBinder, InProgressStartOpEvent> events = isPaused()
+ ? mPausedInProgressEvents : mInProgressEvents;
+ InProgressStartOpEvent deadEvent = events.get(clientId);
if (deadEvent != null) {
deadEvent.numUnfinishedStarts = 1;
}
@@ -1250,14 +1252,18 @@
* @param newState The new state
*/
public void onUidStateChanged(@AppOpsManager.UidState int newState) {
- if (mInProgressEvents == null) {
+ if (mInProgressEvents == null && mPausedInProgressEvents == null) {
return;
}
- int numInProgressEvents = mInProgressEvents.size();
- List<IBinder> binders = new ArrayList<>(mInProgressEvents.keySet());
+ boolean isRunning = isRunning();
+ ArrayMap<IBinder, AppOpsService.InProgressStartOpEvent> events =
+ isRunning ? mInProgressEvents : mPausedInProgressEvents;
+
+ int numInProgressEvents = events.size();
+ List<IBinder> binders = new ArrayList<>(events.keySet());
for (int i = 0; i < numInProgressEvents; i++) {
- InProgressStartOpEvent event = mInProgressEvents.get(binders.get(i));
+ InProgressStartOpEvent event = events.get(binders.get(i));
if (event != null && event.getUidState() != newState) {
try {
@@ -1272,16 +1278,17 @@
// Call started() to add a new start event object and then add the
// previously removed unfinished start counts back
if (proxy != null) {
- started(event.getClientId(), proxy.getUid(), proxy.getPackageName(),
- proxy.getAttributionTag(), newState, event.getFlags(), false,
+ startedOrPaused(event.getClientId(), proxy.getUid(),
+ proxy.getPackageName(), proxy.getAttributionTag(), newState,
+ event.getFlags(), false, isRunning,
event.getAttributionFlags(), event.getAttributionChainId());
} else {
- started(event.getClientId(), Process.INVALID_UID, null, null, newState,
- OP_FLAG_SELF, false, event.getAttributionFlags(),
- event.getAttributionChainId());
+ startedOrPaused(event.getClientId(), Process.INVALID_UID, null, null,
+ newState, event.getFlags(), false, isRunning,
+ event.getAttributionFlags(), event.getAttributionChainId());
}
- InProgressStartOpEvent newEvent = mInProgressEvents.get(binders.get(i));
+ InProgressStartOpEvent newEvent = events.get(binders.get(i));
if (newEvent != null) {
newEvent.numUnfinishedStarts += numPreviousUnfinishedStarts - 1;
}
@@ -4551,15 +4558,15 @@
}
try {
- if (mPlatformCompat.isChangeEnabledByPackageName(
+ if (!mPlatformCompat.isChangeEnabledByPackageName(
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName,
- userId) && mPlatformCompat.isChangeEnabledByUid(
+ userId) || !mPlatformCompat.isChangeEnabledByUid(
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE,
- callingUid) && !isAttributionTagValid) {
- Slog.e(TAG, msg);
- } else {
- Slog.e(TAG, msg);
+ callingUid)) {
+ // Do not override tags if overriding is not enabled for this package
+ isAttributionTagValid = true;
}
+ Slog.e(TAG, msg);
} catch (RemoteException neverHappens) {
}
}
@@ -6494,9 +6501,9 @@
int numAttrTags = op.mAttributions.size();
for (int attrNum = 0; attrNum < numAttrTags; attrNum++) {
AttributedOp attrOp = op.mAttributions.valueAt(attrNum);
- if (restricted) {
+ if (restricted && attrOp.isRunning()) {
attrOp.pause();
- } else {
+ } else if (attrOp.isPaused()) {
attrOp.resume();
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 13b7ebc..fe5ee78 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -512,6 +512,8 @@
}
}
}
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ mDisplayModeDirector.onBootCompleted();
}
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 997f0e5..07d13c2 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -155,7 +155,6 @@
mSettingsObserver.observe();
mDisplayObserver.observe();
mBrightnessObserver.observe(sensorManager);
- mUdfpsObserver.observe();
synchronized (mLock) {
// We may have a listener already registered before the call to start, so go ahead and
// notify them to pick up our newly initialized state.
@@ -163,6 +162,16 @@
}
}
+ /**
+ * Same as {@link #start(SensorManager)}, but for observers that need to be delayed even more,
+ * for example until SystemUI is ready.
+ */
+ public void onBootCompleted() {
+ // UDFPS observer registers a listener with SystemUI which might not be ready until the
+ // system is fully booted.
+ mUdfpsObserver.observe();
+ }
+
public void setLoggingEnabled(boolean loggingEnabled) {
if (mLoggingEnabled == loggingEnabled) {
return;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index c14acd7..1b50f03 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -365,7 +365,7 @@
@Nullable
private final ColorDisplayServiceInternal mCdsi;
- private final float[] mNitsRange;
+ private float[] mNitsRange;
private final HighBrightnessModeController mHbmController;
@@ -447,6 +447,7 @@
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
+ mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
mHandler = new DisplayControllerHandler(handler.getLooper());
if (mDisplayId == Display.DEFAULT_DISPLAY) {
@@ -462,6 +463,7 @@
mBlanker = blanker;
mContext = context;
mBrightnessTracker = brightnessTracker;
+ // TODO: b/186428377 update brightness setting when display changes
mBrightnessSetting = brightnessSetting;
mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
@@ -498,13 +500,10 @@
mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
+ mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
+ .getDisplayDeviceConfig();
- mDisplayDeviceConfig = logicalDisplay
- .getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
- mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease();
- mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
- mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
- mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
+ loadBrightnessRampRates();
mSkipScreenOnBrightnessRamp = resources.getBoolean(
com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
@@ -513,66 +512,7 @@
// Seed the cached brightness
saveBrightnessInfo(getScreenBrightnessSetting());
- if (mUseSoftwareAutoBrightnessConfig) {
- final float dozeScaleFactor = resources.getFraction(
- com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
- 1, 1);
-
- int[] ambientBrighteningThresholds = resources.getIntArray(
- com.android.internal.R.array.config_ambientBrighteningThresholds);
- int[] ambientDarkeningThresholds = resources.getIntArray(
- com.android.internal.R.array.config_ambientDarkeningThresholds);
- int[] ambientThresholdLevels = resources.getIntArray(
- com.android.internal.R.array.config_ambientThresholdLevels);
- HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
- ambientBrighteningThresholds, ambientDarkeningThresholds,
- ambientThresholdLevels);
-
- int[] screenBrighteningThresholds = resources.getIntArray(
- com.android.internal.R.array.config_screenBrighteningThresholds);
- int[] screenDarkeningThresholds = resources.getIntArray(
- com.android.internal.R.array.config_screenDarkeningThresholds);
- int[] screenThresholdLevels = resources.getIntArray(
- com.android.internal.R.array.config_screenThresholdLevels);
- HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
- screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
-
- long brighteningLightDebounce = resources.getInteger(
- com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
- long darkeningLightDebounce = resources.getInteger(
- com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
- boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
- com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
-
- int lightSensorWarmUpTimeConfig = resources.getInteger(
- com.android.internal.R.integer.config_lightSensorWarmupTime);
- int lightSensorRate = resources.getInteger(
- com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
- int initialLightSensorRate = resources.getInteger(
- com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
- if (initialLightSensorRate == -1) {
- initialLightSensorRate = lightSensorRate;
- } else if (initialLightSensorRate > lightSensorRate) {
- Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
- + initialLightSensorRate + ") to be less than or equal to "
- + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
- }
-
- loadAmbientLightSensor();
-
- mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig);
- if (mBrightnessMapper != null) {
- mAutomaticBrightnessController = new AutomaticBrightnessController(this,
- handler.getLooper(), sensorManager, mLightSensor, mBrightnessMapper,
- lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
- PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
- initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
- autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
- screenBrightnessThresholds, logicalDisplay, context, mHbmController);
- } else {
- mUseSoftwareAutoBrightnessConfig = false;
- }
- }
+ setUpAutoBrightness(resources, handler);
mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic();
mColorFadeFadesConfig = resources.getBoolean(
@@ -610,13 +550,8 @@
mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
mDisplayWhiteBalanceController = displayWhiteBalanceController;
- if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) {
- mNitsRange = mDisplayDeviceConfig.getNits();
- } else {
- Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back");
- mNitsRange = BrightnessMappingStrategy.getFloatArray(context.getResources()
- .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits));
- }
+ loadNitsRange(resources);
+
if (mDisplayId == Display.DEFAULT_DISPLAY) {
mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
@@ -802,10 +737,7 @@
mDisplayDevice = device;
mUniqueDisplayId = uniqueId;
mDisplayDeviceConfig = config;
-
- loadAmbientLightSensor();
- loadProximitySensor();
- mHbmController.resetHbmData(token, config.getHighBrightnessModeData());
+ loadFromDisplayDeviceConfig(token);
});
}
@@ -846,6 +778,18 @@
}
}
+ private void loadFromDisplayDeviceConfig(IBinder token) {
+ // All properties that depend on the associated DisplayDevice and the DDC must be
+ // updated here.
+ loadAmbientLightSensor();
+ loadBrightnessRampRates();
+ loadProximitySensor();
+ loadNitsRange(mContext.getResources());
+ setUpAutoBrightness(mContext.getResources(), mHandler);
+ reloadReduceBrightColours();
+ mHbmController.resetHbmData(token, mDisplayDeviceConfig.getHighBrightnessModeData());
+ }
+
private void sendUpdatePowerState() {
synchronized (mLock) {
sendUpdatePowerStateLocked();
@@ -903,6 +847,98 @@
false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
}
+ private void setUpAutoBrightness(Resources resources, Handler handler) {
+ if (!mUseSoftwareAutoBrightnessConfig) {
+ return;
+ }
+
+ mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig);
+
+ if (mBrightnessMapper != null) {
+ final float dozeScaleFactor = resources.getFraction(
+ com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
+ 1, 1);
+
+ int[] ambientBrighteningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_ambientBrighteningThresholds);
+ int[] ambientDarkeningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_ambientDarkeningThresholds);
+ int[] ambientThresholdLevels = resources.getIntArray(
+ com.android.internal.R.array.config_ambientThresholdLevels);
+ HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
+ ambientBrighteningThresholds, ambientDarkeningThresholds,
+ ambientThresholdLevels);
+
+ int[] screenBrighteningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_screenBrighteningThresholds);
+ int[] screenDarkeningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_screenDarkeningThresholds);
+ int[] screenThresholdLevels = resources.getIntArray(
+ com.android.internal.R.array.config_screenThresholdLevels);
+ HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
+ screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
+
+ long brighteningLightDebounce = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
+ long darkeningLightDebounce = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
+ boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
+ com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
+
+ int lightSensorWarmUpTimeConfig = resources.getInteger(
+ com.android.internal.R.integer.config_lightSensorWarmupTime);
+ int lightSensorRate = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
+ int initialLightSensorRate = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
+ if (initialLightSensorRate == -1) {
+ initialLightSensorRate = lightSensorRate;
+ } else if (initialLightSensorRate > lightSensorRate) {
+ Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
+ + initialLightSensorRate + ") to be less than or equal to "
+ + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
+ }
+
+ loadAmbientLightSensor();
+
+ if (mAutomaticBrightnessController != null) {
+ mAutomaticBrightnessController.stop();
+ }
+ mAutomaticBrightnessController = new AutomaticBrightnessController(this,
+ handler.getLooper(), mSensorManager, mLightSensor, mBrightnessMapper,
+ lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
+ PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
+ initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
+ autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
+ screenBrightnessThresholds, mLogicalDisplay, mContext, mHbmController);
+ } else {
+ mUseSoftwareAutoBrightnessConfig = false;
+ }
+ }
+
+ private void loadBrightnessRampRates() {
+ mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease();
+ mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
+ mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
+ mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
+ }
+
+ private void loadNitsRange(Resources resources) {
+ if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) {
+ mNitsRange = mDisplayDeviceConfig.getNits();
+ } else {
+ Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back");
+ mNitsRange = BrightnessMappingStrategy.getFloatArray(resources
+ .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits));
+ }
+ }
+
+ private void reloadReduceBrightColours() {
+ if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) {
+ applyReduceBrightColorsSplineAdjustment();
+ }
+ }
+
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index 66b23c4..e6d25ec 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -33,7 +33,6 @@
import android.location.LocationRequest;
import android.location.provider.ProviderRequest;
import android.location.util.identity.CallerIdentity;
-import android.os.Build;
import android.os.PowerManager.LocationPowerSaveMode;
import android.os.SystemClock;
import android.util.ArrayMap;
@@ -47,8 +46,8 @@
public static final LocationEventLog EVENT_LOG = new LocationEventLog();
private static int getLogSize() {
- if (Build.IS_DEBUGGABLE || D) {
- return 500;
+ if (D) {
+ return 600;
} else {
return 200;
}
@@ -152,7 +151,7 @@
/** Logs a client for a location provider entering the foreground state. */
public void logProviderClientForeground(String provider, CallerIdentity identity) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_CLIENT_FOREGROUND, provider, identity);
}
getAggregateStats(provider, identity).markRequestForeground();
@@ -160,7 +159,7 @@
/** Logs a client for a location provider leaving the foreground state. */
public void logProviderClientBackground(String provider, CallerIdentity identity) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_CLIENT_BACKGROUND, provider, identity);
}
getAggregateStats(provider, identity).markRequestBackground();
@@ -168,14 +167,14 @@
/** Logs a client for a location provider entering the permitted state. */
public void logProviderClientPermitted(String provider, CallerIdentity identity) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_CLIENT_PERMITTED, provider, identity);
}
}
/** Logs a client for a location provider leaving the permitted state. */
public void logProviderClientUnpermitted(String provider, CallerIdentity identity) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_CLIENT_UNPERMITTED, provider, identity);
}
}
@@ -187,7 +186,7 @@
/** Logs a new incoming location for a location provider. */
public void logProviderReceivedLocations(String provider, int numLocations) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
}
}
@@ -195,7 +194,7 @@
/** Logs a location deliver for a client of a location provider. */
public void logProviderDeliveredLocations(String provider, int numLocations,
CallerIdentity identity) {
- if (Build.IS_DEBUGGABLE || D) {
+ if (D) {
addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
}
getAggregateStats(provider, identity).markLocationDelivered();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 2b6a838..14f6fb3 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -312,6 +312,12 @@
}
}
+ /** Returns {@code true} if the incoming activity can belong to this transition. */
+ boolean canCoalesce(ActivityRecord r) {
+ return mLastLaunchedActivity.mDisplayContent == r.mDisplayContent
+ && mLastLaunchedActivity.getWindowingMode() == r.getWindowingMode();
+ }
+
/** @return {@code true} if the activity matches a launched activity in this transition. */
boolean contains(ActivityRecord r) {
return r != null && (r == mLastLaunchedActivity || mPendingDrawActivities.contains(r));
@@ -604,8 +610,7 @@
return;
}
- final DisplayContent targetDisplay = launchedActivity.mDisplayContent;
- if (info != null && info.mLastLaunchedActivity.mDisplayContent == targetDisplay) {
+ if (info != null && info.canCoalesce(launchedActivity)) {
// If we are already in an existing transition on the same display, only update the
// activity name, but not the other attributes.
@@ -633,7 +638,7 @@
// As abort for no process switch.
launchObserverNotifyIntentFailed();
}
- if (targetDisplay.isSleeping()) {
+ if (launchedActivity.mDisplayContent.isSleeping()) {
// It is unknown whether the activity can be drawn or not, e.g. ut depends on the
// keyguard states and the attributes or flags set by the activity. If the activity
// keeps invisible in the grace period, the tracker will be cancelled so it won't get
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index fb2db22..918979c 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -854,7 +854,7 @@
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0);
verify(mStatusBarMock, never()).setUdfpsHbmListener(any());
- director.start(createMockSensorManager());
+ director.onBootCompleted();
verify(mStatusBarMock).setUdfpsHbmListener(eq(director.getUdpfsObserver()));
}
@@ -863,6 +863,7 @@
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0);
director.start(createMockSensorManager());
+ director.onBootCompleted();
ArgumentCaptor<IUdfpsHbmListener> captor =
ArgumentCaptor.forClass(IUdfpsHbmListener.class);
verify(mStatusBarMock).setUdfpsHbmListener(captor.capture());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 82c459c..38466eb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -38,6 +38,7 @@
import android.app.ActivityOptions;
import android.app.ActivityOptions.SourceInfo;
import android.app.WaitResult;
+import android.app.WindowConfiguration;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
@@ -476,6 +477,18 @@
transitToDrawnAndVerifyOnLaunchFinished(activityOnNewDisplay);
}
+ @Test
+ public void testConsecutiveLaunchWithDifferentWindowingMode() {
+ mTopActivity.setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+ onActivityLaunched(mTrampolineActivity);
+ mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent,
+ mTrampolineActivity /* caller */, mTrampolineActivity.getUid());
+ notifyActivityLaunched(START_SUCCESS, mTopActivity);
+ // Different windowing modes should be independent launch events.
+ transitToDrawnAndVerifyOnLaunchFinished(mTrampolineActivity);
+ transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
+ }
+
private void transitToDrawnAndVerifyOnLaunchFinished(ActivityRecord activity) {
notifyTransitionStarting(activity);
notifyWindowsDrawn(activity);