Merge "Renaming compose slider haptics flag." into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 2bb08fc..c3c41f8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6858,27 +6858,36 @@
@FlaggedApi("android.app.api_rich_ongoing") public static class Notification.ProgressStyle extends android.app.Notification.Style {
ctor public Notification.ProgressStyle();
+ method @NonNull public android.app.Notification.ProgressStyle addProgressPoint(@NonNull android.app.Notification.ProgressStyle.Point);
method @NonNull public android.app.Notification.ProgressStyle addProgressSegment(@NonNull android.app.Notification.ProgressStyle.Segment);
- method @NonNull public android.app.Notification.ProgressStyle addProgressStep(@NonNull android.app.Notification.ProgressStyle.Step);
method public int getProgress();
method @Nullable public android.graphics.drawable.Icon getProgressEndIcon();
method public int getProgressMax();
+ method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Point> getProgressPoints();
method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Segment> getProgressSegments();
method @Nullable public android.graphics.drawable.Icon getProgressStartIcon();
- method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Step> getProgressSteps();
method @Nullable public android.graphics.drawable.Icon getProgressTrackerIcon();
method public boolean isProgressIndeterminate();
method public boolean isStyledByProgress();
method @NonNull public android.app.Notification.ProgressStyle setProgress(int);
method @NonNull public android.app.Notification.ProgressStyle setProgressEndIcon(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.app.Notification.ProgressStyle setProgressIndeterminate(boolean);
+ method @NonNull public android.app.Notification.ProgressStyle setProgressPoints(@NonNull java.util.List<android.app.Notification.ProgressStyle.Point>);
method @NonNull public android.app.Notification.ProgressStyle setProgressSegments(@NonNull java.util.List<android.app.Notification.ProgressStyle.Segment>);
method @NonNull public android.app.Notification.ProgressStyle setProgressStartIcon(@Nullable android.graphics.drawable.Icon);
- method @NonNull public android.app.Notification.ProgressStyle setProgressSteps(@NonNull java.util.List<android.app.Notification.ProgressStyle.Step>);
method @NonNull public android.app.Notification.ProgressStyle setProgressTrackerIcon(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.app.Notification.ProgressStyle setStyledByProgress(boolean);
}
+ public static final class Notification.ProgressStyle.Point {
+ ctor public Notification.ProgressStyle.Point(int);
+ method @ColorInt public int getColor();
+ method public int getId();
+ method public int getPosition();
+ method @NonNull public android.app.Notification.ProgressStyle.Point setColor(@ColorInt int);
+ method @NonNull public android.app.Notification.ProgressStyle.Point setId(int);
+ }
+
public static final class Notification.ProgressStyle.Segment {
ctor public Notification.ProgressStyle.Segment(int);
method @ColorInt public int getColor();
@@ -6888,15 +6897,6 @@
method @NonNull public android.app.Notification.ProgressStyle.Segment setId(int);
}
- public static final class Notification.ProgressStyle.Step {
- ctor public Notification.ProgressStyle.Step(int);
- method @ColorInt public int getColor();
- method public int getId();
- method public int getPosition();
- method @NonNull public android.app.Notification.ProgressStyle.Step setColor(@ColorInt int);
- method @NonNull public android.app.Notification.ProgressStyle.Step setId(int);
- }
-
public abstract static class Notification.Style {
ctor @Deprecated public Notification.Style();
method public android.app.Notification build();
@@ -36992,7 +36992,7 @@
}
@FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount {
- ctor public ContactsContract.RawContacts.DefaultAccount();
+ method @FlaggedApi("android.provider.new_default_account_api_enabled") @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState getDefaultAccountForNewContacts(@NonNull android.content.ContentResolver);
}
@FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 4b6c62e..7e43e46 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11950,6 +11950,10 @@
field @Deprecated public static final String STATE = "state";
}
+ @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount {
+ method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) public static void setDefaultAccountForNewContacts(@NonNull android.content.ContentResolver, @NonNull android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState);
+ }
+
public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
method @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) public static void setDefaultAccount(@NonNull android.content.ContentResolver, @Nullable android.accounts.Account);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5b556cc..95d3ea5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1960,8 +1960,12 @@
@Override
public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
- PropertyInvalidatedCache.dumpCacheInfo(pfd, args);
- IoUtils.closeQuietly(pfd);
+ try {
+ PropertyInvalidatedCache.dumpCacheInfo(pfd, args);
+ BroadcastStickyCache.dump(pfd);
+ } finally {
+ IoUtils.closeQuietly(pfd);
+ }
}
private File getDatabasesDir(Context context) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f27dc32..5907af0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -10153,6 +10153,9 @@
}
p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
+ final int sizePosition = p.dataPosition();
+ // Write size placeholder. With this size we can easily skip it in native.
+ p.writeInt(0);
int numAttributionWithNotesAppOps = notedAppOps.size();
p.writeInt(numAttributionWithNotesAppOps);
@@ -10169,6 +10172,12 @@
}
}
}
+
+ final int payloadPosition = p.dataPosition();
+ p.setDataPosition(sizePosition);
+ // Total header size including 4 bytes size itself.
+ p.writeInt(payloadPosition - sizePosition);
+ p.setDataPosition(payloadPosition);
}
/**
@@ -10182,6 +10191,8 @@
* @hide
*/
public static void readAndLogNotedAppops(@NonNull Parcel p) {
+ // Skip size.
+ p.readInt();
int numAttributionsWithNotedAppOps = p.readInt();
for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
diff --git a/core/java/android/app/BroadcastStickyCache.java b/core/java/android/app/BroadcastStickyCache.java
index d6f061b..ea81731 100644
--- a/core/java/android/app/BroadcastStickyCache.java
+++ b/core/java/android/app/BroadcastStickyCache.java
@@ -27,16 +27,21 @@
import android.net.nsd.NsdManager;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pManager;
+import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.os.UpdateLock;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
import android.view.WindowManagerPolicyConstants;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastPrintWriter;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
import java.util.ArrayList;
/** @hide */
@@ -214,6 +219,41 @@
}
}
+ public static void dump(@NonNull ParcelFileDescriptor pfd) {
+ if (!Flags.useStickyBcastCache()) {
+ return;
+ }
+ final PrintWriter pw = new FastPrintWriter(new FileOutputStream(pfd.getFileDescriptor()));
+ synchronized (sCachedStickyBroadcasts) {
+ dumpLocked(pw);
+ }
+ pw.flush();
+ }
+
+ @GuardedBy("sCachedStickyBroadcasts")
+ private static void dumpLocked(@NonNull PrintWriter pw) {
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(
+ pw, " " /* singleIndent */, " " /* prefix */);
+ ipw.println("Cached sticky broadcasts:");
+ ipw.increaseIndent();
+ final int count = sCachedStickyBroadcasts.size();
+ if (count == 0) {
+ ipw.println("<empty>");
+ } else {
+ for (int i = 0; i < count; ++i) {
+ final CachedStickyBroadcast cachedStickyBroadcast = sCachedStickyBroadcasts.get(i);
+ ipw.print("Entry #"); ipw.print(i); ipw.println(":");
+ ipw.increaseIndent();
+ ipw.print("filter="); ipw.println(cachedStickyBroadcast.filter.toLongString());
+ ipw.print("intent="); ipw.println(cachedStickyBroadcast.intent);
+ ipw.print("version="); ipw.println(cachedStickyBroadcast.version);
+ ipw.print("handle="); ipw.println(cachedStickyBroadcast.propertyHandle);
+ ipw.decreaseIndent();
+ }
+ }
+ ipw.decreaseIndent();
+ }
+
private static final class CachedStickyBroadcast {
@NonNull public final IntentFilter filter;
@Nullable public Intent intent;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 34d0f3b..0812a13 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1637,16 +1637,16 @@
public static final String EXTRA_PROGRESS_SEGMENTS = "android.progressSegments";
/**
- * {@link #extras} key: an arraylist of {@link android.app.Notification.ProgressStyle.Step}
+ * {@link #extras} key: an arraylist of {@link ProgressStyle.Point}
* bundles provided by a
* {@link android.app.Notification.ProgressStyle} notification as supplied to
- * {@link ProgressStyle#setProgressSteps}
- * or {@link ProgressStyle#addProgressStep(ProgressStyle.Step)}.
+ * {@link ProgressStyle#setProgressPoints}
+ * or {@link ProgressStyle#addProgressPoint(ProgressStyle.Point)}.
* This extra is a parcelable array list of bundles.
* @hide
*/
@FlaggedApi(Flags.FLAG_API_RICH_ONGOING)
- public static final String EXTRA_PROGRESS_STEPS = "android.progressSteps";
+ public static final String EXTRA_PROGRESS_POINTS = "android.progressPoints";
/**
* {@link #extras} key: whether the progress bar should be styled by its progress as
@@ -11159,7 +11159,7 @@
/**
* A Notification Style used to to define a notification whose expanded state includes
- * a highly customizable progress bar with segments, steps, a custom tracker icon,
+ * a highly customizable progress bar with segments, points, a custom tracker icon,
* and custom icons at the start and end of the progress bar.
*
* This style is suggested for use cases where the app is showing a tracker to the
@@ -11185,8 +11185,8 @@
* .addProgressSegment(new Segment(552).setColor(Color.YELLOW))
* .addProgressSegment(new Segment(253).setColor(Color.YELLOW))
* .addProgressSegment(new Segment(94).setColor(Color.BLUE))
- * .addProgressStep(new Step(60).setColor(Color.RED))
- * .addProgressStep(new Step(560).setColor(Color.YELLOW))
+ * .addProgressPoint(new Point(60).setColor(Color.RED))
+ * .addProgressPoint(new Point(560).setColor(Color.YELLOW))
* )
* </pre>
*
@@ -11202,14 +11202,14 @@
private static final String KEY_ELEMENT_ID = "id";
private static final String KEY_ELEMENT_COLOR = "colorInt";
private static final String KEY_SEGMENT_LENGTH = "length";
- private static final String KEY_STEP_POSITION = "position";
+ private static final String KEY_POINT_POSITION = "position";
private static final int MAX_PROGRESS_SEGMENT_LIMIT = 15;
- private static final int MAX_PROGRESS_STEP_LIMIT = 5;
+ private static final int MAX_PROGRESS_STOP_LIMIT = 5;
private static final int DEFAULT_PROGRESS_MAX = 100;
private List<Segment> mProgressSegments = new ArrayList<>();
- private List<Step> mProgressSteps = new ArrayList<>();
+ private List<Point> mProgressPoints = new ArrayList<>();
private int mProgress = 0;
@@ -11246,7 +11246,7 @@
nonIndeterminateCheckResult = !Objects.equals(mProgress, progressStyle.mProgress)
|| !Objects.equals(mIsStyledByProgress, progressStyle.mIsStyledByProgress)
|| !Objects.equals(mProgressSegments, progressStyle.mProgressSegments)
- || !Objects.equals(mProgressSteps, progressStyle.mProgressSteps)
+ || !Objects.equals(mProgressPoints, progressStyle.mProgressPoints)
|| !Objects.equals(mTrackerIcon, progressStyle.mTrackerIcon);
}
@@ -11300,48 +11300,47 @@
}
/**
- * Gets the steps that are displayed on the progress bar.
+ * Gets the points that are displayed on the progress bar.
*.
- * @see #setProgressSteps
- * @see #addProgressStep
- * @see Step
+ * @see #setProgressPoints
+ * @see #addProgressPoint
+ * @see Point
*/
- public @NonNull List<Step> getProgressSteps() {
- return mProgressSteps;
+ public @NonNull List<Point> getProgressPoints() {
+ return mProgressPoints;
}
/**
- * Replaces all the progress steps.
+ * Replaces all the progress points.
*
- * Steps are designated points within a progressbar to visualize
- * distinct stages or milestones.
- * For example, you might use steps to mark stops in a multi-stop
- * navigation journey, where each step represents a destination.
- * @see Step
+ * Points within a progress bar are used to visualize distinct stages or milestones.
+ * For example, you might use points to mark stops in a multi-stop
+ * navigation journey, where each point represents a destination.
+ * @see Point
*/
- public @NonNull ProgressStyle setProgressSteps(@NonNull List<Step> steps) {
- mProgressSteps = new ArrayList<>(steps);
+ public @NonNull ProgressStyle setProgressPoints(@NonNull List<Point> points) {
+ mProgressPoints = new ArrayList<>(points);
return this;
}
/**
- * Adds another step.
+ * Adds another point.
*
- * Steps are designated points within a progressbar to visualize
- * distinct stages or milestones.
- * For example, you might use steps to mark stops in a multi-stop
- * navigation journey, where each step represents a destination.
+ * Points within a progress bar are used to visualize distinct stages or milestones.
*
- * Steps can be added in any order, as their
+ * For example, you might use points to mark stops in a multi-stop
+ * navigation journey, where each point represents a destination.
+ *
+ * Points can be added in any order, as their
* position within the progress bar is determined by their individual
- * {@link Step#getPosition()}.
- * @see Step
+ * {@link Point#getPosition()}.
+ * @see Point
*/
- public @NonNull ProgressStyle addProgressStep(@NonNull Step step) {
- if (mProgressSteps == null) {
- mProgressSteps = new ArrayList<>();
+ public @NonNull ProgressStyle addProgressPoint(@NonNull Point point) {
+ if (mProgressPoints == null) {
+ mProgressPoints = new ArrayList<>();
}
- mProgressSteps.add(step);
+ mProgressPoints.add(point);
return this;
}
@@ -11414,7 +11413,7 @@
* When specified, the following fields are ignored:
* @see #setProgress
* @see #setProgressSegments
- * @see #setProgressSteps
+ * @see #setProgressPoints
* @see #setProgressTrackerIcon
* @see #setStyledByProgress
*
@@ -11435,7 +11434,7 @@
}
/**
- * Indicates whether the segments and steps will be styled differently
+ * Indicates whether the segments and points will be styled differently
* based on whether they are behind or ahead of the current progress.
* When true, segments appearing ahead of the current progress will be given a
* slightly different appearance to indicate that it is part of the progress bar
@@ -11558,8 +11557,8 @@
super.addExtras(extras);
extras.putParcelableArrayList(EXTRA_PROGRESS_SEGMENTS,
getProgressSegmentsAsBundleList(mProgressSegments));
- extras.putParcelableArrayList(EXTRA_PROGRESS_STEPS,
- getProgressStepsAsBundleList(mProgressSteps));
+ extras.putParcelableArrayList(EXTRA_PROGRESS_POINTS,
+ getProgressPointsAsBundleList(mProgressPoints));
extras.putInt(EXTRA_PROGRESS, mProgress);
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mIndeterminate);
@@ -11599,8 +11598,8 @@
mTrackerIcon = extras.getParcelable(EXTRA_PROGRESS_TRACKER_ICON, Icon.class);
mStartIcon = extras.getParcelable(EXTRA_PROGRESS_START_ICON, Icon.class);
mEndIcon = extras.getParcelable(EXTRA_PROGRESS_END_ICON, Icon.class);
- mProgressSteps = getProgressStepsFromBundleList(
- extras.getParcelableArrayList(EXTRA_PROGRESS_STEPS, Bundle.class));
+ mProgressPoints = getProgressPointsFromBundleList(
+ extras.getParcelableArrayList(EXTRA_PROGRESS_POINTS, Bundle.class));
}
/**
@@ -11613,6 +11612,30 @@
// actually be included.
return true;
}
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ final StandardTemplateParams p = mBuilder.mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL)
+ .hideProgress(true)
+ .fillTextsFrom(mBuilder);
+
+ return getStandardView(mBuilder.getBaseLayoutResource(), p, null /* result */);
+ }
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
+ final StandardTemplateParams p = mBuilder.mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP)
+ .hideProgress(true)
+ .fillTextsFrom(mBuilder);
+
+ return getStandardView(mBuilder.getHeadsUpBaseLayoutResource(), p, null /* result */);
+ }
private static @NonNull ArrayList<Bundle> getProgressSegmentsAsBundleList(
@Nullable List<Segment> progressSegments) {
@@ -11660,48 +11683,48 @@
return segments;
}
- private static @NonNull ArrayList<Bundle> getProgressStepsAsBundleList(
- @Nullable List<Step> progressSteps) {
- final ArrayList<Bundle> steps = new ArrayList<>();
- if (progressSteps != null && !progressSteps.isEmpty()) {
- for (int i = 0; i < progressSteps.size(); i++) {
- final Step step = progressSteps.get(i);
- if (step.getPosition() < 0) {
+ private static @NonNull ArrayList<Bundle> getProgressPointsAsBundleList(
+ @Nullable List<Point> progressPoints) {
+ final ArrayList<Bundle> points = new ArrayList<>();
+ if (progressPoints != null && !progressPoints.isEmpty()) {
+ for (int i = 0; i < progressPoints.size(); i++) {
+ final Point point = progressPoints.get(i);
+ if (point.getPosition() < 0) {
continue;
}
final Bundle bundle = new Bundle();
- bundle.putInt(KEY_STEP_POSITION, step.getPosition());
- bundle.putInt(KEY_ELEMENT_ID, step.getId());
- bundle.putInt(KEY_ELEMENT_COLOR, step.getColor());
+ bundle.putInt(KEY_POINT_POSITION, point.getPosition());
+ bundle.putInt(KEY_ELEMENT_ID, point.getId());
+ bundle.putInt(KEY_ELEMENT_COLOR, point.getColor());
- steps.add(bundle);
+ points.add(bundle);
}
}
- return steps;
+ return points;
}
- private static @NonNull List<Step> getProgressStepsFromBundleList(
- @Nullable List<Bundle> stepBundleList) {
- final ArrayList<Step> steps = new ArrayList<>();
+ private static @NonNull List<Point> getProgressPointsFromBundleList(
+ @Nullable List<Bundle> pointBundleList) {
+ final ArrayList<Point> points = new ArrayList<>();
- if (stepBundleList != null && !stepBundleList.isEmpty()) {
- for (int i = 0; i < stepBundleList.size(); i++) {
- final Bundle segmentBundle = stepBundleList.get(i);
- final int position = segmentBundle.getInt(KEY_STEP_POSITION);
+ if (pointBundleList != null && !pointBundleList.isEmpty()) {
+ for (int i = 0; i < pointBundleList.size(); i++) {
+ final Bundle pointBundle = pointBundleList.get(i);
+ final int position = pointBundle.getInt(KEY_POINT_POSITION);
if (position < 0) {
continue;
}
- final int id = segmentBundle.getInt(KEY_ELEMENT_ID);
- final int color = segmentBundle.getInt(KEY_ELEMENT_COLOR,
+ final int id = pointBundle.getInt(KEY_ELEMENT_ID);
+ final int color = pointBundle.getInt(KEY_ELEMENT_COLOR,
Notification.COLOR_DEFAULT);
- final Step step = new Step(position).setId(id).setColor(color);
- steps.add(step);
+ final Point point = new Point(position).setId(id).setColor(color);
+ points.add(point);
}
}
- return steps;
+ return points;
}
/**
@@ -11776,7 +11799,7 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- Segment segment = (Segment) o;
+ final Segment segment = (Segment) o;
return mLength == segment.mLength && mId == segment.mId
&& mColor == segment.mColor;
}
@@ -11788,13 +11811,12 @@
}
/**
- * A step within the progress bar, defining its position and color.
- * Steps are designated points within a progressbar to visualize
- * distinct stages or milestones.
- * For example, you might use steps to mark stops in a multi-stop
- * navigation journey, where each step represents a destination.
+ * A point within the progress bar, defining its position and color.
+ * Points within a progress bar are used to visualize distinct stages or milestones.
+ * For example, you might use points to mark stops in a multi-stop
+ * navigation journey, where each point represents a destination.
*/
- public static final class Step {
+ public static final class Point {
private int mPosition;
private int mId;
@@ -11802,19 +11824,19 @@
private int mColor = Notification.COLOR_DEFAULT;
/**
- * Create a step element.
- * The position of this step on the progress bar
+ * Create a point element.
+ * The position of this point on the progress bar
* relative to {@link ProgressStyle#getProgressMax}
* @param position
* See {@link #getPosition}
*/
- public Step(int position) {
+ public Point(int position) {
mPosition = position;
}
/**
- * Gets the position of this Step.
- * The position of this step on the progress bar
+ * Gets the position of this Point.
+ * The position of this point on the progress bar
* relative to {@link ProgressStyle#getProgressMax}.
*/
public int getPosition() {
@@ -11832,7 +11854,7 @@
/**
* Optional ID used to uniquely identify the element across updates.
*/
- public @NonNull Step setId(int id) {
+ public @NonNull Point setId(int id) {
mId = id;
return this;
}
@@ -11850,7 +11872,7 @@
/**
* Optional color of this Segment
*/
- public @NonNull Step setColor(@ColorInt int color) {
+ public @NonNull Point setColor(@ColorInt int color) {
mColor = color;
return this;
}
@@ -11862,9 +11884,9 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- Step step = (Step) o;
- return mPosition == step.mPosition && mId == step.mId
- && mColor == step.mColor;
+ final Point point = (Point) o;
+ return mPosition == point.mPosition && mId == point.mId
+ && mColor == point.mColor;
}
@Override
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index af242dd..e882bb5 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -275,7 +275,10 @@
public int parentTaskId;
/**
- * Whether this task is focused.
+ * Whether this task is focused on the display. This means the task receives input events that
+ * target the display.
+ * CAUTION: This can be true for multiple tasks especially when multiple displays are connected
+ * in the system.
* @hide
*/
public boolean isFocused;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index e598097..36e816a 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -455,6 +455,11 @@
public abstract void onPresentation(int displayId, boolean isShown);
/**
+ * Called upon the usage of stylus.
+ */
+ public abstract void stylusGestureStarted(long eventTime);
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b9b5295..c41e626 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3088,8 +3088,9 @@
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
- "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw",
- "Esw", "Ewa", "Elw", "Eec", "Esc", "Eds"
+ "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa",
+ "Etw", "Esw", "Ewa", "Elw", "Esc",
+ "Eds"
};
@FunctionalInterface
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 27b1dfb..d557046 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3027,6 +3027,46 @@
*/
@FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
public static final class DefaultAccount {
+ /**
+ * Key in the outgoing Bundle for the default account list.
+ *
+ * @hide
+ */
+ public static final String KEY_ELIGIBLE_DEFAULT_ACCOUNTS =
+ "key_eligible_default_accounts";
+ /**
+ * The method to invoke in order to query eligiblie default accounts.
+ *
+ * @hide
+ */
+ public static final String QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD =
+ "queryEligibleDefaultAccounts";
+ /**
+ * Key in the Bundle for the default account state.
+ *
+ * @hide
+ */
+ public static final String KEY_DEFAULT_ACCOUNT_STATE =
+ "key_default_account_state";
+ /**
+ * The method to invoke in order to set the default account.
+ *
+ * @hide
+ */
+ public static final String SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD =
+ "setDefaultAccountForNewContacts";
+ /**
+ * The method to invoke in order to query the default account.
+ *
+ * @hide
+ */
+ public static final String QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD =
+ "queryDefaultAccountForNewContacts";
+
+ private DefaultAccount() {
+
+ }
+
/**
* Represents the state of the default account, and the actual {@link Account} if it's
@@ -3228,6 +3268,94 @@
public @interface DefaultAccountState {
}
}
+
+ /**
+ * Get the account that is set as the default account for new contacts, which should be
+ * initially selected when creating a new contact on contact management apps.
+ *
+ * @param resolver the ContentResolver to query.
+ *
+ * @return the default account state for new contacts.
+ * @throws RuntimeException if failed to look up the default account.
+ * @throws IllegalStateException if the default account is in an invalid state.
+ */
+ @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
+ public static @NonNull DefaultAccountAndState getDefaultAccountForNewContacts(
+ @NonNull ContentResolver resolver) {
+ Bundle response = nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
+ QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, null);
+
+ int defaultContactsAccountState = response.getInt(KEY_DEFAULT_ACCOUNT_STATE, -1);
+ if (defaultContactsAccountState
+ == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
+ String accountName = response.getString(Settings.ACCOUNT_NAME);
+ String accountType = response.getString(Settings.ACCOUNT_TYPE);
+ if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
+ throw new IllegalStateException(
+ "account name and type cannot be null or empty");
+ }
+ return new DefaultAccountAndState(
+ DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD,
+ new Account(accountName, accountType));
+ } else if (defaultContactsAccountState
+ == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL
+ || defaultContactsAccountState
+ == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_NOT_SET) {
+ return new DefaultAccountAndState(defaultContactsAccountState, /*cloudAccount=*/
+ null);
+ } else {
+ throw new IllegalStateException("Invalid default account state");
+ }
+ }
+
+ /**
+ * Sets the default account that should be initially selected when creating a new
+ * contact on
+ * contact management apps. Apps can only set one of
+ * The following accounts as the default account:
+ * <ol>
+ * <li> local account
+ * <li> cloud account that are eligible to be set as default account.
+ * </ol>
+ *
+ * @param resolver the ContentResolver to query.
+ * @param defaultAccountAndState the default account and state to be set. To set the
+ * local
+ * account as the
+ * default account, this parameter should be
+ * {@link DefaultAccountAndState#ofLocal()}. To set the a
+ * cloud
+ * account as the default account, this parameter should
+ * be
+ * {@link DefaultAccountAndState#ofCloud(Account)}. To
+ * set
+ * the
+ * default account to a "not set" state, this parameter
+ * should
+ * be {@link DefaultAccountAndState#ofNotSet()}.
+ *
+ * @throws RuntimeException if it fails to set the default account.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS)
+ @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
+ @SystemApi
+ public static void setDefaultAccountForNewContacts(@NonNull ContentResolver resolver,
+ @NonNull DefaultAccountAndState defaultAccountAndState) {
+ Bundle extras = new Bundle();
+
+ extras.putInt(KEY_DEFAULT_ACCOUNT_STATE, defaultAccountAndState.getState());
+ if (defaultAccountAndState.getState()
+ == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
+ Account cloudAccount = defaultAccountAndState.getAccount();
+ assert cloudAccount != null;
+ extras.putString(Settings.ACCOUNT_NAME, cloudAccount.name);
+ extras.putString(Settings.ACCOUNT_TYPE, cloudAccount.type);
+ }
+ nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
+ SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, extras);
+ }
}
/**
@@ -9055,30 +9183,6 @@
public static final String KEY_DEFAULT_ACCOUNT = "key_default_account";
/**
- * Key in the Bundle for the default account state.
- *
- * @hide
- */
- public static final String KEY_DEFAULT_ACCOUNT_STATE =
- "key_default_contacts_account_state";
-
- /**
- * The method to invoke in order to set the default account.
- *
- * @hide
- */
- public static final String SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD =
- "setDefaultAccountForNewContacts";
-
- /**
- * The method to invoke in order to query the default account.
- *
- * @hide
- */
- public static final String QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD =
- "queryDefaultAccountForNewContacts";
-
- /**
* Get the account that is set as the default account for new contacts, which should be
* initially selected when creating a new contact on contact management apps.
* If the setting has not been set by any app, it will return null. Once the setting
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0582afe..381006c 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1345,7 +1345,7 @@
}
/**
- * <p>Sets the desired about of HDR headroom to be used when rendering as a ratio of
+ * <p>Sets the desired amount of HDR headroom to be used when rendering as a ratio of
* targetHdrPeakBrightnessInNits / targetSdrWhitePointInNits. Only applies when
* {@link #setColorMode(int)} is {@link ActivityInfo#COLOR_MODE_HDR}</p>
*
diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h
index 21b5b13..e3e17ee 100644
--- a/core/jni/jni_wrappers.h
+++ b/core/jni/jni_wrappers.h
@@ -79,13 +79,14 @@
jniMethodFormat = value;
}
-// Potentially translates the given JNINativeMethods if setJniMethodFormat has been set.
-// Has no effect otherwise
-inline const JNINativeMethod* maybeRenameJniMethods(const JNINativeMethod* gMethods,
- int numMethods) {
+// Register the native methods, potenially applying the jniMethodFormat if it has been set.
+static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className,
+ const JNINativeMethod* gMethods,
+ int numMethods) {
if (jniMethodFormat.empty()) {
- return gMethods;
+ return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
+
// Make a copy of gMethods with reformatted method names.
JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods];
LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods");
@@ -103,13 +104,17 @@
std::strcpy(modifiedNameChars, modifiedName.c_str());
modifiedMethods[i].name = modifiedNameChars;
}
- return modifiedMethods;
+ int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+ for (int i = 0; i < numMethods; i++) {
+ delete[] modifiedMethods[i].name;
+ }
+ delete[] modifiedMethods;
+ return res;
}
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods) {
- const JNINativeMethod* modifiedMethods = maybeRenameJniMethods(gMethods, numMethods);
- int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+ int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods);
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
return res;
}
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index e9b137c..48e2620 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -2301,13 +2301,13 @@
@Test
@EnableFlags(Flags.FLAG_API_RICH_ONGOING)
- public void progressStyle_onProgressStepChange_visiblyDifferent() {
+ public void progressStyle_onProgressPointChange_visiblyDifferent() {
final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.ProgressStyle()
- .addProgressStep(new Notification.ProgressStyle.Step(10)));
+ .addProgressPoint(new Notification.ProgressStyle.Point(10)));
final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.ProgressStyle()
- .addProgressStep(new Notification.ProgressStyle.Step(12)));
+ .addProgressPoint(new Notification.ProgressStyle.Point(12)));
assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2))
.isTrue();
@@ -2315,13 +2315,13 @@
@Test
@EnableFlags(Flags.FLAG_API_RICH_ONGOING)
- public void indeterminateProgressStyle_onProgressStepChange_visiblyNotDifferent() {
+ public void indeterminateProgressStyle_onProgressPointChange_visiblyNotDifferent() {
final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true)
- .addProgressStep(new Notification.ProgressStyle.Step(10)));
+ .addProgressPoint(new Notification.ProgressStyle.Point(10)));
final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true)
- .addProgressStep(new Notification.ProgressStyle.Step(12)));
+ .addProgressPoint(new Notification.ProgressStyle.Point(12)));
assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2))
.isFalse();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index ec235a5..2a90017 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -353,6 +353,11 @@
if (isDragging != mIsDragging) {
mIsDragging = isDragging;
updateSamplingState();
+
+ if (isDragging && mPositioner.isImeVisible()) {
+ // Hide the IME when dragging begins
+ mManager.hideCurrentInputMethod();
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
index b1b7d05..5a277316f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -19,6 +19,7 @@
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.protolog.ProtoLog
import com.android.internal.util.FrameworkStatsLog
+import com.android.window.flags.Flags
import com.android.wm.shell.EventLogTags
import com.android.wm.shell.protolog.ShellProtoLogGroup
@@ -79,7 +80,8 @@
)
logTaskUpdate(
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED,
- sessionId, taskUpdate)
+ sessionId, taskUpdate
+ )
}
/**
@@ -95,7 +97,8 @@
)
logTaskUpdate(
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED,
- sessionId, taskUpdate)
+ sessionId, taskUpdate
+ )
}
/**
@@ -111,7 +114,46 @@
)
logTaskUpdate(
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED,
- sessionId, taskUpdate)
+ sessionId, taskUpdate
+ )
+ }
+
+ /**
+ * Logs that a task resize event is starting with [taskSizeUpdate] within a
+ * Desktop mode [sessionId].
+ */
+ fun logTaskResizingStarted(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) {
+ if (!Flags.enableResizingMetrics()) return
+
+ ProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging task resize is starting, session: %s taskId: %s",
+ sessionId,
+ taskSizeUpdate.instanceId
+ )
+ logTaskSizeUpdated(
+ FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE,
+ sessionId, taskSizeUpdate
+ )
+ }
+
+ /**
+ * Logs that a task resize event is ending with [taskSizeUpdate] within a
+ * Desktop mode [sessionId].
+ */
+ fun logTaskResizingEnded(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) {
+ if (!Flags.enableResizingMetrics()) return
+
+ ProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging task resize is ending, session: %s taskId: %s",
+ sessionId,
+ taskSizeUpdate.instanceId
+ )
+ logTaskSizeUpdated(
+ FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE,
+ sessionId, taskSizeUpdate
+ )
}
private fun logTaskUpdate(taskEvent: Int, sessionId: Int, taskUpdate: TaskUpdate) {
@@ -162,6 +204,34 @@
)
}
+ private fun logTaskSizeUpdated(
+ resizingStage: Int,
+ sessionId: Int,
+ taskSizeUpdate: TaskSizeUpdate
+ ) {
+ FrameworkStatsLog.write(
+ DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID,
+ /* resize_trigger */
+ taskSizeUpdate.resizeTrigger?.trigger ?: ResizeTrigger.UNKNOWN_RESIZE_TRIGGER.trigger,
+ /* resizing_stage */
+ resizingStage,
+ /* input_method */
+ taskSizeUpdate.inputMethod?.method ?: InputMethod.UNKNOWN_INPUT_METHOD.method,
+ /* desktop_mode_session_id */
+ sessionId,
+ /* instance_id */
+ taskSizeUpdate.instanceId,
+ /* uid */
+ taskSizeUpdate.uid,
+ /* task_height */
+ taskSizeUpdate.taskHeight,
+ /* task_width */
+ taskSizeUpdate.taskWidth,
+ /* display_area */
+ taskSizeUpdate.displayArea
+ )
+ }
+
companion object {
/**
* Describes a task position and dimensions.
@@ -188,13 +258,35 @@
val visibleTaskCount: Int,
)
+ /**
+ * Describes a task size update (resizing, snapping or maximizing to
+ * stable bounds).
+ *
+ * @property resizeTrigger the trigger for task resize
+ * @property inputMethod the input method for resizing this task
+ * @property instanceId instance id of the task
+ * @property uid uid of the app associated with the task
+ * @property taskHeight height of the task in dp
+ * @property taskWidth width of the task in dp
+ * @property displayArea the display size of the screen in dp
+ */
+ data class TaskSizeUpdate(
+ val resizeTrigger: ResizeTrigger? = null,
+ val inputMethod: InputMethod? = null,
+ val instanceId: Int,
+ val uid: Int,
+ val taskHeight: Int,
+ val taskWidth: Int,
+ val displayArea: Int,
+ )
+
// Default value used when the task was not minimized.
@VisibleForTesting
const val UNSET_MINIMIZE_REASON =
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__UNSET_MINIMIZE
/** The reason a task was minimized. */
- enum class MinimizeReason (val reason: Int) {
+ enum class MinimizeReason(val reason: Int) {
TASK_LIMIT(
FrameworkStatsLog
.DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_TASK_LIMIT
@@ -211,7 +303,7 @@
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNSET_UNMINIMIZE
/** The reason a task was unminimized. */
- enum class UnminimizeReason (val reason: Int) {
+ enum class UnminimizeReason(val reason: Int) {
UNKNOWN(
FrameworkStatsLog
.DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_UNKNOWN
@@ -275,8 +367,88 @@
SCREEN_OFF(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF)
}
+ /**
+ * Enum ResizeTrigger mapped to the ResizeTrigger definition in
+ * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+ */
+ enum class ResizeTrigger(val trigger: Int) {
+ UNKNOWN_RESIZE_TRIGGER(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER
+ ),
+ CORNER(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER
+ ),
+ EDGE(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__EDGE_RESIZE_TRIGGER
+ ),
+ TILING_DIVIDER(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__TILING_DIVIDER_RESIZE_TRIGGER
+ ),
+ MAXIMIZE_BUTTON(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__MAXIMIZE_BUTTON_RESIZE_TRIGGER
+ ),
+ DOUBLE_TAP_APP_HEADER(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DOUBLE_TAP_APP_HEADER_RESIZE_TRIGGER
+ ),
+ DRAG_LEFT(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_LEFT_RESIZE_TRIGGER
+ ),
+ DRAG_RIGHT(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_RIGHT_RESIZE_TRIGGER
+ ),
+ SNAP_LEFT_MENU(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_LEFT_MENU_RESIZE_TRIGGER
+ ),
+ SNAP_RIGHT_MENU(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_RIGHT_MENU_RESIZE_TRIGGER
+ ),
+ }
+
+ /**
+ * Enum InputMethod mapped to the InputMethod definition in
+ * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+ */
+ enum class InputMethod(val method: Int) {
+ UNKNOWN_INPUT_METHOD(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD
+ ),
+ TOUCH(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCH_INPUT_METHOD
+ ),
+ STYLUS(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__STYLUS_INPUT_METHOD
+ ),
+ MOUSE(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__MOUSE_INPUT_METHOD
+ ),
+ TOUCHPAD(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCHPAD_INPUT_METHOD
+ ),
+ KEYBOARD(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__KEYBOARD_INPUT_METHOD
+ ),
+ }
+
private const val DESKTOP_MODE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED
private const val DESKTOP_MODE_TASK_UPDATE_ATOM_ID =
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE
+ private const val DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID =
+ FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 5daa3ee..ada1e0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -824,6 +824,7 @@
WindowInsets.Type.systemBars() & ~WindowInsets.Type.captionBar(),
false /* ignoreVisibility */);
relayoutParams.mCaptionTopPadding = systemBarInsets.top;
+ relayoutParams.mIsInsetSource = false;
}
// Report occluding elements as bounding rects to the insets system so that apps can
// draw in the empty space in the center:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 000beba1..f8aed41 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -346,7 +346,7 @@
private void updateCaptionInsets(RelayoutParams params, WindowContainerTransaction wct,
RelayoutResult<T> outResult, Rect taskBounds) {
- if (!mIsCaptionVisible) {
+ if (!mIsCaptionVisible || !params.mIsInsetSource) {
if (mWindowDecorationInsets != null) {
mWindowDecorationInsets.remove(wct);
mWindowDecorationInsets = null;
@@ -724,6 +724,7 @@
int mCaptionWidthId;
final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
int mInputFeatures;
+ boolean mIsInsetSource = true;
@InsetsSource.Flags int mInsetSourceFlags;
int mShadowRadiusId;
@@ -743,6 +744,7 @@
mCaptionWidthId = Resources.ID_NULL;
mOccludingCaptionElements.clear();
mInputFeatures = 0;
+ mIsInsetSource = true;
mInsetSourceFlags = 0;
mShadowRadiusId = Resources.ID_NULL;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
index 6a5719b..d7a132d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
@@ -16,15 +16,22 @@
package com.android.wm.shell.desktopmode
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
import com.android.internal.util.FrameworkStatsLog
import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.window.flags.Flags
import com.android.wm.shell.EventLogTags
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskSizeUpdate
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_MINIMIZE_REASON
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON
@@ -41,11 +48,15 @@
private val desktopModeEventLogger = DesktopModeEventLogger()
@JvmField
- @Rule
+ @Rule(order = 0)
val extendedMockitoRule = ExtendedMockitoRule.Builder(this)
.mockStatic(FrameworkStatsLog::class.java)
.mockStatic(EventLogTags::class.java).build()!!
+ @JvmField
+ @Rule(order = 1)
+ val setFlagsRule = SetFlagsRule()
+
@Test
fun logSessionEnter_enterReason() = runBlocking {
desktopModeEventLogger.logSessionEnter(sessionId = SESSION_ID, EnterReason.UNKNOWN_ENTER)
@@ -328,7 +339,65 @@
}
}
- companion object {
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS)
+ fun logTaskResizingStarted_logsTaskSizeUpdatedWithStartResizingStage() = runBlocking {
+ desktopModeEventLogger.logTaskResizingStarted(sessionId = SESSION_ID, createTaskSizeUpdate())
+
+ verify {
+ FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
+ /* resize_trigger */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+ /* resizing_stage */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE),
+ /* input_method */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD),
+ /* desktop_mode_session_id */
+ eq(SESSION_ID),
+ /* instance_id */
+ eq(TASK_SIZE_UPDATE.instanceId),
+ /* uid */
+ eq(TASK_SIZE_UPDATE.uid),
+ /* task_height */
+ eq(TASK_SIZE_UPDATE.taskHeight),
+ /* task_width */
+ eq(TASK_SIZE_UPDATE.taskWidth),
+ /* display_area */
+ eq(TASK_SIZE_UPDATE.displayArea),
+ )
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS)
+ fun logTaskResizingEnded_logsTaskSizeUpdatedWithEndResizingStage() = runBlocking {
+ desktopModeEventLogger.logTaskResizingEnded(sessionId = SESSION_ID, createTaskSizeUpdate())
+
+ verify {
+ FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
+ /* resize_trigger */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+ /* resizing_stage */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE),
+ /* input_method */
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD),
+ /* desktop_mode_session_id */
+ eq(SESSION_ID),
+ /* instance_id */
+ eq(TASK_SIZE_UPDATE.instanceId),
+ /* uid */
+ eq(TASK_SIZE_UPDATE.uid),
+ /* task_height */
+ eq(TASK_SIZE_UPDATE.taskHeight),
+ /* task_width */
+ eq(TASK_SIZE_UPDATE.taskWidth),
+ /* display_area */
+ eq(TASK_SIZE_UPDATE.displayArea),
+ )
+ }
+ }
+
+ private companion object {
private const val SESSION_ID = 1
private const val TASK_ID = 1
private const val TASK_UID = 1
@@ -337,12 +406,36 @@
private const val TASK_HEIGHT = 100
private const val TASK_WIDTH = 100
private const val TASK_COUNT = 1
+ private const val DISPLAY_AREA = 1000
private val TASK_UPDATE = TaskUpdate(
TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y,
visibleTaskCount = TASK_COUNT,
)
+ private val TASK_SIZE_UPDATE = TaskSizeUpdate(
+ resizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER,
+ inputMethod = InputMethod.UNKNOWN_INPUT_METHOD,
+ TASK_ID,
+ TASK_UID,
+ TASK_HEIGHT,
+ TASK_WIDTH,
+ DISPLAY_AREA,
+ )
+
+ private fun createTaskSizeUpdate(
+ resizeTrigger: ResizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER,
+ inputMethod: InputMethod = InputMethod.UNKNOWN_INPUT_METHOD,
+ ) = TaskSizeUpdate(
+ resizeTrigger,
+ inputMethod,
+ TASK_ID,
+ TASK_UID,
+ TASK_HEIGHT,
+ TASK_WIDTH,
+ DISPLAY_AREA,
+ )
+
private fun createTaskUpdate(
minimizeReason: MinimizeReason? = null,
unminimizeReason: UnminimizeReason? = null,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 3e7f3bd..ed752fd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -619,6 +619,27 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
+ public void updateRelayoutParams_header_notAnInsetsSourceInFullyImmersive() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false,
+ /* isStatusBarVisible */ true,
+ /* isKeyguardVisibleAndOccluded */ false,
+ /* inFullImmersiveMode */ true,
+ new InsetsState());
+
+ assertThat(relayoutParams.mIsInsetSource).isFalse();
+ }
+
+ @Test
@DisableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
public void updateRelayoutParams_header_statusBarInvisible_captionVisible() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 94cabc4..54dd15ba 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -650,6 +650,57 @@
}
@Test
+ public void testRelayout_notAnInsetsSource_doesNotAddInsets() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
+ .build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ mRelayoutParams.mIsInsetSource = false;
+ windowDecor.relayout(taskInfo);
+
+ // Never added.
+ verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
+ verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
+ }
+
+ @Test
+ public void testRelayout_notAnInsetsSource_hadInsetsBefore_removesInsets() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
+ .build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ mRelayoutParams.mIsCaptionVisible = true;
+ mRelayoutParams.mIsInsetSource = true;
+ windowDecor.relayout(taskInfo);
+
+ mRelayoutParams.mIsCaptionVisible = true;
+ mRelayoutParams.mIsInsetSource = false;
+ windowDecor.relayout(taskInfo);
+
+ // Insets should be removed.
+ verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(captionBar()));
+ verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()));
+ }
+
+ @Test
public void testClose_withExistingInsets_insetsRemoved() {
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController)
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index 588463c..e074a27 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -501,18 +501,13 @@
SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination, bool isShared) {
ATRACE_CALL();
SkGainmapInfo gainmapInfo;
- std::unique_ptr<SkStream> gainmapStream;
+ std::unique_ptr<SkAndroidCodec> gainmapCodec;
{
- ATRACE_NAME("getAndroidGainmap");
- if (!mCodec->getAndroidGainmap(&gainmapInfo, &gainmapStream)) {
+ ATRACE_NAME("getGainmapAndroidCodec");
+ if (!mCodec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec)) {
return SkCodec::kSuccess;
}
}
- auto gainmapCodec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream));
- if (!gainmapCodec) {
- ALOGW("Failed to create codec for gainmap stream");
- return SkCodec::kInvalidInput;
- }
ImageDecoder decoder{std::move(gainmapCodec)};
// Gainmap inherits the origin of the containing image
decoder.mOverrideOrigin.emplace(getOrigin());
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index 785aef3..49a7f73 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -183,14 +183,8 @@
needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
}
-static bool decodeGainmap(std::unique_ptr<SkStream> gainmapStream, const SkGainmapInfo& gainmapInfo,
+static bool decodeGainmap(std::unique_ptr<SkAndroidCodec> codec, const SkGainmapInfo& gainmapInfo,
sp<uirenderer::Gainmap>* outGainmap, const int sampleSize, float scale) {
- std::unique_ptr<SkAndroidCodec> codec;
- codec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream), nullptr);
- if (!codec) {
- ALOGE("Can not create a codec for Gainmap.");
- return false;
- }
SkColorType decodeColorType = kN32_SkColorType;
if (codec->getInfo().colorType() == kGray_8_SkColorType) {
decodeColorType = kGray_8_SkColorType;
@@ -613,15 +607,15 @@
bool hasGainmap = false;
SkGainmapInfo gainmapInfo;
- std::unique_ptr<SkStream> gainmapStream = nullptr;
+ std::unique_ptr<SkAndroidCodec> gainmapCodec;
sp<uirenderer::Gainmap> gainmap = nullptr;
if (result == SkCodec::kSuccess) {
- hasGainmap = codec->getAndroidGainmap(&gainmapInfo, &gainmapStream);
+ hasGainmap = codec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec);
}
if (hasGainmap) {
hasGainmap =
- decodeGainmap(std::move(gainmapStream), gainmapInfo, &gainmap, sampleSize, scale);
+ decodeGainmap(std::move(gainmapCodec), gainmapInfo, &gainmap, sampleSize, scale);
}
if (!isMutable && javaBitmap == NULL) {
diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp
index 6a65b82..f7e8e07 100644
--- a/libs/hwui/jni/BitmapRegionDecoder.cpp
+++ b/libs/hwui/jni/BitmapRegionDecoder.cpp
@@ -48,25 +48,14 @@
}
SkGainmapInfo gainmapInfo;
- std::unique_ptr<SkStream> gainmapStream;
+ std::unique_ptr<SkAndroidCodec> gainmapCodec;
std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD = nullptr;
- if (mainImageBRD->getAndroidGainmap(&gainmapInfo, &gainmapStream)) {
- sk_sp<SkData> data = nullptr;
- if (gainmapStream->getMemoryBase()) {
- // It is safe to make without copy because we'll hold onto the stream.
- data = SkData::MakeWithoutCopy(gainmapStream->getMemoryBase(),
- gainmapStream->getLength());
- } else {
- data = SkCopyStreamToData(gainmapStream.get());
- // We don't need to hold the stream anymore
- gainmapStream = nullptr;
- }
- gainmapBRD = skia::BitmapRegionDecoder::Make(std::move(data));
+ if (!mainImageBRD->getGainmapBitmapRegionDecoder(&gainmapInfo, &gainmapBRD)) {
+ gainmapBRD = nullptr;
}
- return std::unique_ptr<BitmapRegionDecoderWrapper>(
- new BitmapRegionDecoderWrapper(std::move(mainImageBRD), std::move(gainmapBRD),
- gainmapInfo, std::move(gainmapStream)));
+ return std::unique_ptr<BitmapRegionDecoderWrapper>(new BitmapRegionDecoderWrapper(
+ std::move(mainImageBRD), std::move(gainmapBRD), gainmapInfo));
}
SkEncodedImageFormat getEncodedFormat() { return mMainImageBRD->getEncodedFormat(); }
@@ -191,16 +180,14 @@
private:
BitmapRegionDecoderWrapper(std::unique_ptr<skia::BitmapRegionDecoder> mainImageBRD,
std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD,
- SkGainmapInfo info, std::unique_ptr<SkStream> stream)
+ SkGainmapInfo info)
: mMainImageBRD(std::move(mainImageBRD))
, mGainmapBRD(std::move(gainmapBRD))
- , mGainmapInfo(info)
- , mGainmapStream(std::move(stream)) {}
+ , mGainmapInfo(info) {}
std::unique_ptr<skia::BitmapRegionDecoder> mMainImageBRD;
std::unique_ptr<skia::BitmapRegionDecoder> mGainmapBRD;
SkGainmapInfo mGainmapInfo;
- std::unique_ptr<SkStream> mGainmapStream;
};
} // namespace android
diff --git a/libs/hwui/jni/graphics_jni_helpers.h b/libs/hwui/jni/graphics_jni_helpers.h
index 78db54a..91db134 100644
--- a/libs/hwui/jni/graphics_jni_helpers.h
+++ b/libs/hwui/jni/graphics_jni_helpers.h
@@ -80,9 +80,52 @@
return static_cast<T>(res);
}
+// Inline variable that specifies the method binding format.
+// The expected format is 'XX${method}XX', where ${method} represents the original method name.
+// This variable is shared across all translation units. This is treated as a global variable as
+// per C++ 17.
+inline std::string jniMethodFormat;
+
+inline static void setJniMethodFormat(std::string value) {
+ jniMethodFormat = value;
+}
+
+// Register the native methods, potenially applying the jniMethodFormat if it has been set.
+static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className,
+ const JNINativeMethod* gMethods,
+ int numMethods) {
+ if (jniMethodFormat.empty()) {
+ return jniRegisterNativeMethods(env, className, gMethods, numMethods);
+ }
+
+ // Make a copy of gMethods with reformatted method names.
+ JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods];
+ LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods");
+
+ size_t methodNamePos = jniMethodFormat.find("${method}");
+ LOG_ALWAYS_FATAL_IF(methodNamePos == std::string::npos,
+ "Invalid jniMethodFormat: could not find '${method}' in pattern");
+
+ for (int i = 0; i < numMethods; i++) {
+ modifiedMethods[i] = gMethods[i];
+ std::string modifiedName = jniMethodFormat;
+ modifiedName.replace(methodNamePos, 9, gMethods[i].name);
+ char* modifiedNameChars = new char[modifiedName.length() + 1];
+ LOG_ALWAYS_FATAL_IF(!modifiedNameChars, "Failed to allocate the new method name");
+ std::strcpy(modifiedNameChars, modifiedName.c_str());
+ modifiedMethods[i].name = modifiedNameChars;
+ }
+ int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+ for (int i = 0; i < numMethods; i++) {
+ delete[] modifiedMethods[i].name;
+ }
+ delete[] modifiedMethods;
+ return res;
+}
+
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods) {
- int res = jniRegisterNativeMethods(env, className, gMethods, numMethods);
+ int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods);
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
return res;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 9d56c77..744e97e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -30,9 +30,10 @@
import android.icu.text.NumberFormat;
import android.location.LocationManager;
import android.media.AudioManager;
+import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.TetheringManager;
-import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
import android.net.wifi.WifiInfo;
import android.os.BatteryManager;
import android.os.Build;
@@ -737,14 +738,9 @@
* @param networkCapabilities NetworkCapabilities of the network.
*/
@Nullable
- public static WifiInfo tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.getTransportInfo() == null
- || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) {
- return null;
- }
- VcnTransportInfo vcnTransportInfo =
- (VcnTransportInfo) networkCapabilities.getTransportInfo();
- return vcnTransportInfo.getWifiInfo();
+ public static WifiInfo tryGetWifiInfoForVcn(
+ ConnectivityManager connectivityMgr, NetworkCapabilities networkCapabilities) {
+ return VcnUtils.getWifiInfoFromVcnCaps(connectivityMgr, networkCapabilities);
}
/** Whether there is any incompatible chargers in the current UsbPort? */
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 015356e..cea3d17 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -30,6 +30,7 @@
import android.net.ScoredNetwork;
import android.net.TransportInfo;
import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -394,10 +395,7 @@
TransportInfo transportInfo = networkCapabilities.getTransportInfo();
if (transportInfo instanceof VcnTransportInfo) {
- // This VcnTransportInfo logic is copied from
- // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
- // re-used because it makes the logic here clearer.
- return ((VcnTransportInfo) transportInfo).getWifiInfo();
+ return VcnUtils.getWifiInfoFromVcnCaps(mConnectivityManager, networkCapabilities);
} else if (transportInfo instanceof WifiInfo) {
return (WifiInfo) transportInfo;
} else {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 3c634f0..011ffbc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -610,7 +610,7 @@
flag.getPackageName(),
flag.getFlagName(),
flag.getServerFlagValue(),
- false);
+ StorageRequestMessage.SERVER_ON_REBOOT);
}
if (flag.getHasLocalOverride()) {
@@ -619,7 +619,7 @@
flag.getPackageName(),
flag.getFlagName(),
flag.getLocalFlagValue(),
- true);
+ StorageRequestMessage.LOCAL_ON_REBOOT);
}
}
diff --git a/packages/SettingsProvider/test/AndroidTest.xml b/packages/SettingsProvider/test/AndroidTest.xml
index dccc2d3..541a294 100644
--- a/packages/SettingsProvider/test/AndroidTest.xml
+++ b/packages/SettingsProvider/test/AndroidTest.xml
@@ -32,7 +32,7 @@
<option name="package" value="com.android.providers.setting.test" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
- <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
- <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
+ <option name="exclude-annotation" value="com.android.bedstead.enterprise.annotations.RequireRunOnWorkProfile" />
+ <option name="exclude-annotation" value="com.android.bedstead.multiuser.annotations.RequireRunOnSecondaryUser" />
</test>
</configuration>
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
index e4898da..e86e727 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
@@ -31,10 +31,10 @@
import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
-import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
import com.android.bedstead.harrier.annotations.RequireFeature;
import com.android.bedstead.harrier.annotations.RequireRunOnInitialUser;
-import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
+import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser;
+import com.android.bedstead.multiuser.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.users.UserType;
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 2745f6e..4c6834c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -47,7 +47,6 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -60,7 +59,6 @@
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
@@ -70,7 +68,6 @@
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalConfiguration
@@ -82,6 +79,7 @@
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.NestedScrollBehavior
@@ -93,8 +91,9 @@
import com.android.systemui.res.R
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.session.ui.composable.rememberSession
+import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.ui.composable.ShadeHeader
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
@@ -112,18 +111,16 @@
val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder")
val HeadsUpNotificationPlaceholder =
ElementKey("HeadsUpNotificationPlaceholder", contentPicker = LowestZIndexContentPicker)
- val ShelfSpace = ElementKey("ShelfSpace")
val NotificationStackCutoffGuideline = ElementKey("NotificationStackCutoffGuideline")
}
-
- // Expansion fraction thresholds (between 0-1f) at which the corresponding value should be
- // at its maximum, given they are at their minimum value at expansion = 0f.
- object TransitionThresholds {
- const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f
- const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f
- }
}
+private val notificationsShadeContentKey: ContentKey
+ get() = if (DualShade.isEnabled) Overlays.NotificationsShade else Scenes.Shade
+
+private val quickSettingsShadeContentKey: ContentKey
+ get() = if (DualShade.isEnabled) Overlays.QuickSettingsShade else Scenes.QuickSettings
+
/**
* Adds the space where heads up notifications can appear in the scene. This should generally be the
* entire size of the scene.
@@ -146,7 +143,7 @@
// This element is sometimes opted out of the shared element system, so there
// can be multiple instances of it during a transition. Thus we need to
// determine which instance should feed its bounds to NSSL to avoid providing
- // conflicting values
+ // conflicting values.
val useBounds = useHunBounds()
if (useBounds) {
val positionInWindow = coordinates.positionInWindow()
@@ -157,8 +154,8 @@
" bounds=$boundsInWindow"
}
// Note: boundsInWindow doesn't scroll off the screen, so use
- // positionInWindow
- // for top bound, which can scroll off screen while snoozing
+ // positionInWindow for top bound, which can scroll off screen while
+ // snoozing.
stackScrollView.setHeadsUpTop(positionInWindow.y)
stackScrollView.setHeadsUpBottom(boundsInWindow.bottom)
}
@@ -285,7 +282,8 @@
shouldFillMaxSize: Boolean = true,
shouldReserveSpaceForNavBar: Boolean = true,
shouldIncludeHeadsUpSpace: Boolean = true,
- shadeMode: ShadeMode,
+ shouldShowScrim: Boolean = true,
+ supportNestedScrolling: Boolean,
onEmptySpaceClick: (() -> Unit)? = null,
modifier: Modifier = Modifier,
) {
@@ -293,6 +291,7 @@
val density = LocalDensity.current
val screenCornerRadius = LocalScreenCornerRadius.current
val scrimCornerRadius = dimensionResource(R.dimen.notification_scrim_corner_radius)
+ val scrimBackgroundColor = MaterialTheme.colorScheme.surface
val scrollState =
shadeSession.rememberSaveableSession(saver = ScrollState.Saver, key = null) {
ScrollState(initial = 0)
@@ -427,8 +426,14 @@
// completes.
if (
scrimOffset.value < 0 &&
- layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Gone) ||
- layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen)
+ (layoutState.isTransitioning(
+ from = notificationsShadeContentKey,
+ to = Scenes.Gone,
+ ) ||
+ layoutState.isTransitioning(
+ from = notificationsShadeContentKey,
+ to = Scenes.Lockscreen,
+ ))
) {
IntOffset(x = 0, y = (scrimOffset.value * expansionFraction).roundToInt())
} else if (
@@ -498,7 +503,7 @@
(expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f)
} else 1f
}
- .background(MaterialTheme.colorScheme.surface)
+ .thenIf(shouldShowScrim) { Modifier.background(scrimBackgroundColor) }
.thenIf(shouldFillMaxSize) { Modifier.fillMaxSize() }
.debugBackground(viewModel, DEBUG_BOX_COLOR)
) {
@@ -508,7 +513,7 @@
topBehavior = NestedScrollBehavior.EdgeWithPreview,
isExternalOverscrollGesture = { isCurrentGestureOverscroll.value },
)
- .thenIf(shadeMode == ShadeMode.Single) {
+ .thenIf(supportNestedScrolling) {
Modifier.nestedScroll(scrimNestedScrollConnection)
}
.stackVerticalOverscroll(coroutineScope) { scrollState.canScrollForward }
@@ -550,38 +555,6 @@
}
/**
- * This may be added to the lockscreen to provide a space to the start of the lock icon where the
- * short shelf has room to flow vertically below the lock icon, but to its start, allowing more
- * notifications to fit in the stack itself. (see: b/213934746)
- *
- * NOTE: this is totally unused for now; it is here to clarify the future plan
- */
-@Composable
-fun SceneScope.NotificationShelfSpace(
- viewModel: NotificationsPlaceholderViewModel,
- modifier: Modifier = Modifier,
-) {
- Text(
- text = "Shelf Space",
- modifier
- .element(key = Notifications.Elements.ShelfSpace)
- .fillMaxWidth()
- .onPlaced { coordinates: LayoutCoordinates ->
- debugLog(viewModel) {
- ("SHELF onPlaced:" +
- " size=${coordinates.size}" +
- " bounds=${coordinates.boundsInWindow()}")
- }
- }
- .clip(RoundedCornerShape(24.dp))
- .background(MaterialTheme.colorScheme.primaryContainer)
- .padding(16.dp),
- style = MaterialTheme.typography.titleLarge,
- color = MaterialTheme.colorScheme.onPrimaryContainer,
- )
-}
-
-/**
* A 0 height horizontal spacer to be placed at the bottom-most position in the current scene, where
* the notification contents (stack, footer, shelf) should be drawn.
*/
@@ -673,15 +646,19 @@
}
}
+private fun TransitionState.isOnLockscreen(): Boolean {
+ return currentScene == Scenes.Lockscreen && currentOverlays.isEmpty()
+}
+
private fun shouldUseLockscreenStackBounds(state: TransitionState): Boolean {
- return state is TransitionState.Idle && state.currentScene == Scenes.Lockscreen
+ return state is TransitionState.Idle && state.isOnLockscreen()
}
private fun shouldUseLockscreenHunBounds(state: TransitionState): Boolean {
return when (state) {
- is TransitionState.Idle -> state.currentScene == Scenes.Lockscreen
+ is TransitionState.Idle -> state.isOnLockscreen()
is TransitionState.Transition ->
- state.isTransitioning(from = Scenes.QuickSettings, to = Scenes.Lockscreen)
+ state.isTransitioning(from = quickSettingsShadeContentKey, to = Scenes.Lockscreen)
}
}
@@ -690,7 +667,7 @@
shouldPunchHoleBehindScrim: Boolean,
): Boolean {
return shouldPunchHoleBehindScrim ||
- state.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen)
+ state.isTransitioning(from = notificationsShadeContentKey, to = Scenes.Lockscreen)
}
private fun calculateCornerRadius(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index a22becc..5b99670 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -33,7 +33,6 @@
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.ui.composable.Overlay
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
import com.android.systemui.shade.ui.composable.OverlayShade
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
@@ -69,9 +68,7 @@
}
@Composable
- override fun ContentScope.Content(
- modifier: Modifier,
- ) {
+ override fun ContentScope.Content(modifier: Modifier) {
val viewModel =
rememberViewModel("NotificationsShadeOverlay-viewModel") {
contentViewModelFactory.create()
@@ -81,10 +78,7 @@
viewModel.notificationsPlaceholderViewModelFactory.create()
}
- OverlayShade(
- modifier = modifier,
- onScrimClicked = viewModel::onScrimClicked,
- ) {
+ OverlayShade(modifier = modifier, onScrimClicked = viewModel::onScrimClicked) {
Column {
ExpandedShadeHeader(
viewModelFactory = viewModel.shadeHeaderViewModelFactory,
@@ -102,7 +96,8 @@
shouldPunchHoleBehindScrim = false,
shouldFillMaxSize = false,
shouldReserveSpaceForNavBar = false,
- shadeMode = ShadeMode.Dual,
+ shouldShowScrim = false,
+ supportNestedScrolling = false,
modifier = Modifier.fillMaxWidth(),
)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 6304979..e27f46b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -100,7 +100,6 @@
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.ui.composable.CollapsedShadeHeader
import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
import com.android.systemui.shade.ui.composable.Shade
@@ -114,11 +113,9 @@
import javax.inject.Inject
import javax.inject.Named
import kotlin.math.roundToInt
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/** The Quick Settings (AKA "QS") scene shows the quick setting tiles. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class QuickSettingsScene
@Inject
@@ -427,7 +424,7 @@
maxScrimTop = { screenHeight },
shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim,
shouldIncludeHeadsUpSpace = false,
- shadeMode = ShadeMode.Single,
+ supportNestedScrolling = true,
modifier =
Modifier.fillMaxWidth()
.offset { IntOffset(x = 0, y = screenHeight.roundToInt()) }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index 9d5252e..340ac32 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -13,6 +13,8 @@
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition
import com.android.systemui.scene.ui.composable.transitions.bouncerToLockscreenPreview
+import com.android.systemui.scene.ui.composable.transitions.communalToBouncerTransition
+import com.android.systemui.scene.ui.composable.transitions.communalToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition
@@ -89,6 +91,8 @@
sharedElement(Notifications.Elements.NotificationStackPlaceholder, enabled = false)
sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false)
}
+ from(Scenes.Communal, to = Scenes.Shade) { communalToShadeTransition() }
+ from(Scenes.Communal, to = Scenes.Bouncer) { communalToBouncerTransition() }
// Overlay transitions
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
similarity index 65%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
rename to packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
index 15ed1b3..d7173fd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.scene.data.repository
+package com.android.systemui.scene.ui.composable.transitions
-import android.view.windowManagerService
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.compose.animation.scene.TransitionBuilder
-val Kosmos.systemGestureExclusionRepository by Fixture {
- SystemGestureExclusionRepository(windowManager = windowManagerService)
+fun TransitionBuilder.communalToBouncerTransition() {
+ toBouncerTransition()
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
similarity index 65%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
copy to packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
index 15ed1b3..ba920ac 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.scene.data.repository
+package com.android.systemui.scene.ui.composable.transitions
-import android.view.windowManagerService
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.compose.animation.scene.TransitionBuilder
-val Kosmos.systemGestureExclusionRepository by Fixture {
- SystemGestureExclusionRepository(windowManager = windowManagerService)
+fun TransitionBuilder.communalToShadeTransition() {
+ toShadeTransition()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
index 4c0efd2..dd37b53 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
@@ -1,29 +1,11 @@
package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.CubicBezierEasing
-import androidx.compose.animation.core.tween
-import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.TransitionBuilder
-import com.android.compose.animation.scene.UserActionDistance
import com.android.systemui.bouncer.ui.composable.Bouncer
-const val FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION = 0.5f
-const val FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f
-
fun TransitionBuilder.lockscreenToBouncerTransition() {
- spec = tween(durationMillis = 500)
-
- distance = UserActionDistance { fromSceneSize, _ ->
- fromSceneSize.height * FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION
- }
-
- translate(Bouncer.Elements.Content, y = 300.dp)
- fractionRange(end = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) {
- fade(Bouncer.Elements.Background)
- }
- fractionRange(start = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) {
- fade(Bouncer.Elements.Content)
- }
+ toBouncerTransition()
}
fun TransitionBuilder.bouncerToLockscreenPreview() {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
new file mode 100644
index 0000000..de76f70
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.ui.composable.transitions
+
+import androidx.compose.animation.core.tween
+import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.systemui.bouncer.ui.composable.Bouncer
+
+const val TO_BOUNCER_FADE_FRACTION = 0.5f
+private const val TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f
+
+fun TransitionBuilder.toBouncerTransition() {
+ spec = tween(durationMillis = 500)
+
+ distance = UserActionDistance { fromSceneSize, _ ->
+ fromSceneSize.height * TO_BOUNCER_SWIPE_DISTANCE_FRACTION
+ }
+
+ translate(Bouncer.Elements.Content, y = 300.dp)
+ fractionRange(end = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Background) }
+ fractionRange(start = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Content) }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
index 337f53a5..23c4f12 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
@@ -21,26 +21,20 @@
import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
-import com.android.compose.animation.scene.UserActionDistance
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.shade.ui.composable.OverlayShade
import com.android.systemui.shade.ui.composable.Shade
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
-fun TransitionBuilder.toNotificationsShadeTransition(
- durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.toNotificationsShadeTransition(durationScale: Double = 1.0) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
swipeSpec =
spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
)
- distance = UserActionDistance { fromSceneSize, orientation ->
- fromSceneSize.height.toFloat() * 2 / 3f
- }
-
+ scaleSize(OverlayShade.Elements.Panel, height = 0f)
translate(OverlayShade.Elements.Panel, Edge.Top)
fractionRange(end = .5f) { fade(OverlayShade.Elements.Scrim) }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index c6c42fc..3ec057b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -40,7 +40,6 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -89,7 +88,6 @@
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.view.MediaHost
-import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.COLLAPSED
import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.EXPANDED
import com.android.systemui.media.dagger.MediaModule.QS_PANEL
@@ -117,7 +115,6 @@
import javax.inject.Inject
import javax.inject.Named
import kotlin.math.roundToInt
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
object Shade {
@@ -128,23 +125,13 @@
}
object Dimensions {
- val ScrimCornerSize = 32.dp
val HorizontalPadding = 16.dp
val ScrimOverscrollLimit = 32.dp
const val ScrimVisibilityThreshold = 5f
}
-
- object Shapes {
- val Scrim =
- RoundedCornerShape(
- topStart = Dimensions.ScrimCornerSize,
- topEnd = Dimensions.ScrimCornerSize,
- )
- }
}
/** The shade scene shows scrolling list of notifications and some of the quick setting tiles. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class ShadeScene
@Inject
@@ -197,11 +184,11 @@
)
init {
- qqsMediaHost.expansion = MediaHostState.EXPANDED
+ qqsMediaHost.expansion = EXPANDED
qqsMediaHost.showsOnlyActiveMedia = true
qqsMediaHost.init(MediaHierarchyManager.LOCATION_QQS)
- qsMediaHost.expansion = MediaHostState.EXPANDED
+ qsMediaHost.expansion = EXPANDED
qsMediaHost.showsOnlyActiveMedia = false
qsMediaHost.init(MediaHierarchyManager.LOCATION_QS)
}
@@ -329,8 +316,7 @@
modifier =
modifier.thenIf(shouldPunchHoleBehindScrim) {
// Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this
- // scene
- // (and not the one under it) during a scene transition.
+ // scene (and not the one under it) during a scene transition.
Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
}
) {
@@ -382,8 +368,8 @@
stackScrollView = notificationStackScrollView,
viewModel = notificationsPlaceholderViewModel,
maxScrimTop = { maxNotifScrimTop.toFloat() },
- shadeMode = ShadeMode.Single,
shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim,
+ supportNestedScrolling = true,
onEmptySpaceClick =
viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable },
modifier =
@@ -601,7 +587,7 @@
maxScrimTop = { 0f },
shouldPunchHoleBehindScrim = false,
shouldReserveSpaceForNavBar = false,
- shadeMode = ShadeMode.Split,
+ supportNestedScrolling = false,
onEmptySpaceClick =
viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable },
modifier =
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 5fa5db8..085157a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -226,7 +226,6 @@
val fromSource = resolveSwipeSource(startedPosition)
val upOrLeft = resolveSwipe(pointersDown, fromSource, isUpOrLeft = true)
val downOrRight = resolveSwipe(pointersDown, fromSource, isUpOrLeft = false)
-
return if (fromSource == null) {
Swipes(
upOrLeft = null,
@@ -366,10 +365,18 @@
return 0f
}
+ val currentTransitionIrreversible =
+ if (swipeAnimation.isUpOrLeft) {
+ swipes.upOrLeftResult?.isIrreversible ?: false
+ } else {
+ swipes.downOrRightResult?.isIrreversible ?: false
+ }
+
val needNewTransition =
- hasReachedToContent ||
- result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
- result.transitionKey != swipeAnimation.contentTransition.key
+ !currentTransitionIrreversible &&
+ (hasReachedToContent ||
+ result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
+ result.transitionKey != swipeAnimation.contentTransition.key)
if (needNewTransition) {
// Make sure the current transition will finish to the right current scene.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index cec8883..c9a4d58 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -498,6 +498,12 @@
* bigger than 100% when the user released their finger. `
*/
open val requiresFullDistanceSwipe: Boolean,
+
+ /**
+ * Whether swiping back in the opposite direction past the origin point of the swipe can replace
+ * the action with the action for the opposite direction.
+ */
+ open val isIrreversible: Boolean = false,
) {
internal abstract fun toContent(currentScene: SceneKey): ContentKey
@@ -507,6 +513,7 @@
val toScene: SceneKey,
override val transitionKey: TransitionKey? = null,
override val requiresFullDistanceSwipe: Boolean = false,
+ override val isIrreversible: Boolean = false,
) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
override fun toContent(currentScene: SceneKey): ContentKey = toScene
}
@@ -516,6 +523,7 @@
val overlay: OverlayKey,
override val transitionKey: TransitionKey? = null,
override val requiresFullDistanceSwipe: Boolean = false,
+ override val isIrreversible: Boolean = false,
) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
override fun toContent(currentScene: SceneKey): ContentKey = overlay
}
@@ -558,7 +566,14 @@
* the user released their finger.
*/
requiresFullDistanceSwipe: Boolean = false,
- ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
+
+ /**
+ * Whether swiping back in the opposite direction past the origin point of the swipe can
+ * replace the action with the action for the opposite direction.
+ */
+ isIrreversible: Boolean = false,
+ ): UserActionResult =
+ ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe, isIrreversible)
/** A [UserActionResult] that shows [toOverlay]. */
operator fun invoke(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 302f207..ecef6be 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -507,6 +507,54 @@
}
@Test
+ fun onDragWithActionsInBothDirections_dragToOppositeDirectionReplacesAction() = runGestureTest {
+ // We are on SceneA. UP -> B, DOWN-> C.
+ val dragController = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
+ assertTransition(
+ currentScene = SceneA,
+ fromScene = SceneA,
+ toScene = SceneB,
+ progress = 0.2f,
+ )
+
+ // Reverse drag direction, it will replace the previous transition
+ dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
+ assertTransition(
+ currentScene = SceneA,
+ fromScene = SceneA,
+ toScene = SceneC,
+ progress = 0.3f,
+ )
+ }
+
+ @Test
+ fun onDragWithActionsInBothDirections_dragToOppositeDirectionNotReplaceable() = runGestureTest {
+ // We are on SceneA. UP -> B, DOWN-> C. The up swipe is not replaceable though.
+ mutableUserActionsA =
+ mapOf(Swipe.Up to UserActionResult(SceneB, isIrreversible = true), Swipe.Down to SceneC)
+ val dragController =
+ onDragStarted(
+ startedPosition = Offset(SCREEN_SIZE * 0.5f, SCREEN_SIZE * 0.5f),
+ overSlop = up(fractionOfScreen = 0.2f),
+ )
+ assertTransition(
+ currentScene = SceneA,
+ fromScene = SceneA,
+ toScene = SceneB,
+ progress = 0.2f,
+ )
+
+ // Reverse drag direction, it cannot replace the previous transition
+ dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
+ assertTransition(
+ currentScene = SceneA,
+ fromScene = SceneA,
+ toScene = SceneB,
+ progress = -0.3f,
+ )
+ }
+
+ @Test
fun onDragFromEdge_startTransitionToEdgeAction() = runGestureTest {
navigateToSceneC()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
index 0d369a3..97f2e56 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
@@ -67,7 +67,6 @@
import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.scene.ui.composable.SceneContainer
-import com.android.systemui.settings.displayTracker
import com.android.systemui.testKosmos
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.awaitCancellation
@@ -127,7 +126,7 @@
private val sceneContainerViewModel by lazy {
kosmos.sceneContainerViewModelFactory
- .create(view, kosmos.displayTracker.defaultDisplayId, {})
+ .create(view) {}
.apply { setTransitionState(transitionState) }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
index 58b59ff..755c4eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
@@ -85,7 +85,8 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
- assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
+ assertThat(actions?.get(Swipe.Down))
+ .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
setUpState(
isShadeTouchable = false,
@@ -102,7 +103,8 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
- assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
+ assertThat(actions?.get(Swipe.Down))
+ .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
}
@Test
@@ -120,7 +122,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
setUpState(
isShadeTouchable = false,
@@ -138,7 +140,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
}
@Test
@@ -156,7 +158,9 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Overlays.NotificationsShade))
+ .isEqualTo(
+ UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+ )
setUpState(
isShadeTouchable = false,
@@ -170,7 +174,9 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Overlays.NotificationsShade))
+ .isEqualTo(
+ UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+ )
}
private fun TestScope.setUpState(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index fb1bf28..6397979 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -303,7 +303,8 @@
// Top edge is not applicable in dual shade, as well as two-finger swipe.
assertThat(downDestination).isNull()
} else {
- assertThat(downDestination).isEqualTo(ShowOverlay(Overlays.NotificationsShade))
+ assertThat(downDestination)
+ .isEqualTo(ShowOverlay(Overlays.NotificationsShade, isIrreversible = true))
assertThat(downDestination?.transitionKey).isNull()
}
@@ -320,7 +321,7 @@
downWithTwoPointers -> assertThat(downFromTopRightDestination).isNull()
else -> {
assertThat(downFromTopRightDestination)
- .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade))
+ .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true))
assertThat(downFromTopRightDestination?.transitionKey).isNull()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index 5c47f55..47fae9f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -106,7 +106,7 @@
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.QuickSettings))
+ .isEqualTo(UserActionResult(Scenes.QuickSettings, isIrreversible = true))
}
@Test
@@ -118,7 +118,7 @@
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt
deleted file mode 100644
index efde1ec..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.scene.ui.viewmodel
-
-import android.graphics.Region
-import android.view.setSystemGestureExclusionRegion
-import androidx.compose.ui.geometry.Offset
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.lifecycle.activateIn
-import com.android.systemui.scene.sceneContainerGestureFilterFactory
-import com.android.systemui.settings.displayTracker
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SceneContainerGestureFilterTest : SysuiTestCase() {
-
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val displayId = kosmos.displayTracker.defaultDisplayId
-
- private val underTest = kosmos.sceneContainerGestureFilterFactory.create(displayId)
- private val activationJob = Job()
-
- @Test
- fun shouldFilterGesture_whenNoRegion_returnsFalse() =
- testScope.runTest {
- activate()
- setSystemGestureExclusionRegion(displayId, null)
- runCurrent()
-
- assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isFalse()
- }
-
- @Test
- fun shouldFilterGesture_whenOutsideRegion_returnsFalse() =
- testScope.runTest {
- activate()
- setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
- runCurrent()
-
- assertThat(underTest.shouldFilterGesture(Offset(300f, 100f))).isFalse()
- }
-
- @Test
- fun shouldFilterGesture_whenInsideRegion_returnsTrue() =
- testScope.runTest {
- activate()
- setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
- runCurrent()
-
- assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isTrue()
- }
-
- @Test(expected = IllegalStateException::class)
- fun shouldFilterGesture_beforeActivation_throws() =
- testScope.runTest {
- setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
- runCurrent()
-
- underTest.shouldFilterGesture(Offset(100f, 100f))
- }
-
- @Test(expected = IllegalStateException::class)
- fun shouldFilterGesture_afterCancellation_throws() =
- testScope.runTest {
- activate()
- setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
- runCurrent()
-
- cancel()
-
- underTest.shouldFilterGesture(Offset(100f, 100f))
- }
-
- private fun TestScope.activate() {
- underTest.activateIn(testScope, activationJob)
- runCurrent()
- }
-
- private fun TestScope.cancel() {
- activationJob.cancel()
- runCurrent()
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index a37f511..4ec0802 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -39,7 +39,6 @@
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.settings.displayTracker
import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
@@ -82,7 +81,6 @@
underTest =
kosmos.sceneContainerViewModelFactory.create(
view,
- kosmos.displayTracker.defaultDisplayId,
{ motionEventHandler ->
this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
},
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
index a0f6431..9d93a9c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
@@ -61,7 +61,7 @@
interactor,
kosmos.testDispatcher,
mockDialogDelegate,
- mockDialogEventLogger
+ mockDialogEventLogger,
)
@Test
@@ -97,7 +97,7 @@
assertThat(tiles?.size).isEqualTo(3)
with(tiles?.elementAt(0)!!) {
assertThat(this.text).isEqualTo("Disabled by other")
- assertThat(this.subtext).isEqualTo("Set up")
+ assertThat(this.subtext).isEqualTo("Not set")
assertThat(this.enabled).isEqualTo(false)
}
with(tiles?.elementAt(1)!!) {
@@ -323,10 +323,10 @@
assertThat(tiles!!).hasSize(6)
assertThat(tiles!![0].subtext).isEqualTo("When the going gets tough")
assertThat(tiles!![1].subtext).isEqualTo("On • When in Rome")
- assertThat(tiles!![2].subtext).isEqualTo("Set up")
+ assertThat(tiles!![2].subtext).isEqualTo("Not set")
assertThat(tiles!![3].subtext).isEqualTo("Off")
assertThat(tiles!![4].subtext).isEqualTo("On")
- assertThat(tiles!![5].subtext).isEqualTo("Set up")
+ assertThat(tiles!![5].subtext).isEqualTo("Not set")
}
@Test
@@ -387,7 +387,7 @@
}
with(tiles?.elementAt(2)!!) {
assertThat(this.stateDescription).isEqualTo("Off")
- assertThat(this.subtextDescription).isEqualTo("Set up")
+ assertThat(this.subtextDescription).isEqualTo("Not set")
}
with(tiles?.elementAt(3)!!) {
assertThat(this.stateDescription).isEqualTo("Off")
@@ -399,7 +399,7 @@
}
with(tiles?.elementAt(5)!!) {
assertThat(this.stateDescription).isEqualTo("Off")
- assertThat(this.subtextDescription).isEqualTo("Set up")
+ assertThat(this.subtextDescription).isEqualTo("Not set")
}
// All tiles have the same long click info
@@ -451,7 +451,7 @@
.setName("Active without manual")
.setActive(true)
.setManualInvocationAllowed(false)
- .build(),
+ .build()
)
)
runCurrent()
@@ -492,7 +492,7 @@
.setId("ID")
.setName("Disabled by other")
.setEnabled(false, /* byUser= */ false)
- .build(),
+ .build()
)
)
runCurrent()
@@ -500,7 +500,7 @@
assertThat(tiles?.size).isEqualTo(1)
with(tiles?.elementAt(0)!!) {
assertThat(this.text).isEqualTo("Disabled by other")
- assertThat(this.subtext).isEqualTo("Set up")
+ assertThat(this.subtext).isEqualTo("Not set")
assertThat(this.enabled).isEqualTo(false)
// Click the tile
@@ -519,7 +519,7 @@
// Check that nothing happened to the tile
with(tiles?.elementAt(0)!!) {
assertThat(this.text).isEqualTo("Disabled by other")
- assertThat(this.subtext).isEqualTo("Set up")
+ assertThat(this.subtext).isEqualTo("Not set")
assertThat(this.enabled).isEqualTo(false)
}
}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c76b35f..2ddaa56 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1120,7 +1120,7 @@
<string name="zen_mode_off">Off</string>
<!-- Modes: label for a mode that needs to be set up [CHAR LIMIT=35] -->
- <string name="zen_mode_set_up">Set up</string>
+ <string name="zen_mode_set_up">Not set</string>
<!-- Modes: label for a mode that cannot be manually turned on [CHAR LIMIT=35] -->
<string name="zen_mode_no_manual_invocation">Manage in settings</string>
@@ -1827,6 +1827,12 @@
<!-- Name of the alarm status bar icon. -->
<string name="status_bar_alarm">Alarm</string>
+ <!-- Format string for the content description of the icon that indicates that a Mode is on.
+ For example, if the mode name is Bedtime, this will be "Bedtime is on". This content
+ description will be associated to the mode icon in status bar, smartspace, and everyone else
+ where it might be displayed without text. [CHAR LIMIT=NONE] -->
+ <string name="active_mode_content_description"><xliff:g id="modeName" example="Do Not Disturb">%1$s</xliff:g> is on</string>
+
<!-- Wallet strings -->
<!-- Wallet empty state, title [CHAR LIMIT=32] -->
<string name="wallet_title">Wallet</string>
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt
index dc07cca..3bfc7a1 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt
@@ -19,8 +19,7 @@
import android.annotation.MainThread
import android.view.Display.DEFAULT_DISPLAY
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.FocusedDisplayRepoLog
@@ -43,15 +42,20 @@
class FocusedDisplayRepository
@Inject
constructor(
- @Application val scope: CoroutineScope,
- @Main private val mainExecutor: Executor,
+ @Background val backgroundScope: CoroutineScope,
+ @Background private val backgroundExecutor: Executor,
transitions: ShellTransitions,
@FocusedDisplayRepoLog logBuffer: LogBuffer,
) {
val focusedTask: Flow<Int> =
- conflatedCallbackFlow {
- val listener = FocusTransitionListener { displayId -> trySend(displayId) }
- transitions.setFocusTransitionListener(listener, mainExecutor)
+ conflatedCallbackFlow<Int> {
+ val listener =
+ object : FocusTransitionListener {
+ override fun onFocusedDisplayChanged(displayId: Int) {
+ trySend(displayId)
+ }
+ }
+ transitions.setFocusTransitionListener(listener, backgroundExecutor)
awaitClose { transitions.unsetFocusTransitionListener(listener) }
}
.onEach {
@@ -65,5 +69,5 @@
/** Provides the currently focused display. */
val focusedDisplayId: StateFlow<Int>
- get() = focusedTask.stateIn(scope, SharingStarted.Eagerly, DEFAULT_DISPLAY)
+ get() = focusedTask.stateIn(backgroundScope, SharingStarted.Eagerly, DEFAULT_DISPLAY)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index c0b9efaa..914730e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -25,7 +25,7 @@
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.composable.transitions.FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION
+import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -49,14 +49,12 @@
duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
edge = Edge.create(from = LOCKSCREEN, to = Scenes.Bouncer),
)
- .setupWithoutSceneContainer(
- edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER),
- )
+ .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER))
private val alphaForAnimationStep: (Float) -> Float =
when {
SceneContainerFlag.isEnabled -> { step ->
- 1f - Math.min((step / FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION), 1f)
+ 1f - Math.min((step / TO_BOUNCER_FADE_FRACTION), 1f)
}
else -> { step -> 1f - step }
}
@@ -64,7 +62,7 @@
val shortcutsAlpha: Flow<Float> =
transitionAnimation.sharedFlow(
duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
- onStep = alphaForAnimationStep
+ onStep = alphaForAnimationStep,
)
val lockscreenAlpha: Flow<Float> = shortcutsAlpha
@@ -76,8 +74,8 @@
duration = 250.milliseconds,
onStep = { 1f - it },
onCancel = { 0f },
- onFinish = { 0f }
+ onFinish = { 0f },
),
- flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f)
+ flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt
deleted file mode 100644
index a8d0777..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.data.repository
-
-import android.graphics.Region
-import android.view.ISystemGestureExclusionListener
-import android.view.IWindowManager
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
-import javax.inject.Inject
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-
-@SysUISingleton
-class SystemGestureExclusionRepository
-@Inject
-constructor(private val windowManager: IWindowManager) {
-
- /**
- * Returns [Flow] of the [Region] in which system gestures should be excluded on the display
- * identified with [displayId].
- */
- fun exclusionRegion(displayId: Int): Flow<Region?> {
- return conflatedCallbackFlow {
- val listener =
- object : ISystemGestureExclusionListener.Stub() {
- override fun onSystemGestureExclusionChanged(
- displayId: Int,
- restrictedRegion: Region?,
- unrestrictedRegion: Region?,
- ) {
- trySend(restrictedRegion)
- }
- }
- windowManager.registerSystemGestureExclusionListener(listener, displayId)
-
- awaitClose {
- windowManager.unregisterSystemGestureExclusionListener(listener, displayId)
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt
deleted file mode 100644
index 4cee874..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.domain.interactor
-
-import android.graphics.Region
-import com.android.systemui.scene.data.repository.SystemGestureExclusionRepository
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-
-class SystemGestureExclusionInteractor
-@Inject
-constructor(private val repository: SystemGestureExclusionRepository) {
-
- /**
- * Returns [Flow] of the [Region] in which system gestures should be excluded on the display
- * identified with [displayId].
- */
- fun exclusionRegion(displayId: Int): Flow<Region?> {
- return repository.exclusionRegion(displayId)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index a8be580..38f4e73 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -107,13 +107,7 @@
view.viewModel(
traceName = "SceneWindowRootViewBinder",
minWindowLifecycleState = WindowLifecycleState.ATTACHED,
- factory = {
- viewModelFactory.create(
- view,
- view.context.displayId,
- motionEventHandlerReceiver,
- )
- },
+ factory = { viewModelFactory.create(view, motionEventHandlerReceiver) },
) { viewModel ->
try {
view.setViewTreeOnBackPressedDispatcherOwner(
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt
deleted file mode 100644
index a1d915a..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.ui.viewmodel
-
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.geometry.Offset
-import com.android.systemui.lifecycle.ExclusiveActivatable
-import com.android.systemui.lifecycle.Hydrator
-import com.android.systemui.scene.domain.interactor.SystemGestureExclusionInteractor
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import kotlin.math.roundToInt
-
-/** Decides whether drag gestures should be filtered out in the scene container framework. */
-class SceneContainerGestureFilter
-@AssistedInject
-constructor(interactor: SystemGestureExclusionInteractor, @Assisted displayId: Int) :
- ExclusiveActivatable() {
-
- private val hydrator = Hydrator("SceneContainerGestureFilter.hydrator")
- private val exclusionRegion by
- hydrator.hydratedStateOf(
- traceName = "exclusionRegion",
- initialValue = null,
- source = interactor.exclusionRegion(displayId),
- )
-
- override suspend fun onActivated(): Nothing {
- hydrator.activate()
- }
-
- /**
- * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g.
- * ignored, `false` otherwise.
- *
- * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the
- * gesture.
- */
- fun shouldFilterGesture(startPosition: Offset): Boolean {
- check(isActive) { "Must be activated to use!" }
-
- return exclusionRegion?.contains(startPosition.x.roundToInt(), startPosition.y.roundToInt())
- ?: false
- }
-
- @AssistedFactory
- interface Factory {
- fun create(displayId: Int): SceneContainerGestureFilter
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index f505385..889380a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -19,7 +19,6 @@
import android.view.MotionEvent
import android.view.View
import androidx.compose.runtime.getValue
-import androidx.compose.ui.geometry.Offset
import com.android.app.tracing.coroutines.launch
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.DefaultEdgeDetector
@@ -61,10 +60,8 @@
shadeInteractor: ShadeInteractor,
private val splitEdgeDetector: SplitEdgeDetector,
private val logger: SceneLogger,
- gestureFilterFactory: SceneContainerGestureFilter.Factory,
hapticsViewModelFactory: SceneContainerHapticsViewModel.Factory,
@Assisted view: View,
- @Assisted displayId: Int,
@Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
) : ExclusiveActivatable() {
@@ -92,8 +89,6 @@
},
)
- private val gestureFilter: SceneContainerGestureFilter = gestureFilterFactory.create(displayId)
-
override suspend fun onActivated(): Nothing {
try {
// Sends a MotionEventHandler to the owner of the view-model so they can report
@@ -112,7 +107,6 @@
coroutineScope {
launch { hydrator.activate() }
- launch { gestureFilter.activate() }
launch("SceneContainerHapticsViewModel") { hapticsViewModel.activate() }
}
awaitCancellation()
@@ -262,17 +256,6 @@
}
}
- /**
- * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g.
- * ignored, `false` otherwise.
- *
- * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the
- * gesture.
- */
- fun shouldFilterGesture(startPosition: Offset): Boolean {
- return gestureFilter.shouldFilterGesture(startPosition)
- }
-
/** Defines interface for classes that can handle externally-reported [MotionEvent]s. */
interface MotionEventHandler {
/** Notifies that a [MotionEvent] has occurred. */
@@ -289,7 +272,6 @@
interface Factory {
fun create(
view: View,
- displayId: Int,
motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
): SceneContainerViewModel
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
index 65b6231..e5f6846 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
@@ -30,41 +30,47 @@
fun singleShadeActions(
requireTwoPointersForTopEdgeForQs: Boolean = false
): Array<Pair<UserAction, UserActionResult>> {
+ val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true)
+ val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true)
return arrayOf(
// Swiping down, not from the edge, always goes to shade.
- Swipe.Down to Scenes.Shade,
- swipeDown(pointerCount = 2) to Scenes.Shade,
+ Swipe.Down to shadeUserActionResult,
+ swipeDown(pointerCount = 2) to shadeUserActionResult,
// Swiping down from the top edge.
swipeDownFromTop(pointerCount = 1) to
if (requireTwoPointersForTopEdgeForQs) {
- Scenes.Shade
+ shadeUserActionResult
} else {
- Scenes.QuickSettings
+ qsSceneUserActionResult
},
- swipeDownFromTop(pointerCount = 2) to Scenes.QuickSettings,
+ swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult,
)
}
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */
fun splitShadeActions(): Array<Pair<UserAction, UserActionResult>> {
- val splitShadeSceneKey = UserActionResult(Scenes.Shade, ToSplitShade)
+ val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)
return arrayOf(
// Swiping down, not from the edge, always goes to shade.
- Swipe.Down to splitShadeSceneKey,
- swipeDown(pointerCount = 2) to splitShadeSceneKey,
+ Swipe.Down to shadeUserActionResult,
+ swipeDown(pointerCount = 2) to shadeUserActionResult,
// Swiping down from the top edge goes to QS.
- swipeDownFromTop(pointerCount = 1) to splitShadeSceneKey,
- swipeDownFromTop(pointerCount = 2) to splitShadeSceneKey,
+ swipeDownFromTop(pointerCount = 1) to shadeUserActionResult,
+ swipeDownFromTop(pointerCount = 2) to shadeUserActionResult,
)
}
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the dual shade. */
fun dualShadeActions(): Array<Pair<UserAction, UserActionResult>> {
+ val notifShadeUserActionResult =
+ UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+ val qsShadeuserActionResult =
+ UserActionResult.ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true)
return arrayOf(
- Swipe.Down to Overlays.NotificationsShade,
+ Swipe.Down to notifShadeUserActionResult,
Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
- Overlays.QuickSettingsShade,
+ qsShadeuserActionResult,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index e3c47a4..321593b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -596,7 +596,8 @@
// NetworkCapabilities, but we need to convert it into TRANSPORT_WIFI in order to
// distinguish it from VCN over Cellular.
if (transportTypes[i] == NetworkCapabilities.TRANSPORT_CELLULAR
- && Utils.tryGetWifiInfoForVcn(networkCapabilities) != null) {
+ && Utils.tryGetWifiInfoForVcn(mConnectivityManager, networkCapabilities)
+ != null) {
transportTypes[i] = NetworkCapabilities.TRANSPORT_WIFI;
break;
}
@@ -1112,7 +1113,9 @@
continue;
}
if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR
- && Utils.tryGetWifiInfoForVcn(mLastDefaultNetworkCapabilities) != null) {
+ && Utils.tryGetWifiInfoForVcn(
+ mConnectivityManager, mLastDefaultNetworkCapabilities)
+ != null) {
mConnectedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
mValidatedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 8c80fd4..36e3e92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -203,13 +203,16 @@
messagingStyle = mConversationProcessor
.processNotification(entry, builder, mLogger);
}
- result.mInflatedSingleLineViewModel = SingleLineViewInflater
+ SingleLineViewModel viewModel = SingleLineViewInflater
.inflateSingleLineViewModel(
entry.getSbn().getNotification(),
messagingStyle,
builder,
row.getContext()
);
+ // If the messagingStyle is null, we want to inflate the normal view
+ isConversation = viewModel.isConversation();
+ result.mInflatedSingleLineViewModel = viewModel;
result.mInflatedSingleLineView =
SingleLineViewInflater.inflatePrivateSingleLineView(
isConversation,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
index 3b0f1ee..a17197c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
@@ -24,14 +24,14 @@
object SingleLineViewBinder {
@JvmStatic
fun bind(viewModel: SingleLineViewModel?, view: HybridNotificationView?) {
- if (viewModel?.isConversation() == true && view is HybridConversationNotificationView) {
+ if (view is HybridConversationNotificationView) {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
- viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
+ viewModel?.conversationData?.avatar?.let { view.setAvatar(it) }
view.setText(
- viewModel.titleText,
- viewModel.contentText,
- viewModel.conversationData?.conversationSenderName
+ viewModel?.titleText,
+ viewModel?.contentText,
+ viewModel?.conversationData?.conversationSenderName,
)
} else {
// bind the title and content text views
@@ -39,7 +39,7 @@
bind(
/* title = */ viewModel?.titleText,
/* text = */ viewModel?.contentText,
- /* contentView = */ null
+ /* contentView = */ null,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
index c9eaec7..aec81b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
@@ -84,9 +84,9 @@
private fun fullyExpandedDuringSceneChange(change: ChangeScene): Boolean {
// The lockscreen stack is visible during all transitions away from the lockscreen, so keep
// the stack expanded until those transitions finish.
- return if (change.isFrom({ it == Scenes.Lockscreen }, to = { true })) {
+ return if (change.isTransitioning(from = Scenes.Lockscreen)) {
true
- } else if (change.isFrom({ it == Scenes.Shade }, to = { it == Scenes.Lockscreen })) {
+ } else if (change.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen)) {
false
} else {
(expandedInScene(change.fromScene) && expandedInScene(change.toScene))
@@ -101,11 +101,11 @@
return if (fullyExpandedDuringSceneChange(change)) {
1f
} else if (
- change.isBetween({ it == Scenes.Gone }, { it == Scenes.Shade }) ||
- change.isFrom({ it == Scenes.Shade }, to = { it == Scenes.Lockscreen })
+ change.isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
+ change.isTransitioning(from = Scenes.Gone, to = Scenes.Lockscreen)
) {
shadeExpansion
- } else if (change.isBetween({ it == Scenes.Gone }, { it == Scenes.QuickSettings })) {
+ } else if (change.isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings)) {
// during QS expansion, increase fraction at same rate as scrim alpha,
// but start when scrim alpha is at EXPANSION_FOR_DELAYED_STACK_FADE_IN.
(qsExpansion / EXPANSION_FOR_MAX_SCRIM_ALPHA - EXPANSION_FOR_DELAYED_STACK_FADE_IN)
@@ -213,7 +213,11 @@
private val qsAllowsClipping: Flow<Boolean> =
combine(shadeInteractor.shadeMode, shadeInteractor.qsExpansion) { shadeMode, qsExpansion ->
- qsExpansion < 0.5f || shadeMode != ShadeMode.Single
+ when (shadeMode) {
+ is ShadeMode.Dual -> false
+ is ShadeMode.Split -> true
+ is ShadeMode.Single -> qsExpansion < 0.5f
+ }
}
.distinctUntilChanged()
@@ -325,9 +329,3 @@
fun create(): NotificationScrollViewModel
}
}
-
-private fun ChangeScene.isBetween(a: (SceneKey) -> Boolean, b: (SceneKey) -> Boolean): Boolean =
- (a(fromScene) && b(toScene)) || (b(fromScene) && a(toScene))
-
-private fun ChangeScene.isFrom(from: (SceneKey) -> Boolean, to: (SceneKey) -> Boolean): Boolean =
- from(fromScene) && to(toScene)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 8c03538..f8eae36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -411,7 +411,8 @@
mainActiveMode.getIcon().key().resPackage(),
mainActiveMode.getIcon().key().resId(),
mainActiveMode.getIcon().drawable(),
- mainActiveMode.getName(),
+ mResources.getString(R.string.active_mode_content_description,
+ mainActiveMode.getName()),
StatusBarIcon.Shape.FIXED_SPACE);
}
if (visible != mZenVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
index 6764839c..4f595ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
@@ -76,7 +76,7 @@
// can be manually toggled on
mode.rule.isEnabled -> mode.isActive || mode.rule.isManualInvocationAllowed
// Mode was created as disabled, or disabled by the app that owns it ->
- // will be shown with a "Set up" text
+ // will be shown with a "Not set" text
!mode.rule.isEnabled -> mode.status == ZenMode.Status.DISABLED_BY_OTHER
else -> false
}
@@ -120,7 +120,7 @@
},
onLongClick = { openSettings(mode) },
onLongClickLabel =
- context.resources.getString(R.string.accessibility_long_click_tile)
+ context.resources.getString(R.string.accessibility_long_click_tile),
)
}
}
@@ -137,10 +137,10 @@
/**
* Returns a description of the mode, which is:
- * * a prompt to set up the mode if it is not enabled
- * * if it cannot be manually activated, text that says so
- * * otherwise, the trigger description of the mode if it exists...
- * * ...or null if it doesn't
+ * * a prompt to set up the mode if it is not enabled
+ * * if it cannot be manually activated, text that says so
+ * * otherwise, the trigger description of the mode if it exists...
+ * * ...or null if it doesn't
*
* This description is used directly for the content description of a mode tile for screen
* readers, and for the tile subtext will be augmented with the current status of the mode.
@@ -174,7 +174,7 @@
context,
R.style.Theme_SystemUI_Dialog,
/* cancelIsNeutral= */ true,
- zenDialogMetricsLogger
+ zenDialogMetricsLogger,
)
.createDialog()
SystemUIDialog.applyFlags(dialog)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 98315d0c..83dbfa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -95,6 +95,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class NetworkControllerBaseTest extends SysuiTestCase {
@@ -332,10 +333,15 @@
}
public void setConnectivityViaCallbackInNetworkControllerForVcn(
- int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+ int networkType,
+ boolean validated,
+ boolean isConnected,
+ VcnTransportInfo info,
+ Network underlyingNetwork) {
final NetworkCapabilities.Builder builder =
new NetworkCapabilities.Builder(mNetCapabilities);
- builder.setTransportInfo(info);
+ builder.setTransportInfo(info)
+ .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
setConnectivityCommon(builder, networkType, validated, isConnected);
mDefaultCallbackInNetworkController.onCapabilitiesChanged(
mock(Network.class), builder.build());
@@ -385,10 +391,15 @@
}
public void setConnectivityViaCallbackInWifiTrackerForVcn(
- int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+ int networkType,
+ boolean validated,
+ boolean isConnected,
+ VcnTransportInfo info,
+ Network underlyingNetwork) {
final NetworkCapabilities.Builder builder =
new NetworkCapabilities.Builder(mNetCapabilities);
- builder.setTransportInfo(info);
+ builder.setTransportInfo(info)
+ .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
setConnectivityCommon(builder, networkType, validated, isConnected);
if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) {
if (isConnected) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
index 6c80a97..6febb91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
@@ -18,6 +18,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static junit.framework.Assert.assertEquals;
@@ -250,6 +251,17 @@
assertEquals(testSsid, mNetworkController.mWifiSignalController.mCurrentState.ssid);
}
+ private Network newWifiNetwork(WifiInfo wifiInfo) {
+ final Network network = mock(Network.class);
+ final NetworkCapabilities wifiCaps =
+ new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(wifiInfo)
+ .build();
+ when(mMockCm.getNetworkCapabilities(network)).thenReturn(wifiCaps);
+ return network;
+ }
+
@Test
public void testVcnWithUnderlyingWifi() {
String testSsid = "Test VCN SSID";
@@ -266,11 +278,19 @@
setWifiLevelForVcn(testLevel);
setConnectivityViaCallbackInNetworkControllerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, true, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ true,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, true);
setConnectivityViaCallbackInNetworkControllerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, false);
}
}
@@ -391,13 +411,15 @@
}
protected void setWifiLevelForVcn(int level) {
- when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
- when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getRssi()).thenReturn(calculateRssiForLevel(level));
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
setConnectivityViaCallbackInWifiTrackerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
}
private int calculateRssiForLevel(int level) {
@@ -409,13 +431,15 @@
}
protected void setWifiStateForVcn(boolean connected, String ssid) {
- when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
- when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getSSID()).thenReturn(ssid);
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
setConnectivityViaCallbackInWifiTrackerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, connected, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ connected,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
}
protected void verifyLastQsDataDirection(boolean in, boolean out) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index 6b3fb5b..503fa78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -29,12 +29,13 @@
import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePublicSingleLineView
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
-import com.android.systemui.util.mockito.mock
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
+import kotlin.test.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -69,7 +70,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
val publicView =
@@ -78,7 +79,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
assertNotNull(publicView)
@@ -114,7 +115,7 @@
.addMessage(
"How about lunch?",
System.currentTimeMillis(),
- Person.Builder().setName("user2").build()
+ Person.Builder().setName("user2").build(),
)
.setGroupConversation(true)
notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
@@ -127,7 +128,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
as HybridConversationNotificationView
@@ -137,7 +138,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
as HybridConversationNotificationView
assertNotNull(publicView)
@@ -150,10 +151,7 @@
systemUiContext = context,
)
// WHEN: binds the view
- SingleLineViewBinder.bind(
- viewModel,
- view,
- )
+ SingleLineViewBinder.bind(viewModel, view)
// THEN: the single-line conversation view should be bound with view model's corresponding
// fields
@@ -161,10 +159,55 @@
assertEquals(viewModel.contentText, view.textView.text)
assertEquals(
viewModel.conversationData?.conversationSenderName,
- view.conversationSenderNameView.text
+ view.conversationSenderNameView.text,
)
}
+ @Test
+ @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
+ fun bindConversationSingleLineView_nonConversationViewModel() {
+ // GIVEN: a ConversationSingleLineView, and a nonConversationViewModel
+ val style = Notification.BigTextStyle().bigText(CONTENT_TEXT)
+ notificationBuilder.setStyle(style)
+ val notification = notificationBuilder.build()
+ val row: ExpandableNotificationRow = helper.createRow(notification)
+
+ val view =
+ inflatePrivateSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+ assertNotNull(publicView)
+
+ val viewModel =
+ SingleLineViewInflater.inflateSingleLineViewModel(
+ notification = notification,
+ messagingStyle = null,
+ builder = notificationBuilder,
+ systemUiContext = context,
+ )
+ // WHEN: binds the view with the view model
+ SingleLineViewBinder.bind(viewModel, view)
+
+ // THEN: the single-line view should be bound with view model's corresponding
+ // fields as a normal non-conversation single-line view
+ assertEquals(viewModel.titleText, view?.titleView?.text)
+ assertEquals(viewModel.contentText, view?.textView?.text)
+ assertNull(viewModel.conversationData)
+ }
+
private companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CONTENT_TITLE = "A Cool New Feature"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 2ed3473..8360042 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -160,11 +160,11 @@
testableLooper = TestableLooper.get(this)
context.orCreateTestableResources.addOverride(
com.android.internal.R.string.status_bar_alarm_clock,
- ALARM_SLOT
+ ALARM_SLOT,
)
context.orCreateTestableResources.addOverride(
com.android.internal.R.string.status_bar_managed_profile,
- MANAGED_PROFILE_SLOT
+ MANAGED_PROFILE_SLOT,
)
whenever(devicePolicyManager.resources).thenReturn(devicePolicyManagerResources)
whenever(devicePolicyManagerResources.getString(anyString(), any())).thenReturn("")
@@ -430,8 +430,8 @@
eq(mContext.packageName),
eq(android.R.drawable.ic_lock_lock),
any(), // non-null
- eq("Bedtime Mode"),
- eq(StatusBarIcon.Shape.FIXED_SPACE)
+ eq("Bedtime Mode is on"),
+ eq(StatusBarIcon.Shape.FIXED_SPACE),
)
zenModeRepository.deactivateMode("bedtime")
@@ -443,8 +443,8 @@
eq(null),
eq(android.R.drawable.ic_media_play),
any(), // non-null
- eq("Other Mode"),
- eq(StatusBarIcon.Shape.FIXED_SPACE)
+ eq("Other Mode is on"),
+ eq(StatusBarIcon.Shape.FIXED_SPACE),
)
zenModeRepository.deactivateMode("other")
@@ -538,7 +538,7 @@
privacyLogger,
fakeConnectedDisplayStateProvider,
kosmos.zenModeInteractor,
- JavaAdapter(testScope.backgroundScope)
+ JavaAdapter(testScope.backgroundScope),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index f842db4..020f0a6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -8,17 +8,14 @@
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.domain.interactor.systemGestureExclusionInteractor
import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.FakeOverlay
-import com.android.systemui.scene.ui.viewmodel.SceneContainerGestureFilter
import com.android.systemui.scene.ui.viewmodel.SceneContainerHapticsViewModel
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
-import com.android.systemui.settings.displayTracker
import com.android.systemui.shade.domain.interactor.shadeInteractor
import kotlinx.coroutines.flow.MutableStateFlow
import org.mockito.kotlin.mock
@@ -72,16 +69,15 @@
}
val Kosmos.sceneContainerViewModel by Fixture {
- sceneContainerViewModelFactory.create(mock<View>(), displayTracker.defaultDisplayId, {}).apply {
- setTransitionState(transitionState)
- }
+ sceneContainerViewModelFactory
+ .create(mock<View>()) {}
+ .apply { setTransitionState(transitionState) }
}
val Kosmos.sceneContainerViewModelFactory by Fixture {
object : SceneContainerViewModel.Factory {
override fun create(
view: View,
- displayId: Int,
motionEventHandlerReceiver: (SceneContainerViewModel.MotionEventHandler?) -> Unit,
): SceneContainerViewModel =
SceneContainerViewModel(
@@ -91,26 +87,13 @@
shadeInteractor = shadeInteractor,
splitEdgeDetector = splitEdgeDetector,
logger = sceneLogger,
- gestureFilterFactory = sceneContainerGestureFilterFactory,
hapticsViewModelFactory = sceneContainerHapticsViewModelFactory,
view = view,
- displayId = displayId,
motionEventHandlerReceiver = motionEventHandlerReceiver,
)
}
}
-val Kosmos.sceneContainerGestureFilterFactory by Fixture {
- object : SceneContainerGestureFilter.Factory {
- override fun create(displayId: Int): SceneContainerGestureFilter {
- return SceneContainerGestureFilter(
- interactor = systemGestureExclusionInteractor,
- displayId = displayId,
- )
- }
- }
-}
-
val Kosmos.sceneContainerHapticsViewModelFactory by Fixture {
object : SceneContainerHapticsViewModel.Factory {
override fun create(view: View): SceneContainerHapticsViewModel {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt
deleted file mode 100644
index 3e46c3f..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.domain.interactor
-
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.data.repository.systemGestureExclusionRepository
-
-val Kosmos.systemGestureExclusionInteractor by Fixture {
- SystemGestureExclusionInteractor(repository = systemGestureExclusionRepository)
-}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index c522b64..d0c3daf 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -438,55 +438,10 @@
targetUser,
mServiceConfig.getExecuteAppFunctionCancellationTimeoutMillis(),
cancellationSignal,
- new RunServiceCallCallback<IAppFunctionService>() {
- @Override
- public void onServiceConnected(
- @NonNull IAppFunctionService service,
- @NonNull
- ServiceUsageCompleteListener
- serviceUsageCompleteListener) {
- try {
- service.executeAppFunction(
- requestInternal.getClientRequest(),
- cancellationCallback,
- new IExecuteAppFunctionCallback.Stub() {
- @Override
- public void onResult(
- ExecuteAppFunctionResponse response) {
- safeExecuteAppFunctionCallback.onResult(
- response);
- serviceUsageCompleteListener.onCompleted();
- }
- });
- } catch (Exception e) {
- safeExecuteAppFunctionCallback.onResult(
- ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse
- .RESULT_APP_UNKNOWN_ERROR,
- e.getMessage(),
- /* extras= */ null));
- serviceUsageCompleteListener.onCompleted();
- }
- }
-
- @Override
- public void onFailedToConnect() {
- Slog.e(TAG, "Failed to connect to service");
- safeExecuteAppFunctionCallback.onResult(
- ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
- "Failed to connect to AppFunctionService",
- /* extras= */ null));
- }
-
- @Override
- public void onCancelled() {
- // Do not forward the result back to the caller once it has been
- // canceled. The caller does not need a notification and should
- // proceed after initiating a cancellation.
- safeExecuteAppFunctionCallback.disable();
- }
- },
+ RunAppFunctionServiceCallback.create(
+ requestInternal,
+ cancellationCallback,
+ safeExecuteAppFunctionCallback),
callerBinder);
if (!bindServiceResult) {
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
new file mode 100644
index 0000000..7820390
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+import android.app.appfunctions.ExecuteAppFunctionResponse;
+import android.app.appfunctions.IAppFunctionService;
+import android.app.appfunctions.ICancellationCallback;
+import android.app.appfunctions.IExecuteAppFunctionCallback;
+import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback;
+import android.util.Slog;
+
+import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback;
+import com.android.server.appfunctions.RemoteServiceCaller.ServiceUsageCompleteListener;
+
+
+/**
+ * A callback to forward a request to the {@link IAppFunctionService} and report back the result.
+ */
+public class RunAppFunctionServiceCallback implements RunServiceCallCallback<IAppFunctionService> {
+
+ private final ExecuteAppFunctionAidlRequest mRequestInternal;
+ private final SafeOneTimeExecuteAppFunctionCallback mSafeExecuteAppFunctionCallback;
+ private final ICancellationCallback mCancellationCallback;
+
+ private RunAppFunctionServiceCallback(
+ ExecuteAppFunctionAidlRequest requestInternal,
+ ICancellationCallback cancellationCallback,
+ SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) {
+ this.mRequestInternal = requestInternal;
+ this.mSafeExecuteAppFunctionCallback = safeExecuteAppFunctionCallback;
+ this.mCancellationCallback = cancellationCallback;
+ }
+
+ /**
+ * Creates a new instance of {@link RunAppFunctionServiceCallback}.
+ *
+ * @param requestInternal a request to send to the service.
+ * @param cancellationCallback a callback to forward cancellation signal to the service.
+ * @param safeExecuteAppFunctionCallback a callback to report back the result of the operation.
+ */
+ public static RunAppFunctionServiceCallback create(
+ ExecuteAppFunctionAidlRequest requestInternal,
+ ICancellationCallback cancellationCallback,
+ SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) {
+ return new RunAppFunctionServiceCallback(
+ requestInternal, cancellationCallback, safeExecuteAppFunctionCallback);
+ }
+
+ @Override
+ public void onServiceConnected(
+ @NonNull IAppFunctionService service,
+ @NonNull ServiceUsageCompleteListener serviceUsageCompleteListener) {
+ try {
+ service.executeAppFunction(
+ mRequestInternal.getClientRequest(),
+ mCancellationCallback,
+ new IExecuteAppFunctionCallback.Stub() {
+ @Override
+ public void onResult(ExecuteAppFunctionResponse response) {
+ mSafeExecuteAppFunctionCallback.onResult(response);
+ serviceUsageCompleteListener.onCompleted();
+ }
+ });
+ } catch (Exception e) {
+ mSafeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
+ e.getMessage(),
+ /* extras= */ null));
+ serviceUsageCompleteListener.onCompleted();
+ }
+ }
+
+ @Override
+ public void onFailedToConnect() {
+ Slog.e("AppFunctionManagerServiceImpl", "Failed to connect to service");
+ mSafeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
+ "Failed to connect to AppFunctionService",
+ /* extras= */ null));
+ }
+
+ @Override
+ public void onCancelled() {
+ mSafeExecuteAppFunctionCallback.disable();
+ }
+}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 78a0a11..796de19 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -458,7 +458,13 @@
}
void setThreadPriority(int tid, int priority) {
- Process.setThreadPriority(tid, priority);
+ if (Flags.resetOnForkEnabled()) {
+ Process.setThreadScheduler(tid,
+ Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK,
+ priority);
+ } else {
+ Process.setThreadPriority(tid, priority);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 4f6da3b..cc66378 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -214,3 +214,10 @@
description: "Defer submitting display events to frozen processes."
bug: "326315985"
}
+
+flag {
+ name: "reset_on_fork_enabled"
+ namespace: "system_performance"
+ description: "Set reset_on_fork flag."
+ bug: "370988407"
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c2e62d0..e0cf96f 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -540,11 +540,11 @@
this.uid = uid;
}
- @SuppressWarnings("GuardedBy")
public void clear() {
mAppOpsCheckingService.removeUid(uid);
for (int i = 0; i < pkgOps.size(); i++) {
- packageRemovedLocked(uid, pkgOps.keyAt(i));
+ String packageName = pkgOps.keyAt(i);
+ mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index af9c9ac..8d96ba9 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -377,6 +377,7 @@
* </point>
* </map>
* </luxToBrightnessMapping>
+ * <idleStylusTimeoutMillis>10000</idleStylusTimeoutMillis>
* </autoBrightness>
*
* <screenBrightnessRampFastDecrease>0.01</screenBrightnessRampFastDecrease>
@@ -708,6 +709,10 @@
private static final int KEEP_CURRENT_BRIGHTNESS = -1;
+ // The default value to 0 which will signify that the stylus usage immediately stopped
+ // after it was started. This will make the system behave as if the stylus was never used
+ private static final int DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS = 0;
+
private final Context mContext;
// The details of the ambient light sensor associated with this display.
@@ -754,6 +759,9 @@
@Nullable
private DisplayBrightnessMappingConfig mDisplayBrightnessMapping;
+ private int mIdleStylusTimeoutMillis =
+ DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS;
+
private float mBacklightMinimum = Float.NaN;
private float mBacklightMaximum = Float.NaN;
private float mBrightnessDefault = Float.NaN;
@@ -1730,6 +1738,7 @@
+ ", mDisplayBrightnessMapping= " + mDisplayBrightnessMapping
+ ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable
+ ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable
+ + ", mIdleStylusTimeoutMillis= " + mIdleStylusTimeoutMillis
+ "\n"
+ "mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate
+ ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate
@@ -2389,10 +2398,19 @@
loadAutoBrightnessDarkeningLightDebounceIdle(autoBrightness);
mDisplayBrightnessMapping = new DisplayBrightnessMappingConfig(mContext, mFlags,
autoBrightness, getBacklightToBrightnessSpline());
+ loadIdleStylusTimeoutMillis(autoBrightness);
loadEnableAutoBrightness(autoBrightness);
}
/**
+ * Gets the timeout post the stylus usage after which the automatic brightness will be enabled
+ * again
+ */
+ public int getIdleStylusTimeoutMillis() {
+ return mIdleStylusTimeoutMillis;
+ }
+
+ /**
* Loads the auto-brightness brightening light debounce. Internally, this takes care of loading
* the value from the display config, and if not present, falls back to config.xml.
*/
@@ -2923,6 +2941,16 @@
return levels;
}
+ private void loadIdleStylusTimeoutMillis(AutoBrightness autoBrightness) {
+ if (autoBrightness == null) {
+ return;
+ }
+ BigInteger idleStylusTimeoutMillis = autoBrightness.getIdleStylusTimeoutMillis();
+ if (idleStylusTimeoutMillis != null) {
+ mIdleStylusTimeoutMillis = idleStylusTimeoutMillis.intValue();
+ }
+ }
+
private void loadEnableAutoBrightness(AutoBrightness autobrightness) {
// mDdcAutoBrightnessAvailable is initialised to true, so that we fallback to using the
// config.xml values if the autobrightness tag is not defined in the ddc file.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99a7743..bb503aa 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -5646,6 +5646,21 @@
public void onPresentation(int displayId, boolean isShown) {
mExternalDisplayPolicy.onPresentation(displayId, isShown);
}
+
+ @Override
+ public void stylusGestureStarted(long eventTime) {
+ if (mFlags.isBlockAutobrightnessChangesOnStylusUsage()) {
+ DisplayPowerController displayPowerController;
+ synchronized (mSyncRoot) {
+ displayPowerController = mDisplayPowerControllers.get(
+ Display.DEFAULT_DISPLAY);
+ }
+ // We assume that the stylus is being used on the default display. This should
+ // be changed to the displayId on which it is being used once we start getting this
+ // information from the input manager service
+ displayPowerController.stylusGestureStarted(eventTime);
+ }
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 03fec011..8f07bb3 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -167,12 +167,11 @@
private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16;
private static final int MSG_SET_BRIGHTNESS_FROM_OFFLOAD = 17;
private static final int MSG_OFFLOADING_SCREEN_ON_UNBLOCKED = 18;
-
-
+ private static final int MSG_SET_STYLUS_BEING_USED = 19;
+ private static final int MSG_SET_STYLUS_USE_ENDED = 20;
private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
-
// State machine constants for tracking initial brightness ramp skipping when enabled.
private static final int RAMP_STATE_SKIP_NONE = 0;
private static final int RAMP_STATE_SKIP_INITIAL = 1;
@@ -191,6 +190,10 @@
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+
+ private static final int STYLUS_USAGE_DEBOUNCE_TIME = 1000;
+ private static final int NANO_SECONDS_TO_MILLI_SECONDS_RATIO = 1_000_000;
+
private static final int[] BRIGHTNESS_RANGE_INDEX = {
FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN,
FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1,
@@ -498,6 +501,11 @@
@GuardedBy("mLock")
private int mPendingOverrideDozeScreenStateLocked;
+ private long mLastStylusUsageEventTime = -1;
+
+ // The time of inactivity after which the stylus can be assumed to be no longer in use.
+ private long mIdleStylusTimeoutMillisConfig = 0;
+
/**
* Creates the display power controller.
*/
@@ -518,6 +526,7 @@
mSensorManager = sensorManager;
mHandler = new DisplayControllerHandler(handler.getLooper());
mDisplayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig();
+ mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis();
mIsEnabled = logicalDisplay.isEnabledLocked();
mIsInTransition = logicalDisplay.isInTransitionLocked();
mIsDisplayInternal = displayDeviceInfo.type == Display.TYPE_INTERNAL;
@@ -893,6 +902,7 @@
mPhysicalDisplayName = displayName;
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
+ mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis();
mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
loadFromDisplayDeviceConfig(token, info, hbmMetadata);
mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
@@ -2971,6 +2981,18 @@
return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
}
+ public void stylusGestureStarted(long eventTimeNanoSeconds) {
+ long eventTimeMs = eventTimeNanoSeconds / NANO_SECONDS_TO_MILLI_SECONDS_RATIO;
+ if (mLastStylusUsageEventTime == -1
+ || eventTimeMs > mLastStylusUsageEventTime + STYLUS_USAGE_DEBOUNCE_TIME) {
+ synchronized (mLock) {
+ // Add a message to notify the stylus usage has started
+ mHandler.sendEmptyMessageAtTime(MSG_SET_STYLUS_BEING_USED, mClock.uptimeMillis());
+ }
+ mLastStylusUsageEventTime = eventTimeMs;
+ }
+ }
+
private final class DisplayControllerHandler extends Handler {
DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -3087,6 +3109,20 @@
updatePowerState();
}
break;
+ case MSG_SET_STYLUS_BEING_USED:
+ // Remove any MSG_SET_STYLUS_USE_ENDED message from the handler queue and
+ // post a delayed MSG_SET_STYLUS_USE_ENDED message to delay the stylus
+ // usage ended event processing
+ mHandler.removeMessages(MSG_SET_STYLUS_USE_ENDED);
+ Message message = mHandler.obtainMessage(MSG_SET_STYLUS_USE_ENDED);
+ mHandler.sendMessageAtTime(message,
+ mClock.uptimeMillis() + mIdleStylusTimeoutMillisConfig);
+ mDisplayBrightnessController.setStylusBeingUsed(true);
+ break;
+ case MSG_SET_STYLUS_USE_ENDED:
+ mDisplayBrightnessController.setStylusBeingUsed(false);
+ updatePowerState();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 72a91d5..71fdaf3 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -501,6 +501,13 @@
return true;
}
+ /**
+ * Notifies if the stylus is currently being used or not.
+ */
+ public void setStylusBeingUsed(boolean isEnabled) {
+ // Todo(b/369977976) - Disable the auto-brightness strategy
+ }
+
@VisibleForTesting
static class Injector {
DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(Context context,
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index df66893..5284d1c 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -203,6 +203,10 @@
Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER,
Flags::normalBrightnessForDozeParameter
);
+ private final FlagState mBlockAutobrightnessChangesOnStylusUsage = new FlagState(
+ Flags.FLAG_BLOCK_AUTOBRIGHTNESS_CHANGES_ON_STYLUS_USAGE,
+ Flags::blockAutobrightnessChangesOnStylusUsage
+ );
private final FlagState mEnableBatteryStatsForAllDisplays = new FlagState(
Flags.FLAG_ENABLE_BATTERY_STATS_FOR_ALL_DISPLAYS,
@@ -436,6 +440,13 @@
}
/**
+ * @return {@code true} if autobrightness is to be blocked when stylus is being used
+ */
+ public boolean isBlockAutobrightnessChangesOnStylusUsage() {
+ return mBlockAutobrightnessChangesOnStylusUsage.isEnabled();
+ }
+
+ /**
* dumps all flagstates
* @param pw printWriter
*/
@@ -479,6 +490,7 @@
pw.println(" " + mNormalBrightnessForDozeParameter);
pw.println(" " + mIdleScreenConfigInSubscribingLightSensor);
pw.println(" " + mEnableBatteryStatsForAllDisplays);
+ pw.println(" " + mBlockAutobrightnessChangesOnStylusUsage);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index e3ebe5b..252ed09 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -364,4 +364,12 @@
description: "Flag to enable battery stats for all displays."
bug: "366112793"
is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+ name: "block_autobrightness_changes_on_stylus_usage"
+ namespace: "display_manager"
+ description: "Block the usage of ALS to control the display brightness when stylus is being used"
+ bug: "352411468"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f045576..8acf583 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2694,6 +2694,9 @@
@SuppressWarnings("unused")
private void notifyStylusGestureStarted(int deviceId, long eventTime) {
mBatteryController.notifyStylusGestureStarted(deviceId, eventTime);
+ if (mDisplayManagerInternal != null) {
+ mDisplayManagerInternal.stylusGestureStarted(eventTime);
+ }
}
/**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e47b4c2..68e781f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1141,9 +1141,9 @@
+ mShortPressOnPowerBehavior);
if (count == 2) {
- powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
+ powerMultiPressAction(displayId, eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
- powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
+ powerMultiPressAction(displayId, eventTime, interactive, mTriplePressOnPowerBehavior);
} else if (count > 3 && count <= getMaxMultiPressPowerCount()) {
Slog.d(TAG, "No behavior defined for power press count " + count);
} else if (count == 1 && shouldHandleShortPressPowerAction(interactive, eventTime)) {
@@ -1307,7 +1307,8 @@
}
}
- private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
+ private void powerMultiPressAction(int displayId, long eventTime, boolean interactive,
+ int behavior) {
switch (behavior) {
case MULTI_PRESS_POWER_NOTHING:
break;
@@ -1322,7 +1323,7 @@
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0);
if (!interactive) {
- wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
+ wakeUpFromWakeKey(displayId, eventTime, KEYCODE_POWER, /* isDown= */ false);
}
} else {
Slog.i(TAG, "Toggling theater mode on.");
@@ -1338,7 +1339,7 @@
case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
Slog.i(TAG, "Starting brightness boost.");
if (!interactive) {
- wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
+ wakeUpFromWakeKey(displayId, eventTime, KEYCODE_POWER, /* isDown= */ false);
}
mPowerManager.boostScreenBrightness(eventTime);
break;
@@ -5546,7 +5547,7 @@
if (mRequestedOrSleepingDefaultDisplay) {
mCameraGestureTriggeredDuringGoingToSleep = true;
// Wake device up early to prevent display doing redundant turning off/on stuff.
- mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture();
+ mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture(event.getDisplayId());
}
return true;
}
@@ -5644,8 +5645,8 @@
public int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action,
long whenNanos, int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
- if (mWindowWakeUpPolicy.wakeUpFromMotion(
- whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
+ if (mWindowWakeUpPolicy.wakeUpFromMotion(displayId, whenNanos / 1000000, source,
+ action == MotionEvent.ACTION_DOWN)) {
// Woke up. Pass motion events to user.
return ACTION_PASS_TO_USER;
}
@@ -5659,8 +5660,8 @@
// there will be no dream to intercept the touch and wake into ambient. The device should
// wake up in this case.
if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
- if (mWindowWakeUpPolicy.wakeUpFromMotion(
- whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
+ if (mWindowWakeUpPolicy.wakeUpFromMotion(displayId, whenNanos / 1000000, source,
+ action == MotionEvent.ACTION_DOWN)) {
// Woke up. Pass motion events to user.
return ACTION_PASS_TO_USER;
}
@@ -6002,13 +6003,14 @@
return;
}
wakeUpFromWakeKey(
+ event.getDisplayId(),
event.getEventTime(),
event.getKeyCode(),
event.getAction() == KeyEvent.ACTION_DOWN);
}
- private void wakeUpFromWakeKey(long eventTime, int keyCode, boolean isDown) {
- if (mWindowWakeUpPolicy.wakeUpFromKey(eventTime, keyCode, isDown)) {
+ private void wakeUpFromWakeKey(int displayId, long eventTime, int keyCode, boolean isDown) {
+ if (mWindowWakeUpPolicy.wakeUpFromKey(displayId, eventTime, keyCode, isDown)) {
final boolean keyCanLaunchHome = keyCode == KEYCODE_HOME || keyCode == KEYCODE_POWER;
// Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
if (shouldWakeUpWithHomeIntent() && keyCanLaunchHome) {
diff --git a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
index af1ad13..966d84f4 100644
--- a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
@@ -25,6 +25,7 @@
import static android.view.KeyEvent.KEYCODE_POWER;
import static com.android.server.policy.Flags.supportInputWakeupDelegate;
+import static com.android.server.power.feature.flags.Flags.perDisplayWakeByTouch;
import android.annotation.Nullable;
import android.content.Context;
@@ -107,13 +108,14 @@
/**
* Wakes up from a key event.
*
+ * @param displayId the id of the display to wake.
* @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
* @param keyCode the {@link android.view.KeyEvent} key code of the key event.
* @param isDown {@code true} if the event's action is {@link KeyEvent#ACTION_DOWN}.
* @return {@code true} if the policy allows the requested wake up and the request has been
* executed; {@code false} otherwise.
*/
- boolean wakeUpFromKey(long eventTime, int keyCode, boolean isDown) {
+ boolean wakeUpFromKey(int displayId, long eventTime, int keyCode, boolean isDown) {
final boolean wakeAllowedDuringTheaterMode =
keyCode == KEYCODE_POWER
? mAllowTheaterModeWakeFromPowerKey
@@ -127,6 +129,7 @@
return true;
}
wakeUp(
+ displayId,
eventTime,
keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
keyCode == KEYCODE_POWER ? "POWER" : "KEY");
@@ -136,12 +139,13 @@
/**
* Wakes up from a motion event.
*
+ * @param displayId the id of the display to wake.
* @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
* @param isDown {@code true} if the event's action is {@link MotionEvent#ACTION_DOWN}.
* @return {@code true} if the policy allows the requested wake up and the request has been
* executed; {@code false} otherwise.
*/
- boolean wakeUpFromMotion(long eventTime, int source, boolean isDown) {
+ boolean wakeUpFromMotion(int displayId, long eventTime, int source, boolean isDown) {
if (!canWakeUp(mAllowTheaterModeWakeFromMotion)) {
if (DEBUG) Slog.d(TAG, "Unable to wake up from motion.");
return false;
@@ -150,7 +154,7 @@
&& mInputWakeUpDelegate.wakeUpFromMotion(eventTime, source, isDown)) {
return true;
}
- wakeUp(eventTime, WAKE_REASON_WAKE_MOTION, "MOTION");
+ wakeUp(displayId, eventTime, WAKE_REASON_WAKE_MOTION, "MOTION");
return true;
}
@@ -166,7 +170,7 @@
if (DEBUG) Slog.d(TAG, "Unable to wake up from camera cover.");
return false;
}
- wakeUp(eventTime, WAKE_REASON_CAMERA_LAUNCH, "CAMERA_COVER");
+ wakeUp(Display.DEFAULT_DISPLAY, eventTime, WAKE_REASON_CAMERA_LAUNCH, "CAMERA_COVER");
return true;
}
@@ -181,22 +185,24 @@
if (DEBUG) Slog.d(TAG, "Unable to wake up from lid.");
return false;
}
- wakeUp(mClock.uptimeMillis(), WAKE_REASON_LID, "LID");
+ wakeUp(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(), WAKE_REASON_LID, "LID");
return true;
}
/**
* Wakes up to prevent sleeping when opening camera through power button.
*
+ * @param displayId the id of the display to wake.
* @return {@code true} if the policy allows the requested wake up and the request has been
* executed; {@code false} otherwise.
*/
- boolean wakeUpFromPowerKeyCameraGesture() {
+ boolean wakeUpFromPowerKeyCameraGesture(int displayId) {
if (!canWakeUp(mAllowTheaterModeWakeFromPowerKey)) {
if (DEBUG) Slog.d(TAG, "Unable to wake up from power key camera gesture.");
return false;
}
- wakeUp(mClock.uptimeMillis(), WAKE_REASON_CAMERA_LAUNCH, "CAMERA_GESTURE_PREVENT_LOCK");
+ wakeUp(displayId, mClock.uptimeMillis(), WAKE_REASON_CAMERA_LAUNCH,
+ "CAMERA_GESTURE_PREVENT_LOCK");
return true;
}
@@ -211,7 +217,7 @@
if (DEBUG) Slog.d(TAG, "Unable to wake up from gesture.");
return false;
}
- wakeUp(mClock.uptimeMillis(), WAKE_REASON_GESTURE, "GESTURE");
+ wakeUp(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(), WAKE_REASON_GESTURE, "GESTURE");
return true;
}
@@ -234,7 +240,11 @@
}
/** Wakes up {@link PowerManager}. */
- private void wakeUp(long wakeTime, @WakeReason int reason, String details) {
- mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
+ private void wakeUp(int displayId, long wakeTime, @WakeReason int reason, String details) {
+ if (perDisplayWakeByTouch()) {
+ mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details, displayId);
+ } else {
+ mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
+ }
}
}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index dc48242..c969eff 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -21,6 +21,7 @@
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.server.power.hint.Flags.adpfSessionTag;
import static com.android.server.power.hint.Flags.powerhintThreadCleanup;
+import static com.android.server.power.hint.Flags.resetOnForkEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1057,6 +1058,11 @@
Slogf.w(TAG, errMsg);
throw new SecurityException(errMsg);
}
+ if (resetOnForkEnabled()){
+ for (int tid : tids) {
+ Process.setThreadScheduler(tid, Process.SCHED_RESET_ON_FORK, 0);
+ }
+ }
if (adpfSessionTag() && tag == SessionTag.APP) {
// If the category of the app is a game,
@@ -1447,6 +1453,11 @@
Slogf.w(TAG, errMsg);
throw new SecurityException(errMsg);
}
+ if (resetOnForkEnabled()){
+ for (int tid : tids) {
+ Process.setThreadScheduler(tid, Process.SCHED_RESET_ON_FORK, 0);
+ }
+ }
if (powerhintThreadCleanup()) {
synchronized (mNonIsolatedTidsLock) {
for (int i = nonIsolated.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/power/hint/flags.aconfig b/services/core/java/com/android/server/power/hint/flags.aconfig
index 55afa05..e56b68c 100644
--- a/services/core/java/com/android/server/power/hint/flags.aconfig
+++ b/services/core/java/com/android/server/power/hint/flags.aconfig
@@ -14,3 +14,10 @@
description: "Feature flag for adding session tag to hint session atom"
bug: "345011125"
}
+
+flag {
+ name: "reset_on_fork_enabled"
+ namespace: "game"
+ description: "Set reset_on_fork flag."
+ bug: "370988407"
+}
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 1073713..264c8be 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -146,7 +146,7 @@
"process bound by foreground uid");
}
// Allow if the caller has an activity in any foreground task.
- if (checkConfiguration.checkVisibility && hasActivityInVisibleTask
+ if (checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask
&& appSwitchState != APP_SWITCH_DISALLOW) {
return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false,
"process has activity in foreground task");
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index a07facf..776de2e 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -712,6 +712,12 @@
minOccurs="0" maxOccurs="unbounded">
<xs:annotation name="final"/>
</xs:element>
+ <!-- The time after which the stylus is to be assumed to be not under use. This will
+ enable the logic of changing the brightness with ambient light changes -->
+ <xs:element name="idleStylusTimeoutMillis" type="xs:nonNegativeInteger"
+ minOccurs="0" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 5309263..110a5a2 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -8,12 +8,14 @@
method public final java.math.BigInteger getDarkeningLightDebounceIdleMillis();
method public final java.math.BigInteger getDarkeningLightDebounceMillis();
method public boolean getEnabled();
+ method public final java.math.BigInteger getIdleStylusTimeoutMillis();
method public final java.util.List<com.android.server.display.config.LuxToBrightnessMapping> getLuxToBrightnessMapping();
method public final void setBrighteningLightDebounceIdleMillis(java.math.BigInteger);
method public final void setBrighteningLightDebounceMillis(java.math.BigInteger);
method public final void setDarkeningLightDebounceIdleMillis(java.math.BigInteger);
method public final void setDarkeningLightDebounceMillis(java.math.BigInteger);
method public void setEnabled(boolean);
+ method public final void setIdleStylusTimeoutMillis(java.math.BigInteger);
}
public enum AutoBrightnessModeName {
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
index e33ca77..70a2d48 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
+++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
@@ -45,7 +45,7 @@
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
-import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
+import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser;
import com.android.bedstead.nene.users.UserReference;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.TestUtils;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 8e1be9a..3976ea4 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -157,6 +157,7 @@
.getIdleScreenRefreshRateTimeoutLuxThresholdPoint());
assertNull(mDisplayDeviceConfig.getTempSensor().name);
assertTrue(mDisplayDeviceConfig.isAutoBrightnessAvailable());
+ assertEquals(0, mDisplayDeviceConfig.getIdleStylusTimeoutMillis());
}
@Test
@@ -253,6 +254,7 @@
.getLux().intValue());
assertEquals(800, idleScreenRefreshRateTimeoutLuxThresholdPoints.get(1)
.getTimeout().intValue());
+ assertEquals(1000, mDisplayDeviceConfig.getIdleStylusTimeoutMillis());
}
@Test
@@ -1479,6 +1481,7 @@
+ "</point>\n"
+ "</map>\n"
+ "</luxToBrightnessMapping>\n"
+ + "<idleStylusTimeoutMillis>1000</idleStylusTimeoutMillis>\n"
+ "</autoBrightness>\n"
+ getPowerThrottlingConfig()
+ "<highBrightnessMode enabled=\"true\">\n"
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a85f866..3dc893a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -700,7 +700,7 @@
void assertPowerWakeUp() {
mTestLooper.dispatchAll();
verify(mWindowWakeUpPolicy)
- .wakeUpFromKey(anyLong(), eq(KeyEvent.KEYCODE_POWER), anyBoolean());
+ .wakeUpFromKey(anyInt(), anyLong(), eq(KeyEvent.KEYCODE_POWER), anyBoolean());
}
void assertNoPowerSleep() {
diff --git a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
index 7322e5a..4119ad3 100644
--- a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
@@ -35,6 +35,7 @@
import static com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch;
import static com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture;
import static com.android.server.policy.Flags.FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE;
+import static com.android.server.power.feature.flags.Flags.FLAG_PER_DISPLAY_WAKE_BY_TOUCH;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -43,6 +44,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -52,6 +54,8 @@
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.os.PowerManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.Display;
@@ -125,6 +129,7 @@
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testMotionWakeUpDelegation_wakePowerManagerIfDelegateDoesNotHandleWake() {
setTheaterModeEnabled(false);
mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
@@ -136,7 +141,8 @@
// Verify the policy wake up call succeeds because of the call on the delegate, and not
// because of a PowerManager wake up.
- assertThat(mPolicy.wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true)).isTrue();
+ assertThat(mPolicy.wakeUpFromMotion(
+ mDefaultDisplay.getDisplayId(), 200, SOURCE_TOUCHSCREEN, true)).isTrue();
verify(mInputWakeUpDelegate).wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true);
verifyNoPowerManagerWakeUp();
@@ -144,12 +150,14 @@
// Verify the policy wake up call succeeds because of the PowerManager wake up, since the
// delegate would not handle the wake up request.
- assertThat(mPolicy.wakeUpFromMotion(300, SOURCE_ROTARY_ENCODER, false)).isTrue();
+ assertThat(mPolicy.wakeUpFromMotion(
+ mDefaultDisplay.getDisplayId(), 300, SOURCE_ROTARY_ENCODER, false)).isTrue();
verify(mInputWakeUpDelegate).wakeUpFromMotion(300, SOURCE_ROTARY_ENCODER, false);
verify(mPowerManager).wakeUp(300, WAKE_REASON_WAKE_MOTION, "android.policy:MOTION");
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testKeyWakeUpDelegation_wakePowerManagerIfDelegateDoesNotHandleWake() {
setTheaterModeEnabled(false);
mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
@@ -161,7 +169,8 @@
// Verify the policy wake up call succeeds because of the call on the delegate, and not
// because of a PowerManager wake up.
- assertThat(mPolicy.wakeUpFromKey(200, KEYCODE_POWER, true)).isTrue();
+ assertThat(mPolicy.wakeUpFromKey(
+ mDefaultDisplay.getDisplayId(), 200, KEYCODE_POWER, true)).isTrue();
verify(mInputWakeUpDelegate).wakeUpFromKey(200, KEYCODE_POWER, true);
verifyNoPowerManagerWakeUp();
@@ -169,7 +178,8 @@
// Verify the policy wake up call succeeds because of the PowerManager wake up, since the
// delegate would not handle the wake up request.
- assertThat(mPolicy.wakeUpFromKey(300, KEYCODE_STEM_PRIMARY, false)).isTrue();
+ assertThat(mPolicy.wakeUpFromKey(
+ mDefaultDisplay.getDisplayId(), 300, KEYCODE_STEM_PRIMARY, false)).isTrue();
verify(mInputWakeUpDelegate).wakeUpFromKey(300, KEYCODE_STEM_PRIMARY, false);
verify(mPowerManager).wakeUp(300, WAKE_REASON_WAKE_KEY, "android.policy:KEY");
}
@@ -186,7 +196,8 @@
.setInputWakeUpDelegate(mInputWakeUpDelegate);
// Check that the wake up does not happen because the theater mode policy check fails.
- assertThat(mPolicy.wakeUpFromKey(200, KEYCODE_POWER, true)).isFalse();
+ assertThat(mPolicy.wakeUpFromKey(
+ mDefaultDisplay.getDisplayId(), 200, KEYCODE_POWER, true)).isFalse();
verify(mInputWakeUpDelegate, never()).wakeUpFromKey(anyLong(), anyInt(), anyBoolean());
}
@@ -201,11 +212,13 @@
.setInputWakeUpDelegate(mInputWakeUpDelegate);
// Check that the wake up does not happen because the theater mode policy check fails.
- assertThat(mPolicy.wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true)).isFalse();
+ assertThat(mPolicy.wakeUpFromMotion(
+ mDefaultDisplay.getDisplayId(), 200, SOURCE_TOUCHSCREEN, true)).isFalse();
verify(mInputWakeUpDelegate, never()).wakeUpFromMotion(anyLong(), anyInt(), anyBoolean());
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testTheaterModeChecksNotAppliedWhenScreenIsOn() {
mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
setDefaultDisplayState(Display.STATE_ON);
@@ -213,30 +226,69 @@
setBooleanRes(config_allowTheaterModeWakeFromMotion, false);
mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
- mPolicy.wakeUpFromMotion(200L, SOURCE_TOUCHSCREEN, true);
+ mPolicy.wakeUpFromMotion(mDefaultDisplay.getDisplayId(), 200L, SOURCE_TOUCHSCREEN, true);
verify(mPowerManager).wakeUp(200L, WAKE_REASON_WAKE_MOTION, "android.policy:MOTION");
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromMotion() {
runPowerManagerUpChecks(
- () -> mPolicy.wakeUpFromMotion(mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, true),
+ () -> mPolicy.wakeUpFromMotion(mDefaultDisplay.getDisplayId(),
+ mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, true),
config_allowTheaterModeWakeFromMotion,
WAKE_REASON_WAKE_MOTION,
"android.policy:MOTION");
}
@Test
+ @EnableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
+ public void testWakeUpFromMotion_perDisplayWakeByTouchEnabled() {
+ setTheaterModeEnabled(false);
+ final int displayId = 555;
+ mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
+
+ boolean displayWokeUp = mPolicy.wakeUpFromMotion(
+ displayId, mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, /* isDown= */ true);
+
+ // Verify that display is woken up
+ assertThat(displayWokeUp).isTrue();
+ verify(mPowerManager).wakeUp(anyLong(), eq(WAKE_REASON_WAKE_MOTION),
+ eq("android.policy:MOTION"), eq(displayId));
+ }
+
+ @Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
+ public void testWakeUpFromMotion_perDisplayWakeByTouchDisabled() {
+ setTheaterModeEnabled(false);
+ final int displayId = 555;
+ mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
+
+ boolean displayWokeUp = mPolicy.wakeUpFromMotion(
+ displayId, mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, /* isDown= */ true);
+
+ // Verify that power is woken up and display isn't woken up individually
+ assertThat(displayWokeUp).isTrue();
+ verify(mPowerManager).wakeUp(
+ anyLong(), eq(WAKE_REASON_WAKE_MOTION), eq("android.policy:MOTION"));
+ verify(mPowerManager, never()).wakeUp(anyLong(), eq(WAKE_REASON_WAKE_MOTION),
+ eq("android.policy:MOTION"), eq(displayId));
+ }
+
+ @Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromKey_nonPowerKey() {
runPowerManagerUpChecks(
- () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_HOME, true),
+ () -> mPolicy.wakeUpFromKey(
+ mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(), KEYCODE_HOME, true),
config_allowTheaterModeWakeFromKey,
WAKE_REASON_WAKE_KEY,
"android.policy:KEY");
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromKey_powerKey() {
// Disable the resource affecting all wake keys because it affects power key as well.
// That way, power key wake during theater mode will solely be controlled by
@@ -245,7 +297,8 @@
// Test with power key
runPowerManagerUpChecks(
- () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_POWER, true),
+ () -> mPolicy.wakeUpFromKey(
+ mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(), KEYCODE_POWER, true),
config_allowTheaterModeWakeFromPowerKey,
WAKE_REASON_POWER_BUTTON,
"android.policy:POWER");
@@ -254,13 +307,15 @@
// even if the power-key specific theater mode config is disabled.
setBooleanRes(config_allowTheaterModeWakeFromPowerKey, false);
runPowerManagerUpChecks(
- () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_POWER, false),
+ () -> mPolicy.wakeUpFromKey(mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(),
+ KEYCODE_POWER, false),
config_allowTheaterModeWakeFromKey,
WAKE_REASON_POWER_BUTTON,
"android.policy:POWER");
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromLid() {
runPowerManagerUpChecks(
() -> mPolicy.wakeUpFromLid(),
@@ -270,6 +325,7 @@
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromWakeGesture() {
runPowerManagerUpChecks(
() -> mPolicy.wakeUpFromWakeGesture(),
@@ -279,6 +335,7 @@
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testwakeUpFromCameraCover() {
runPowerManagerUpChecks(
() -> mPolicy.wakeUpFromCameraCover(mClock.uptimeMillis()),
@@ -288,6 +345,7 @@
}
@Test
+ @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
public void testWakeUpFromPowerKeyCameraGesture() {
// Disable the resource affecting all wake keys because it affects power key as well.
// That way, power key wake during theater mode will solely be controlled by
@@ -295,7 +353,7 @@
setBooleanRes(config_allowTheaterModeWakeFromKey, false);
runPowerManagerUpChecks(
- () -> mPolicy.wakeUpFromPowerKeyCameraGesture(),
+ () -> mPolicy.wakeUpFromPowerKeyCameraGesture(mDefaultDisplay.getDisplayId()),
config_allowTheaterModeWakeFromPowerKey,
WAKE_REASON_CAMERA_LAUNCH,
"android.policy:CAMERA_GESTURE_PREVENT_LOCK");
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 1af8d6f..b2e48bd 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -40,7 +40,7 @@
void printStringPool(const ResStringPool* pool)
{
if (pool->getError() == NO_INIT) {
- printf("String pool is unitialized.\n");
+ printf("String pool is uninitialized.\n");
return;
} else if (pool->getError() != NO_ERROR) {
printf("String pool is corrupt/invalid.\n");
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 064b461..2527dcd 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -445,7 +445,7 @@
using namespace android;
if (pool->getError() == NO_INIT) {
- printer->Print("String pool is unitialized.\n");
+ printer->Print("String pool is uninitialized.\n");
return;
} else if (pool->getError() != NO_ERROR) {
printer->Print("String pool is corrupt/invalid.\n");