Merge "Delegate bugreport consent for system apps." into main
diff --git a/boot/boot-image-profile-extra.txt b/boot/boot-image-profile-extra.txt
index e3b187e..11ca1dc 100644
--- a/boot/boot-image-profile-extra.txt
+++ b/boot/boot-image-profile-extra.txt
@@ -19,3 +19,7 @@
# methods are latency sensitive is difficult. For example, this method is executed
# in the system server, not on the UI thread of an app.
HSPLandroid/graphics/Color;->luminance()F
+
+# For now, compile all methods in MessageQueue to avoid performance cliffs for
+# flagged/evolving hot code paths. See: b/338098106
+HSPLandroid/os/MessageQueue;->*
diff --git a/core/api/current.txt b/core/api/current.txt
index a8b9e33..09fef25 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -52491,6 +52491,7 @@
method public android.graphics.Canvas lockHardwareCanvas();
method public void readFromParcel(android.os.Parcel);
method public void release();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public void setFrameRate(@NonNull android.view.Surface.FrameRateParams);
method public void setFrameRate(@FloatRange(from=0.0) float, int, int);
method public void setFrameRate(@FloatRange(from=0.0) float, int);
method @Deprecated public void unlockCanvas(android.graphics.Canvas);
@@ -52507,6 +52508,22 @@
field public static final int ROTATION_90 = 1; // 0x1
}
+ @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static class Surface.FrameRateParams {
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public int getChangeFrameRateStrategy();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getDesiredMaxRate();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getDesiredMinRate();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getFixedSourceRate();
+ field @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static final android.view.Surface.FrameRateParams IGNORE;
+ }
+
+ @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static final class Surface.FrameRateParams.Builder {
+ ctor public Surface.FrameRateParams.Builder();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams build();
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setChangeFrameRateStrategy(int);
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setDesiredRateRange(@FloatRange(from=0.0) float, @FloatRange(from=0.0) float);
+ method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setFixedSourceRate(@FloatRange(from=0.0) float);
+ }
+
public static class Surface.OutOfResourcesException extends java.lang.RuntimeException {
ctor public Surface.OutOfResourcesException();
ctor public Surface.OutOfResourcesException(String);
diff --git a/core/java/android/hardware/fingerprint/FingerprintCallback.java b/core/java/android/hardware/fingerprint/FingerprintCallback.java
index 24e9f9d..e4fbe6e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintCallback.java
+++ b/core/java/android/hardware/fingerprint/FingerprintCallback.java
@@ -189,7 +189,7 @@
mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD);
}
final String msg = getAcquiredString(context, acquireInfo, vendorCode);
- if (msg == null || msg.isEmpty()) {
+ if (msg == null) {
return;
}
// emulate HAL 2.1 behavior and send real acquiredInfo
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 7f1cac0..590c4d6 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -1517,7 +1517,7 @@
*/
public static String getAcquiredString(Context context, int acquireInfo, int vendorCode) {
switch (acquireInfo) {
- case FINGERPRINT_ACQUIRED_GOOD:
+ case FINGERPRINT_ACQUIRED_GOOD, FINGERPRINT_ACQUIRED_START:
return null;
case FINGERPRINT_ACQUIRED_PARTIAL:
return context.getString(
@@ -1546,13 +1546,10 @@
case FINGERPRINT_ACQUIRED_VENDOR: {
String[] msgArray = context.getResources().getStringArray(
com.android.internal.R.array.fingerprint_acquired_vendor);
- if (vendorCode < msgArray.length) {
+ if (vendorCode < msgArray.length && !msgArray[vendorCode].isEmpty()) {
return msgArray[vendorCode];
}
}
- break;
- case FINGERPRINT_ACQUIRED_START:
- return null;
}
Slog.w(TAG, "Invalid acquired message: " + acquireInfo + ", " + vendorCode);
return null;
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index 6afb8e0..8eaadde 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -29,6 +29,8 @@
import com.android.internal.annotations.GuardedBy;
+import dalvik.annotation.optimization.NeverCompile;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1331,6 +1333,7 @@
mMatchAllFutureMessages, true);
}
+ @NeverCompile
private void printPriorityQueueNodes() {
Iterator<MessageNode> iterator = mPriorityQueue.iterator();
@@ -1342,6 +1345,7 @@
}
}
+ @NeverCompile
private int dumpPriorityQueue(ConcurrentSkipListSet<MessageNode> queue, Printer pw,
String prefix, Handler h, int n) {
int count = 0;
@@ -1357,6 +1361,7 @@
return count;
}
+ @NeverCompile
void dump(Printer pw, String prefix, Handler h) {
long now = SystemClock.uptimeMillis();
int n = 0;
@@ -1387,6 +1392,7 @@
+ ", quitting=" + (boolean) sQuitting.getVolatile(this) + ")");
}
+ @NeverCompile
private int dumpPriorityQueue(ConcurrentSkipListSet<MessageNode> queue,
ProtoOutputStream proto) {
int count = 0;
@@ -1399,6 +1405,7 @@
return count;
}
+ @NeverCompile
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long messageQueueToken = proto.start(fieldId);
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index 4474e7e..9f7b0b7 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -28,6 +28,8 @@
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import dalvik.annotation.optimization.NeverCompile;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1106,6 +1108,7 @@
}
}
+ @NeverCompile
void dump(Printer pw, String prefix, Handler h) {
synchronized (this) {
pw.println(prefix + "(MessageQueue is using Legacy implementation)");
@@ -1122,6 +1125,7 @@
}
}
+ @NeverCompile
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long messageQueueToken = proto.start(fieldId);
synchronized (this) {
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
index f1affce..f3eec13 100644
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -30,6 +30,8 @@
import com.android.internal.annotations.GuardedBy;
+import dalvik.annotation.optimization.NeverCompile;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -294,6 +296,7 @@
* Keep this for manual debugging. It's easier to pepper the code with this function
* than MessageQueue.dump()
*/
+ @NeverCompile
void print() {
Log.v(TAG, "heap num elem: " + mNumElements + " mHeap.length " + mHeap.length);
for (int i = 0; i < mNumElements; i++) {
@@ -1209,6 +1212,7 @@
sMatchAllFutureMessages, true);
}
+ @NeverCompile
int dumpPriorityQueue(Printer pw, String prefix, Handler h, MessageHeap priorityQueue) {
int n = 0;
long now = SystemClock.uptimeMillis();
@@ -1222,6 +1226,7 @@
return n;
}
+ @NeverCompile
void dumpPriorityQueue(ProtoOutputStream proto, MessageHeap priorityQueue) {
for (int i = 0; i < priorityQueue.numElements(); i++) {
Message m = priorityQueue.getMessageAt(i);
@@ -1229,6 +1234,7 @@
}
}
+ @NeverCompile
void dump(Printer pw, String prefix, Handler h) {
synchronized (this) {
pw.println(prefix + "(MessageQueue is using Locked implementation)");
@@ -1240,6 +1246,7 @@
}
}
+ @NeverCompile
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long messageQueueToken = proto.start(fieldId);
synchronized (this) {
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index 02335972..db323dc 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -29,6 +29,8 @@
import com.android.internal.annotations.GuardedBy;
+import dalvik.annotation.optimization.NeverCompile;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1249,6 +1251,7 @@
mMatchAllFutureMessages, true);
}
+ @NeverCompile
private void printPriorityQueueNodes() {
Iterator<MessageNode> iterator = mPriorityQueue.iterator();
@@ -1260,6 +1263,7 @@
}
}
+ @NeverCompile
private int dumpPriorityQueue(PriorityQueue<MessageNode> queue, Printer pw, String prefix,
Handler h, int n) {
int count = 0;
@@ -1275,6 +1279,7 @@
return count;
}
+ @NeverCompile
void dump(Printer pw, String prefix, Handler h) {
long now = SystemClock.uptimeMillis();
int n = 0;
@@ -1307,6 +1312,7 @@
+ ", quitting=" + (boolean) sQuitting.getVolatile(this) + ")");
}
+ @NeverCompile
private int dumpPriorityQueue(PriorityQueue<MessageNode> queue, ProtoOutputStream proto) {
int count = 0;
@@ -1318,6 +1324,7 @@
return count;
}
+ @NeverCompile
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long messageQueueToken = proto.start(fieldId);
diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl
index 8f33e0b..9d384fb 100644
--- a/core/java/android/print/IPrintDocumentAdapter.aidl
+++ b/core/java/android/print/IPrintDocumentAdapter.aidl
@@ -37,5 +37,4 @@
void write(in PageRange[] pages, in ParcelFileDescriptor fd,
IWriteResultCallback callback, int sequence);
void finish();
- void kill(String reason);
}
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index ef274a5..1b1554f 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -946,17 +946,6 @@
}
@Override
- public void kill(String reason) {
- synchronized (mLock) {
- // If destroyed the handler is null.
- if (!isDestroyedLocked()) {
- mHandler.obtainMessage(MyHandler.MSG_ON_KILL,
- reason).sendToTarget();
- }
- }
- }
-
- @Override
public void onActivityPaused(Activity activity) {
/* do nothing */
}
@@ -1118,15 +1107,6 @@
}
} break;
- case MSG_ON_KILL: {
- if (DEBUG) {
- Log.i(LOG_TAG, "onKill()");
- }
-
- String reason = (String) message.obj;
- throw new RuntimeException(reason);
- }
-
default: {
throw new IllegalArgumentException("Unknown message: "
+ message.what);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 764570e..8a784eb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11281,7 +11281,8 @@
"assist_long_press_home_enabled";
/**
- * Whether all entrypoints can trigger search. Replaces individual settings.
+ * Whether all entrypoints (e.g. long-press home, long-press nav handle)
+ * can trigger contextual search.
*
* @hide
*/
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 396be7b..03f9d98 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -18,9 +18,11 @@
import static android.system.OsConstants.EINVAL;
+import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo.Translator;
@@ -1026,6 +1028,211 @@
}
/**
+ * Parameter object for {@link #setFrameRate(FrameRateParams)}, describing the intended frame
+ * rate for the Surface that setFrameRate is called on.
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public static class FrameRateParams {
+ private FrameRateParams() {}
+
+ /**
+ * A static FrameRateParams that can be passed directly into {@link
+ * #setFrameRate(FrameRateParams)} to indicate the surface has no preference and any frame
+ * rate is acceptable.
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public static final FrameRateParams IGNORE =
+ new FrameRateParams.Builder().setDesiredRateRange(0f, Float.MAX_VALUE).build();
+
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public static final class Builder {
+ private float mDesiredMinRate;
+ private float mDesiredMaxRate;
+ private float mFixedSourceRate;
+ private int mChangeFrameRateStrategy;
+
+ /**
+ * Sets the desired frame rate range (inclusive) values for the surface, specifying that
+ * the surface prefers the device render rate to be in the range [desiredMinRate,
+ * desiredMaxRate].
+
+ * Set desiredMaxRate to FLOAT.MAX_VALUE to indicate the surface prefers any value
+ * greater than or equal to desiredMinRate.
+ *
+ * Set desiredMinRate = desiredMaxRate to indicate the surface prefers an exact frame
+ * rate. Note that this is different than specifying the fixed source frame rate with
+ * {@link FrameRateParams.Builder#setFixedSourceRate}. To reiterate, this call is used
+ * to specify the surface's frame rate preference to be within the desired range.
+ *
+ * desiredMaxRate must be greater than or equal to desiredMinRate.
+ * The values should be greater than or equal to 0.
+ *
+ * If the surface has no preference and any frame rate is acceptable, use the constant
+ * {@link FrameRateParams.IGNORE} in {@link #setFrameRate(FrameRateParams)} instead of
+ * building {@link FrameRateParams.Builder}.
+ *
+ * @see FrameRateParams#getDesiredMinRate()
+ * @see FrameRateParams#getDesiredMaxRate()
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public Builder setDesiredRateRange(@FloatRange(from = 0.0) float desiredMinRate,
+ @FloatRange(from = 0.0) float desiredMaxRate) {
+ if (desiredMaxRate < desiredMinRate) {
+ Log.e(TAG,
+ "Failed to set desired frame rate range. desiredMaxRate should be "
+ + "greater than or equal to desiredMinRate");
+ return this;
+ }
+ mDesiredMinRate = desiredMinRate;
+ mDesiredMaxRate = desiredMaxRate;
+ return this;
+ }
+
+ /**
+ * Sets the fixed frame rate of the surface when its content has a fixed frame rate,
+ * e.g. a video with a fixed frame rate.
+ *
+ * When the frame rate chosen for the surface is the {@code fixedSourceRate} or a
+ * multiple, the surface can render without frame pulldown, for optimal smoothness. For
+ * example, a 30 fps video ({@code fixedSourceRate=30}) renders just as well on 30 fps,
+ * 60 fps, 90 fps, 120 fps, and so on.
+ *
+ * This method to set the fixed source rate can also be used together with a desired
+ * frame rate range via {@link FrameRateParams.Builder#setDesiredRateRange}. This still
+ * means the surface's content has a fixed frame rate of the provided {@code
+ * fixedSourceRate}, as well as it preferring to be within the desired frame rate range.
+ * For example, a 30 fps video {@code fixedSourceRate=30} and desired frame rate range
+ * [60,90] means the surface ideally prefers 60 fps (which is 30 fps * 2) or 90 fps (30
+ * fps * 3).
+ *
+ * @see FrameRateParams#getFixedSourceRate()
+ */
+ @NonNull
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public Builder setFixedSourceRate(@FloatRange(from = 0.0) float fixedSourceRate) {
+ mFixedSourceRate = fixedSourceRate;
+ return this;
+ }
+
+ /**
+ * Whether display refresh rate transitions caused by this surface should be seamless. A
+ * seamless transition is one that doesn't have any visual interruptions, such as a
+ * black screen for a second or two. Value is
+ * Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, or Surface.CHANGE_FRAME_RATE_ALWAYS
+ *
+ * @see FrameRateParams#getChangeFrameRateStrategy()
+ */
+ @NonNull
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public Builder setChangeFrameRateStrategy(
+ @ChangeFrameRateStrategy int changeFrameRateStrategy) {
+ mChangeFrameRateStrategy = changeFrameRateStrategy;
+ return this;
+ }
+
+ /**
+ * Builds the FrameRateParams object.
+ */
+ @NonNull
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public FrameRateParams build() {
+ FrameRateParams frameRate = new FrameRateParams();
+ frameRate.mDesiredMinRate = this.mDesiredMinRate;
+ frameRate.mDesiredMaxRate = this.mDesiredMaxRate;
+ frameRate.mFixedSourceRate = this.mFixedSourceRate;
+ frameRate.mChangeFrameRateStrategy = this.mChangeFrameRateStrategy;
+ return frameRate;
+ }
+ }
+
+ /**
+ * Gets the minimum desired frame rate.
+ * @see FrameRateParams.Builder#setDesiredRateRange()
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public float getDesiredMinRate() {
+ return mDesiredMinRate;
+ }
+
+ /**
+ * Gets the maximum desired frame rate.
+ * @see FrameRateParams.Builder#setDesiredRateRange()
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public float getDesiredMaxRate() {
+ return mDesiredMaxRate;
+ }
+
+ /**
+ * Gets the fixed source frame rate.
+ * @see FrameRateParams.Builder#setFixedSourceRate()
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public float getFixedSourceRate() {
+ return mFixedSourceRate;
+ }
+
+ /**
+ * Gets the strategy when changing frame rate.
+ * @see FrameRateParams.Builder#setChangeFrameRateStrategy
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ @ChangeFrameRateStrategy
+ public int getChangeFrameRateStrategy() {
+ return mChangeFrameRateStrategy;
+ }
+
+ float mDesiredMinRate;
+ float mDesiredMaxRate;
+ float mFixedSourceRate;
+ int mChangeFrameRateStrategy;
+ }
+
+ /**
+ * Sets the intended frame rate for this surface.
+ *
+ * <p>On devices that are capable of running the display at different frame rates,
+ * the system may choose a display refresh rate to better match this surface's frame
+ * rate. Usage of this API won't introduce frame rate throttling, or affect other
+ * aspects of the application's frame production pipeline. However, because the system
+ * may change the display refresh rate, calls to this function may result in changes
+ * to Choreographer callback timings, and changes to the time interval at which the
+ * system releases buffers back to the application.</p>
+ *
+ * <p>Note that this only has an effect for surfaces presented on the display. If this
+ * surface is consumed by something other than the system compositor, e.g. a media
+ * codec, this call has no effect.</p>
+ *
+ * @param frameRateParams The parameters describing the intended frame rate of this surface.
+ * Refer to {@link FrameRateParams} for details.
+ * @throws IllegalArgumentException If <code>frameRateParams</code> is invalid.
+ * @see #clearFrameRate()
+ */
+ @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
+ public void setFrameRate(@NonNull FrameRateParams frameRateParams) {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ // TODO(b/362798998): Logic currently incomplete: it uses fixed source rate over the
+ // desired min/max rates. Fix when plumbing is upgraded.
+ int compatibility = frameRateParams.getFixedSourceRate() == 0
+ ? FRAME_RATE_COMPATIBILITY_DEFAULT
+ : FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+ float frameRate = compatibility == FRAME_RATE_COMPATIBILITY_DEFAULT
+ ? frameRateParams.getDesiredMinRate()
+ : frameRateParams.getFixedSourceRate();
+ int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility,
+ frameRateParams.getChangeFrameRateStrategy());
+ if (error == -EINVAL) {
+ throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
+ } else if (error != 0) {
+ Log.e(TAG, "Failed to set frame rate on Surface. Native error: " + error);
+ }
+ }
+ }
+
+ /**
* Sets the intended frame rate for this surface.
*
* <p>On devices that are capable of running the display at different refresh rates,
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 0bcc9c1..a0d58d5 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -348,3 +348,10 @@
description: "Enables a switch to change the concequence of dragging a window to the top edge."
bug: "372614715"
}
+
+flag {
+ name: "enable_task_resizing_keyboard_shortcuts"
+ namespace: "lse_desktop_experience"
+ description: "Enables keyboard shortcuts for resizing tasks in desktop mode."
+ bug: "335819608"
+}
diff --git a/core/java/com/android/internal/widget/floatingtoolbar/OWNERS b/core/java/com/android/internal/widget/floatingtoolbar/OWNERS
index ed9425c..999ea0e 100644
--- a/core/java/com/android/internal/widget/floatingtoolbar/OWNERS
+++ b/core/java/com/android/internal/widget/floatingtoolbar/OWNERS
@@ -1 +1 @@
-include /core/java/android/view/selectiontoolbar/OWNERS
+include /core/java/android/permission/OWNERS
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6ab6476..2bf5268 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1494,8 +1494,8 @@
android:description="@string/permdesc_readBasicPhoneState"
android:protectionLevel="normal" />
- <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
- granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
+ <!-- Allows read access to the device's phone number(s),
+ which is exposed to instant applications.
<p>Protection level: dangerous-->
<permission android:name="android.permission.READ_PHONE_NUMBERS"
android:permissionGroup="android.permission-group.UNDEFINED"
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index a3d2d7f..4385327 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -16,6 +16,10 @@
package androidx.window.extensions.area;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import android.app.Activity;
@@ -23,6 +27,7 @@
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateRequest;
+import android.hardware.devicestate.feature.flags.Flags;
import android.hardware.display.DisplayManager;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -72,18 +77,18 @@
@GuardedBy("mLock")
private final ArraySet<Consumer<ExtensionWindowAreaStatus>>
mRearDisplayPresentationStatusListeners = new ArraySet<>();
- private final int mRearDisplayState;
+ private int mRearDisplayState = INVALID_DEVICE_STATE_IDENTIFIER;
private final int mConcurrentDisplayState;
@NonNull
- private final int[] mFoldedDeviceStates;
+ private int[] mFoldedDeviceStates = new int[0];
private long mRearDisplayAddress = INVALID_DISPLAY_ADDRESS;
@WindowAreaSessionState
private int mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_INACTIVE;
@GuardedBy("mLock")
- private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
+ private DeviceState mCurrentDeviceState = INVALID_DEVICE_STATE;
@GuardedBy("mLock")
- private int[] mCurrentSupportedDeviceStates;
+ private List<DeviceState> mCurrentSupportedDeviceStates;
@GuardedBy("mLock")
private DeviceStateRequest mRearDisplayStateRequest;
@@ -103,16 +108,25 @@
mDisplayManager = context.getSystemService(DisplayManager.class);
mExecutor = context.getMainExecutor();
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(
- mDeviceStateManager.getSupportedDeviceStates());
- mFoldedDeviceStates = context.getResources().getIntArray(
- R.array.config_foldedDeviceStates);
+ mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedDeviceStates();
- // TODO(b/236022708) Move rear display state to device state config file
- mRearDisplayState = context.getResources().getInteger(
- R.integer.config_deviceStateRearDisplay);
+ if (Flags.deviceStatePropertyMigration()) {
+ for (int i = 0; i < mCurrentSupportedDeviceStates.size(); i++) {
+ DeviceState state = mCurrentSupportedDeviceStates.get(i);
+ if (state.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY)) {
+ mRearDisplayState = state.getIdentifier();
+ break;
+ }
+ }
+ } else {
+ mFoldedDeviceStates = context.getResources().getIntArray(
+ R.array.config_foldedDeviceStates);
+ // TODO(b/236022708) Move rear display state to device state config file
+ mRearDisplayState = context.getResources().getInteger(
+ R.integer.config_deviceStateRearDisplay);
+ }
+ // TODO(b/374351956) Use DeviceState API when the dual display state is always returned
mConcurrentDisplayState = context.getResources().getInteger(
R.integer.config_deviceStateConcurrentRearDisplay);
@@ -147,7 +161,7 @@
mRearDisplayStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided.
- if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
+ if (mCurrentDeviceState.getIdentifier() == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
consumer.accept(getCurrentRearDisplayModeStatus());
@@ -312,7 +326,7 @@
mRearDisplayPresentationStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided
- if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
+ if (mCurrentDeviceState.getIdentifier() == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
@WindowAreaStatus int currentStatus = getCurrentRearDisplayPresentationModeStatus();
@@ -452,8 +466,7 @@
@Override
public void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) {
synchronized (mLock) {
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(supportedStates);
+ mCurrentSupportedDeviceStates = supportedStates;
updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
updateRearDisplayPresentationStatusListeners(
getCurrentRearDisplayPresentationModeStatus());
@@ -463,8 +476,7 @@
@Override
public void onDeviceStateChanged(@NonNull DeviceState state) {
synchronized (mLock) {
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentDeviceState = state.getIdentifier();
+ mCurrentDeviceState = state;
updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
updateRearDisplayPresentationStatusListeners(
getCurrentRearDisplayPresentationModeStatus());
@@ -477,7 +489,8 @@
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
- if (!ArrayUtils.contains(mCurrentSupportedDeviceStates, mRearDisplayState)) {
+ if (!deviceStateListContainsIdentifier(mCurrentSupportedDeviceStates,
+ mRearDisplayState)) {
return WindowAreaComponent.STATUS_UNAVAILABLE;
}
@@ -488,15 +501,6 @@
return WindowAreaComponent.STATUS_AVAILABLE;
}
- // TODO(b/329436166): Remove and update the usage of device state manager API's
- private int[] getSupportedStateIdentifiers(@NonNull List<DeviceState> states) {
- int[] identifiers = new int[states.size()];
- for (int i = 0; i < states.size(); i++) {
- identifiers[i] = states.get(i).getIdentifier();
- }
- return identifiers;
- }
-
/**
* Helper method to determine if a rear display session is currently active by checking
* if the current device state is that which corresponds to {@code mRearDisplayState}.
@@ -505,7 +509,31 @@
*/
@GuardedBy("mLock")
private boolean isRearDisplayActive() {
- return mCurrentDeviceState == mRearDisplayState;
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY);
+ } else {
+ return mCurrentDeviceState.getIdentifier() == mRearDisplayState;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean isRearDisplayPresentationModeActive() {
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT);
+ } else {
+ return mCurrentDeviceState.getIdentifier() == mConcurrentDisplayState;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean deviceStateListContainsIdentifier(List<DeviceState> deviceStates,
+ int identifier) {
+ for (int i = 0; i < deviceStates.size(); i++) {
+ if (deviceStates.get(i).getIdentifier() == identifier) {
+ return true;
+ }
+ }
+ return false;
}
@GuardedBy("mLock")
@@ -526,12 +554,12 @@
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
- if (mCurrentDeviceState == mConcurrentDisplayState) {
+ if (isRearDisplayPresentationModeActive()) {
return WindowAreaComponent.STATUS_ACTIVE;
}
- if (!ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
- || isDeviceFolded()) {
+ if (!deviceStateListContainsIdentifier(mCurrentSupportedDeviceStates,
+ mConcurrentDisplayState) || isDeviceFolded()) {
return WindowAreaComponent.STATUS_UNAVAILABLE;
}
return WindowAreaComponent.STATUS_AVAILABLE;
@@ -539,7 +567,12 @@
@GuardedBy("mLock")
private boolean isDeviceFolded() {
- return ArrayUtils.contains(mFoldedDeviceStates, mCurrentDeviceState);
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
+ } else {
+ return ArrayUtils.contains(mFoldedDeviceStates, mCurrentDeviceState.getIdentifier());
+ }
}
@GuardedBy("mLock")
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt
index 79becb0..0e8e904 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt
@@ -122,7 +122,8 @@
snapshot.hardwareBuffer,
snapshot.colorSpace
)
- val scaledSnapshotBitmap = snapshotBitmap?.let {
+ val croppedBitmap = snapshotBitmap?.let { cropBitmap(it) }
+ val scaledSnapshotBitmap = croppedBitmap?.let {
Bitmap.createScaledBitmap(
it, instanceIconWidth.toInt(), instanceIconHeight.toInt(), true /* filter */
)
@@ -160,6 +161,35 @@
menuHeight += iconMargin.toInt()
}
+ private fun cropBitmap(
+ bitmapToCrop: Bitmap
+ ): Bitmap {
+ val ratioToMatch = ICON_WIDTH_DP / ICON_HEIGHT_DP
+ val bitmapWidth = bitmapToCrop.width
+ val bitmapHeight = bitmapToCrop.height
+ if (bitmapWidth > bitmapHeight * ratioToMatch) {
+ // Crop based on height
+ val newWidth = bitmapHeight * ratioToMatch
+ return Bitmap.createBitmap(
+ bitmapToCrop,
+ ((bitmapWidth - newWidth) / 2).toInt(),
+ 0,
+ newWidth.toInt(),
+ bitmapHeight
+ )
+ } else {
+ // Crop based on width
+ val newHeight = bitmapWidth / ratioToMatch
+ return Bitmap.createBitmap(
+ bitmapToCrop,
+ 0,
+ ((bitmapHeight - newHeight) / 2).toInt(),
+ bitmapWidth,
+ newHeight.toInt()
+ )
+ }
+ }
+
companion object {
private const val MENU_RADIUS_DP = 26f
private const val ICON_WIDTH_DP = 204f
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index 28856c8..8af4b7e 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -60,6 +60,7 @@
"//apex_available:platform",
"com.android.os.statsd",
"test_com.android.os.statsd",
+ "com.android.uprobestats",
],
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index bfc00bb..b48c55d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -329,18 +329,6 @@
disconnectFromRemoteDocument();
}
- public void kill(String reason) {
- if (DEBUG) {
- Log.i(LOG_TAG, "[CALLED] kill()");
- }
-
- try {
- mPrintDocumentAdapter.kill(reason);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error calling kill()", re);
- }
- }
-
public boolean isUpdating() {
return mState == STATE_UPDATING || mState == STATE_CANCELING;
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index c4173ed..bd2b5ec 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -514,8 +514,12 @@
ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);
setState(STATE_UPDATE_FAILED);
-
- mPrintedDocument.kill(message);
+ if (DEBUG) {
+ Log.i(LOG_TAG, "PrintJob state[" + PrintJobInfo.STATE_FAILED + "] reason: " + message);
+ }
+ PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
+ spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_FAILED, message);
+ mPrintedDocument.finish();
}
@Override
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/back/FlingOnBackAnimationCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/back/FlingOnBackAnimationCallback.kt
new file mode 100644
index 0000000..6da06d0
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/back/FlingOnBackAnimationCallback.kt
@@ -0,0 +1,166 @@
+/*
+ * 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.animation.back
+
+import android.util.TimeUtils
+import android.view.Choreographer
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.VelocityTracker
+import android.view.animation.Interpolator
+import android.window.BackEvent
+import android.window.OnBackAnimationCallback
+import com.android.app.animation.Interpolators
+import com.android.internal.dynamicanimation.animation.DynamicAnimation
+import com.android.internal.dynamicanimation.animation.FlingAnimation
+import com.android.internal.dynamicanimation.animation.FloatValueHolder
+import com.android.window.flags.Flags.predictiveBackTimestampApi
+
+private const val FLING_FRICTION = 6f
+private const val SCALE_FACTOR = 100f
+
+/**
+ * Enhanced [OnBackAnimationCallback] with automatic fling animation and interpolated progress.
+ *
+ * Simplifies back gesture handling by animating flings and emitting processed events through
+ * `compat` functions. Customize progress interpolation with an optional [Interpolator].
+ *
+ * @param progressInterpolator [Interpolator] for progress, defaults to
+ * [Interpolators.BACK_GESTURE].
+ */
+abstract class FlingOnBackAnimationCallback(
+ val progressInterpolator: Interpolator = Interpolators.BACK_GESTURE
+) : OnBackAnimationCallback {
+
+ private val velocityTracker = VelocityTracker.obtain()
+ private var lastBackEvent: BackEvent? = null
+ private var downTime: Long? = null
+
+ private var backInvokedFlingAnim: FlingAnimation? = null
+ private val backInvokedFlingUpdateListener =
+ DynamicAnimation.OnAnimationUpdateListener { _, progress: Float, _ ->
+ lastBackEvent?.let {
+ val backEvent =
+ BackEvent(
+ it.touchX,
+ it.touchY,
+ progress / SCALE_FACTOR,
+ it.swipeEdge,
+ it.frameTime,
+ )
+ onBackProgressedCompat(backEvent)
+ }
+ }
+ private val backInvokedFlingEndListener =
+ DynamicAnimation.OnAnimationEndListener { _, _, _, _ ->
+ onBackInvokedCompat()
+ reset()
+ }
+
+ abstract fun onBackStartedCompat(backEvent: BackEvent)
+
+ abstract fun onBackProgressedCompat(backEvent: BackEvent)
+
+ abstract fun onBackInvokedCompat()
+
+ abstract fun onBackCancelledCompat()
+
+ final override fun onBackStarted(backEvent: BackEvent) {
+ if (backInvokedFlingAnim != null) {
+ // This should never happen but let's call onBackInvokedCompat() just in case there is
+ // still a fling animation in progress
+ onBackInvokedCompat()
+ }
+ reset()
+ if (predictiveBackTimestampApi()) {
+ downTime = backEvent.frameTime
+ }
+ onBackStartedCompat(backEvent)
+ }
+
+ final override fun onBackProgressed(backEvent: BackEvent) {
+ val interpolatedProgress = progressInterpolator.getInterpolation(backEvent.progress)
+ if (predictiveBackTimestampApi()) {
+ velocityTracker.addMovement(
+ MotionEvent.obtain(
+ /* downTime */ downTime!!,
+ /* eventTime */ backEvent.frameTime,
+ /* action */ ACTION_MOVE,
+ /* x */ interpolatedProgress * SCALE_FACTOR,
+ /* y */ 0f,
+ /* metaState */ 0,
+ )
+ )
+ lastBackEvent =
+ BackEvent(
+ backEvent.touchX,
+ backEvent.touchY,
+ interpolatedProgress,
+ backEvent.swipeEdge,
+ backEvent.frameTime,
+ )
+ } else {
+ lastBackEvent =
+ BackEvent(
+ backEvent.touchX,
+ backEvent.touchY,
+ interpolatedProgress,
+ backEvent.swipeEdge,
+ )
+ }
+ lastBackEvent?.let { onBackProgressedCompat(it) }
+ }
+
+ final override fun onBackInvoked() {
+ if (predictiveBackTimestampApi() && lastBackEvent != null) {
+ velocityTracker.computeCurrentVelocity(1000)
+ backInvokedFlingAnim =
+ FlingAnimation(FloatValueHolder())
+ .setStartValue((lastBackEvent?.progress ?: 0f) * SCALE_FACTOR)
+ .setFriction(FLING_FRICTION)
+ .setStartVelocity(velocityTracker.xVelocity)
+ .setMinValue(0f)
+ .setMaxValue(SCALE_FACTOR)
+ .also {
+ it.addUpdateListener(backInvokedFlingUpdateListener)
+ it.addEndListener(backInvokedFlingEndListener)
+ it.start()
+ // do an animation-frame immediately to prevent idle frame
+ it.doAnimationFrame(
+ Choreographer.getInstance().lastFrameTimeNanos / TimeUtils.NANOS_PER_MS
+ )
+ }
+ } else {
+ onBackInvokedCompat()
+ reset()
+ }
+ }
+
+ final override fun onBackCancelled() {
+ onBackCancelledCompat()
+ reset()
+ }
+
+ private fun reset() {
+ velocityTracker.clear()
+ backInvokedFlingAnim?.removeEndListener(backInvokedFlingEndListener)
+ backInvokedFlingAnim?.removeUpdateListener(backInvokedFlingUpdateListener)
+ lastBackEvent = null
+ backInvokedFlingAnim = null
+ downTime = null
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt
index 8740d14..f708de3 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt
@@ -23,6 +23,7 @@
import android.window.OnBackAnimationCallback
import android.window.OnBackInvokedDispatcher
import android.window.OnBackInvokedDispatcher.Priority
+import com.android.app.animation.Interpolators
/**
* Generates an [OnBackAnimationCallback] given a [backAnimationSpec]. [onBackProgressed] will be
@@ -40,16 +41,16 @@
onBackInvoked: () -> Unit = {},
onBackCancelled: () -> Unit = {},
): OnBackAnimationCallback {
- return object : OnBackAnimationCallback {
+ return object : FlingOnBackAnimationCallback(progressInterpolator = Interpolators.LINEAR) {
private var initialY = 0f
private val lastTransformation = BackTransformation()
- override fun onBackStarted(backEvent: BackEvent) {
+ override fun onBackStartedCompat(backEvent: BackEvent) {
initialY = backEvent.touchY
onBackStarted(backEvent)
}
- override fun onBackProgressed(backEvent: BackEvent) {
+ override fun onBackProgressedCompat(backEvent: BackEvent) {
val progressY = (backEvent.touchY - initialY) / displayMetrics.heightPixels
backAnimationSpec.getBackTransformation(
@@ -61,11 +62,11 @@
onBackProgressed(lastTransformation)
}
- override fun onBackInvoked() {
+ override fun onBackInvokedCompat() {
onBackInvoked()
}
- override fun onBackCancelled() {
+ override fun onBackCancelledCompat() {
onBackCancelled()
}
}
@@ -86,7 +87,7 @@
override fun onViewAttachedToWindow(v: View) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
priority,
- onBackAnimationCallback
+ onBackAnimationCallback,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/back/FlingOnBackAnimationCallbackTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/back/FlingOnBackAnimationCallbackTest.kt
new file mode 100644
index 0000000..75a5768
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/back/FlingOnBackAnimationCallbackTest.kt
@@ -0,0 +1,127 @@
+/*
+ * 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.animation.back
+
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.view.animation.Interpolator
+import android.window.BackEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.app.animation.Interpolators
+import com.android.systemui.SysuiTestCase
+import com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class FlingOnBackAnimationCallbackTest : SysuiTestCase() {
+
+ @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
+ @Test
+ fun testProgressInterpolation() {
+ val mockInterpolator = Mockito.mock(Interpolator::class.java)
+ val backEvent = backEventOf(0.5f)
+ Mockito.`when`(mockInterpolator.getInterpolation(0.5f)).thenReturn(0.8f)
+ val callback = TestFlingOnBackAnimationCallback(mockInterpolator)
+ callback.onBackStarted(backEvent)
+ assertTrue("Assert onBackStartedCompat called", callback.backStartedCalled)
+ callback.onBackProgressed(backEvent)
+ assertTrue("Assert onBackProgressedCompat called", callback.backProgressedCalled)
+ assertEquals("Assert interpolated progress", 0.8f, callback.progressEvent?.progress)
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_TIMESTAMP_API)
+ fun testFling() {
+ val callback = TestFlingOnBackAnimationCallback(Interpolators.LINEAR)
+ callback.onBackStarted(backEventOf(progress = 0f, frameTime = 0))
+ assertTrue("Assert onBackStartedCompat called", callback.backStartedCalled)
+ callback.onBackProgressed(backEventOf(0f, 8))
+ callback.onBackProgressed(backEventOf(0.2f, 16))
+ callback.onBackProgressed(backEventOf(0.4f, 24))
+ callback.onBackProgressed(backEventOf(0.6f, 32))
+ assertTrue("Assert onBackProgressedCompat called", callback.backProgressedCalled)
+ assertEquals("Assert interpolated progress", 0.6f, callback.progressEvent?.progress)
+ getInstrumentation().runOnMainSync { callback.onBackInvoked() }
+ // Assert that onBackInvoked is not called immediately...
+ assertFalse(callback.backInvokedCalled)
+ // Instead the fling animation is played and eventually onBackInvoked is called.
+ callback.backInvokedLatch.await(1000, TimeUnit.MILLISECONDS)
+ assertTrue(callback.backInvokedCalled)
+ }
+
+ @Test
+ @RequiresFlagsDisabled(FLAG_PREDICTIVE_BACK_TIMESTAMP_API)
+ fun testCallbackWithoutTimestampApi() {
+ // Assert that all callback methods are immediately forwarded
+ val callback = TestFlingOnBackAnimationCallback(Interpolators.LINEAR)
+ callback.onBackStarted(backEventOf(progress = 0f, frameTime = 0))
+ assertTrue("Assert onBackStartedCompat called", callback.backStartedCalled)
+ callback.onBackProgressed(backEventOf(0f, 8))
+ assertTrue("Assert onBackProgressedCompat called", callback.backProgressedCalled)
+ callback.onBackInvoked()
+ assertTrue("Assert onBackInvoked called", callback.backInvokedCalled)
+ callback.onBackCancelled()
+ assertTrue("Assert onBackCancelled called", callback.backCancelledCalled)
+ }
+
+ private fun backEventOf(progress: Float, frameTime: Long = 0): BackEvent {
+ return BackEvent(10f, 10f, progress, 0, frameTime)
+ }
+
+ /** Helper class to expose the compat functions for testing */
+ private class TestFlingOnBackAnimationCallback(progressInterpolator: Interpolator) :
+ FlingOnBackAnimationCallback(progressInterpolator) {
+ var backStartedCalled = false
+ var backProgressedCalled = false
+ var backInvokedCalled = false
+ val backInvokedLatch = CountDownLatch(1)
+ var backCancelledCalled = false
+ var progressEvent: BackEvent? = null
+
+ override fun onBackStartedCompat(backEvent: BackEvent) {
+ backStartedCalled = true
+ }
+
+ override fun onBackProgressedCompat(backEvent: BackEvent) {
+ backProgressedCalled = true
+ progressEvent = backEvent
+ }
+
+ override fun onBackInvokedCompat() {
+ backInvokedCalled = true
+ backInvokedLatch.countDown()
+ }
+
+ override fun onBackCancelledCompat() {
+ backCancelledCalled = true
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
index 5bd3645..99d2da67 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
@@ -30,9 +30,11 @@
import com.android.systemui.qs.pipeline.domain.interactor.panelInteractor
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.recordissue.IssueRecordingState
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.settings.userFileManager
import com.android.systemui.settings.userTracker
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.statusbar.policy.keyguardStateController
@@ -81,10 +83,11 @@
underTest =
IssueRecordingUserActionInteractor(
testDispatcher,
+ IssueRecordingState(userTracker, userFileManager),
KeyguardDismissUtil(
keyguardStateController,
statusBarStateController,
- activityStarter
+ activityStarter,
),
keyguardStateController,
dialogTransitionAnimator,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
index a1edfc1..a3f8127 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
@@ -107,7 +107,7 @@
@Test
fun requestBugreport_afterReceivingShareCommand_withTakeBugreportTrue() {
- issueRecordingState.takeBugreport = true
+ underTest.takeBugReport = true
val uri = mock<Uri>()
underTest.share(0, uri)
@@ -118,7 +118,7 @@
@Test
fun sharesTracesDirectly_afterReceivingShareCommand_withTakeBugreportFalse() {
- issueRecordingState.takeBugreport = false
+ underTest.takeBugReport = false
val uri = mock<Uri>()
underTest.share(0, uri)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
index f8de714..a831e63 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
@@ -38,6 +38,8 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.screenshot.scroll.ScrollCaptureClient.Session;
+import org.junit.Assume;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,6 +51,12 @@
@RunWith(AndroidJUnit4.class)
public class ScrollCaptureControllerTest extends SysuiTestCase {
+ @Before
+ public void assumeOnDevice() {
+ // TODO(b/373930957) this class hangs under robolectric
+ Assume.assumeFalse(isRobolectricTest());
+ }
+
private static final ScrollCaptureResponse EMPTY_RESPONSE =
new ScrollCaptureResponse.Builder().build();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index d1d3b9b..89ad699 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -85,7 +85,6 @@
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
import com.android.systemui.common.ui.view.LongPressHandlingView;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
@@ -434,15 +433,6 @@
new ShadeInteractorLegacyImpl(
mTestScope.getBackgroundScope(),
mFakeKeyguardRepository,
- new SharedNotificationContainerInteractor(
- new FakeConfigurationRepository(),
- mContext,
- () -> splitShadeStateController,
- () -> mShadeInteractor,
- mKeyguardInteractor,
- deviceEntryUdfpsInteractor,
- () -> mLargeScreenHeaderHelper
- ),
mShadeRepository
),
mKosmos.getShadeModeInteractor());
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index a52f173..2e759a3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -36,16 +36,12 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
@@ -55,7 +51,6 @@
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.qs.QSFragmentLegacy;
import com.android.systemui.res.R;
-import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
@@ -72,7 +67,6 @@
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -179,27 +173,11 @@
mStatusBarStateController = mKosmos.getStatusBarStateController();
mKosmos.getFakeDeviceProvisioningRepository().setDeviceProvisioned(true);
- FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
PowerInteractor powerInteractor = mKosmos.getPowerInteractor();
- SceneInteractor sceneInteractor = mKosmos.getSceneInteractor();
-
KeyguardTransitionInteractor keyguardTransitionInteractor =
mKosmos.getKeyguardTransitionInteractor();
- KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
- mKeyguardRepository,
- powerInteractor,
- new FakeKeyguardBouncerRepository(),
- new ConfigurationInteractor(configurationRepository),
- mShadeRepository,
- keyguardTransitionInteractor,
- () -> sceneInteractor,
- () -> mKosmos.getFromGoneTransitionInteractor(),
- () -> mKosmos.getFromLockscreenTransitionInteractor(),
- () -> mKosmos.getFromOccludedTransitionInteractor(),
- () -> mKosmos.getSharedNotificationContainerInteractor(),
- mTestScope);
ResourcesSplitShadeStateController splitShadeStateController =
new ResourcesSplitShadeStateController();
@@ -222,14 +200,6 @@
new ShadeInteractorLegacyImpl(
mTestScope.getBackgroundScope(),
mKeyguardRepository,
- new SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- () -> splitShadeStateController,
- () -> mShadeInteractor,
- keyguardInteractor,
- deviceEntryUdfpsInteractor,
- () -> mLargeScreenHeaderHelper),
mShadeRepository
),
mKosmos.getShadeModeInteractor());
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
index 4592b60..238a1c1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
@@ -26,9 +26,9 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.kosmos.testScope
-import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.fakeUserRepository
import com.google.common.truth.Truth.assertThat
@@ -46,6 +46,7 @@
class ShadeInteractorLegacyImplTest : SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
+ val shadeTestUtil = kosmos.shadeTestUtil
val configurationRepository = kosmos.fakeConfigurationRepository
val keyguardRepository = kosmos.fakeKeyguardRepository
val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
@@ -87,7 +88,7 @@
// WHEN split shade is enabled and QS is expanded
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- overrideResource(R.bool.config_use_split_notification_shade, true)
+ shadeTestUtil.setSplitShade(true)
configurationRepository.onAnyConfigurationChange()
shadeRepository.setQsExpansion(.5f)
shadeRepository.setLegacyShadeExpansion(.7f)
@@ -104,7 +105,7 @@
// WHEN split shade is not enabled and QS is expanded
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- overrideResource(R.bool.config_use_split_notification_shade, false)
+ shadeTestUtil.setSplitShade(false)
shadeRepository.setQsExpansion(.5f)
shadeRepository.setLegacyShadeExpansion(1f)
runCurrent()
@@ -120,7 +121,7 @@
// WHEN split shade is not enabled and QS is expanded
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- overrideResource(R.bool.config_use_split_notification_shade, false)
+ shadeTestUtil.setSplitShade(false)
shadeRepository.setQsExpansion(1f)
shadeRepository.setLegacyShadeExpansion(1f)
runCurrent()
@@ -136,7 +137,7 @@
// WHEN split shade is not enabled and QS partly expanded
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- overrideResource(R.bool.config_use_split_notification_shade, false)
+ shadeTestUtil.setSplitShade(false)
shadeRepository.setQsExpansion(.4f)
shadeRepository.setLegacyShadeExpansion(1f)
runCurrent()
@@ -152,7 +153,7 @@
// WHEN split shade is not enabled and QS collapsed
keyguardRepository.setStatusBarState(StatusBarState.SHADE)
- overrideResource(R.bool.config_use_split_notification_shade, false)
+ shadeTestUtil.setSplitShade(false)
shadeRepository.setQsExpansion(0f)
shadeRepository.setLegacyShadeExpansion(.6f)
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index add7ac9..25670cb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -161,7 +161,7 @@
fun validateMarginStartInSplitShade() =
testScope.runTest {
shadeTestUtil.setSplitShade(true)
- overrideResource(R.dimen.notification_panel_margin_horizontal, 20)
+ overrideDimensionPixelSize(R.dimen.notification_panel_margin_horizontal, 20)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -174,7 +174,7 @@
fun validateMarginStart() =
testScope.runTest {
shadeTestUtil.setSplitShade(false)
- overrideResource(R.dimen.notification_panel_margin_horizontal, 20)
+ overrideDimensionPixelSize(R.dimen.notification_panel_margin_horizontal, 20)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -189,8 +189,8 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
shadeTestUtil.setSplitShade(true)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
- overrideResource(R.dimen.large_screen_shade_header_height, 10)
- overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+ overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
+ overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
val paddingTop by collectLastValue(underTest.paddingTopDimen)
configurationRepository.onAnyConfigurationChange()
@@ -205,8 +205,8 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(10)
shadeTestUtil.setSplitShade(false)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
- overrideResource(R.dimen.large_screen_shade_header_height, 10)
- overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+ overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
+ overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
val paddingTop by collectLastValue(underTest.paddingTopDimen)
@@ -221,8 +221,8 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(10)
shadeTestUtil.setSplitShade(false)
overrideResource(R.bool.config_use_large_screen_shade_header, false)
- overrideResource(R.dimen.large_screen_shade_header_height, 10)
- overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+ overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
+ overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
val paddingTop by collectLastValue(underTest.paddingTopDimen)
@@ -263,8 +263,11 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
.thenReturn(headerHelperHeight)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
- overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight)
- overrideResource(R.dimen.notification_panel_margin_top, 0)
+ overrideDimensionPixelSize(
+ R.dimen.large_screen_shade_header_height,
+ headerResourceHeight,
+ )
+ overrideDimensionPixelSize(R.dimen.notification_panel_margin_top, 0)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -282,8 +285,11 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
.thenReturn(headerHelperHeight)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
- overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight)
- overrideResource(R.dimen.notification_panel_margin_top, 0)
+ overrideDimensionPixelSize(
+ R.dimen.large_screen_shade_header_height,
+ headerResourceHeight,
+ )
+ overrideDimensionPixelSize(R.dimen.notification_panel_margin_top, 0)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -480,8 +486,8 @@
fun validateMarginTop() =
testScope.runTest {
overrideResource(R.bool.config_use_large_screen_shade_header, false)
- overrideResource(R.dimen.large_screen_shade_header_height, 50)
- overrideResource(R.dimen.notification_panel_margin_top, 0)
+ overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 50)
+ overrideDimensionPixelSize(R.dimen.notification_panel_margin_top, 0)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -676,8 +682,8 @@
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
shadeTestUtil.setSplitShade(true)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
- overrideResource(R.dimen.large_screen_shade_header_height, 10)
- overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+ overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
+ overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
configurationRepository.onAnyConfigurationChange()
runCurrent()
@@ -1310,4 +1316,9 @@
communalSceneRepository.setTransitionState(transitionState)
runCurrent()
}
+
+ private fun overrideDimensionPixelSize(id: Int, pixelSize: Int) {
+ overrideResource(id, pixelSize)
+ configurationRepository.setDimensionPixelSize(id, pixelSize)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 94753f7..21a317a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -56,6 +57,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
@@ -675,8 +677,8 @@
backCallback.onBackProgressed(event);
verify(mBouncerViewDelegateBackCallback).onBackProgressed(eq(event));
- backCallback.onBackInvoked();
- verify(mBouncerViewDelegateBackCallback).onBackInvoked();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(backCallback::onBackInvoked);
+ verify(mBouncerViewDelegateBackCallback, timeout(1000)).onBackInvoked();
backCallback.onBackCancelled();
verify(mBouncerViewDelegateBackCallback).onBackCancelled();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelTest.kt
new file mode 100644
index 0000000..faf01ed
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelTest.kt
@@ -0,0 +1,144 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+import android.media.AudioManager.RINGER_MODE_NORMAL
+import android.media.AudioManager.RINGER_MODE_SILENT
+import android.media.AudioManager.RINGER_MODE_VIBRATE
+import android.media.AudioManager.STREAM_RING
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.volume.shared.model.RingerMode
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.haptics.fakeVibratorHelper
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.fakeVolumeDialogController
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+class VolumeDialogRingerDrawerViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val controller = kosmos.fakeVolumeDialogController
+ private val vibratorHelper = kosmos.fakeVibratorHelper
+
+ private lateinit var underTest: VolumeDialogRingerDrawerViewModel
+
+ @Before
+ fun setUp() {
+ underTest = kosmos.volumeDialogRingerDrawerViewModel
+ }
+
+ @Test
+ fun onSelectedRingerNormalModeButtonClicked_openDrawer() =
+ testScope.runTest {
+ val ringerViewModel by collectLastValue(underTest.ringerViewModel)
+ val normalRingerMode = RingerMode(RINGER_MODE_NORMAL)
+
+ setUpRingerModeAndOpenDrawer(normalRingerMode)
+
+ assertThat(ringerViewModel).isNotNull()
+ assertThat(ringerViewModel?.drawerState)
+ .isEqualTo(RingerDrawerState.Open(normalRingerMode))
+ }
+
+ @Test
+ fun onSelectedRingerButtonClicked_drawerOpened_closeDrawer() =
+ testScope.runTest {
+ val ringerViewModel by collectLastValue(underTest.ringerViewModel)
+ val normalRingerMode = RingerMode(RINGER_MODE_NORMAL)
+
+ setUpRingerModeAndOpenDrawer(normalRingerMode)
+ underTest.onRingerButtonClicked(normalRingerMode)
+ controller.getState()
+
+ assertThat(ringerViewModel).isNotNull()
+ assertThat(ringerViewModel?.drawerState)
+ .isEqualTo(RingerDrawerState.Closed(normalRingerMode))
+ }
+
+ @Test
+ fun onNewRingerButtonClicked_drawerOpened_updateRingerMode_closeDrawer() =
+ testScope.runTest {
+ val ringerViewModel by collectLastValue(underTest.ringerViewModel)
+ val vibrateRingerMode = RingerMode(RINGER_MODE_VIBRATE)
+
+ setUpRingerModeAndOpenDrawer(RingerMode(RINGER_MODE_NORMAL))
+ // Select vibrate ringer mode.
+ underTest.onRingerButtonClicked(vibrateRingerMode)
+ controller.getState()
+ runCurrent()
+
+ assertThat(ringerViewModel).isNotNull()
+ assertThat(
+ ringerViewModel
+ ?.availableButtons
+ ?.get(ringerViewModel!!.currentButtonIndex)
+ ?.ringerMode
+ )
+ .isEqualTo(vibrateRingerMode)
+ assertThat(ringerViewModel?.drawerState)
+ .isEqualTo(RingerDrawerState.Closed(vibrateRingerMode))
+
+ val silentRingerMode = RingerMode(RINGER_MODE_SILENT)
+ // Open drawer
+ underTest.onRingerButtonClicked(vibrateRingerMode)
+ controller.getState()
+
+ // Select silent ringer mode.
+ underTest.onRingerButtonClicked(silentRingerMode)
+ controller.getState()
+ runCurrent()
+
+ assertThat(ringerViewModel).isNotNull()
+ assertThat(
+ ringerViewModel
+ ?.availableButtons
+ ?.get(ringerViewModel!!.currentButtonIndex)
+ ?.ringerMode
+ )
+ .isEqualTo(silentRingerMode)
+ assertThat(ringerViewModel?.drawerState)
+ .isEqualTo(RingerDrawerState.Closed(silentRingerMode))
+ assertThat(controller.hasScheduledTouchFeedback).isFalse()
+ assertThat(vibratorHelper.totalVibrations).isEqualTo(2)
+ }
+
+ private fun TestScope.setUpRingerModeAndOpenDrawer(selectedRingerMode: RingerMode) {
+ controller.setStreamVolume(STREAM_RING, 50)
+ controller.setRingerMode(selectedRingerMode.value, false)
+ runCurrent()
+
+ underTest.onRingerButtonClicked(RingerMode(selectedRingerMode.value))
+ controller.getState()
+ runCurrent()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 2d27f1c0..6bcacd0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -32,7 +32,6 @@
import static androidx.constraintlayout.widget.ConstraintSet.TOP;
import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT;
-import static com.android.app.animation.InterpolatorsAndroidX.DECELERATE_QUINT;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static java.lang.Integer.max;
@@ -271,8 +270,7 @@
public void onBackProgressed(BackEvent event) {
float progress = event.getProgress();
// TODO(b/263819310): Update the interpolator to match spec.
- float scale = MIN_BACK_SCALE
- + (1 - MIN_BACK_SCALE) * (1 - DECELERATE_QUINT.getInterpolation(progress));
+ float scale = MIN_BACK_SCALE + (1 - MIN_BACK_SCALE) * (1 - progress);
setScale(scale);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 0d5ad54..29c6d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -50,7 +50,6 @@
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -93,7 +92,6 @@
private val fromGoneTransitionInteractor: Provider<FromGoneTransitionInteractor>,
private val fromLockscreenTransitionInteractor: Provider<FromLockscreenTransitionInteractor>,
private val fromOccludedTransitionInteractor: Provider<FromOccludedTransitionInteractor>,
- sharedNotificationContainerInteractor: Provider<SharedNotificationContainerInteractor>,
@Application applicationScope: CoroutineScope,
) {
// TODO(b/296118689): move to a repository
@@ -104,15 +102,16 @@
SceneContainerFlag.assertInLegacyMode()
combineTransform(
_notificationPlaceholderBounds,
- sharedNotificationContainerInteractor.get().configurationBasedDimensions,
keyguardTransitionInteractor.isInTransition(
edge = Edge.create(from = LOCKSCREEN, to = AOD)
),
- ) { bounds, cfg, isTransitioningToAod ->
+ shadeRepository.isShadeLayoutWide,
+ configurationInteractor.dimensionPixelSize(R.dimen.keyguard_split_shade_top_margin),
+ ) { bounds, isTransitioningToAod, useSplitShade, keyguardSplitShadeTopMargin ->
if (isTransitioningToAod) {
// Keep bounds stable during this transition, to prevent cases like smartspace
// popping in and adjusting the bounds. A prime example would be media playing,
- // which then updates smartspace on transition to AOD
+ // which then updates smartspace on transition to AOD.
return@combineTransform
}
@@ -120,8 +119,8 @@
// legacy placement behavior within notifications for splitshade.
emit(
if (MigrateClocksToBlueprint.isEnabled) {
- if (cfg.useSplitShade) {
- bounds.copy(bottom = bounds.bottom - cfg.keyguardSplitShadeTopMargin)
+ if (useSplitShade) {
+ bounds.copy(bottom = bounds.bottom - keyguardSplitShadeTopMargin)
} else {
bounds
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/flags/QsDetailedView.kt b/packages/SystemUI/src/com/android/systemui/qs/flags/QsDetailedView.kt
new file mode 100644
index 0000000..ffeec4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/flags/QsDetailedView.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.qs.flags
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.shade.shared.flag.DualShade
+
+/** Helper for reading or using the QS Detailed View flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object QsDetailedView {
+ /** The aconfig flag name */
+ const val FLAG_NAME = Flags.FLAG_QS_TILE_DETAILED_VIEW
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Is the flag enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() =
+ Flags.qsTileDetailedView() && // mainAconfigFlag
+ DualShade.isEnabled &&
+ SceneContainerFlag.isEnabled
+
+ // NOTE: Changes should also be made in getSecondaryFlags
+
+ /** The main aconfig flag. */
+ inline fun getMainAconfigFlag() = FlagToken(FLAG_NAME, Flags.qsTileDetailedView())
+
+ /** The set of secondary flags which must be enabled for qs detailed view to work properly */
+ inline fun getSecondaryFlags(): Sequence<FlagToken> =
+ sequenceOf(
+ DualShade.token
+ // NOTE: Changes should also be made in isEnabled
+ ) + SceneContainerFlag.getAllRequirements()
+
+ /** The full set of requirements for QsDetailedView */
+ inline fun getAllRequirements(): Sequence<FlagToken> {
+ return sequenceOf(getMainAconfigFlag()) + getSecondaryFlags()
+ }
+
+ /** Return all dependencies of this flag in pairs where [Pair.first] depends on [Pair.second] */
+ inline fun getFlagDependencies(): Sequence<Pair<FlagToken, FlagToken>> {
+ val mainAconfigFlag = getMainAconfigFlag()
+ return getSecondaryFlags().map { mainAconfigFlag to it }
+ }
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+
+ /** Returns a developer-readable string that describes the current requirement list. */
+ @JvmStatic
+ fun requirementDescription(): String {
+ return buildString {
+ getAllRequirements().forEach { requirement ->
+ append('\n')
+ append(if (requirement.isEnabled) " [MET]" else "[NOT MET]")
+ append(" ${requirement.name}")
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
index fb406d4..1792ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -152,7 +152,14 @@
recordingController.startCountdown(
DELAY_MS,
INTERVAL_MS,
- pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+ pendingServiceIntent(
+ getStartIntent(
+ userContextProvider.userContext,
+ issueRecordingState.traceConfig,
+ issueRecordingState.recordScreen,
+ issueRecordingState.takeBugreport,
+ )
+ ),
pendingServiceIntent(getStopIntent(userContextProvider.userContext)),
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
index 0c8a375..fceee5a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
@@ -35,6 +35,7 @@
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
+import com.android.systemui.recordissue.IssueRecordingState
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
import com.android.systemui.screenrecord.RecordingController
@@ -52,6 +53,7 @@
@Inject
constructor(
@Main private val mainCoroutineContext: CoroutineContext,
+ private val state: IssueRecordingState,
private val keyguardDismissUtil: KeyguardDismissUtil,
private val keyguardStateController: KeyguardStateController,
private val dialogTransitionAnimator: DialogTransitionAnimator,
@@ -104,8 +106,15 @@
recordingController.startCountdown(
DELAY_MS,
INTERVAL_MS,
- pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
- pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+ pendingServiceIntent(
+ getStartIntent(
+ userContextProvider.userContext,
+ state.traceConfig,
+ state.recordScreen,
+ state.takeBugreport,
+ )
+ ),
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext)),
)
private fun stopIssueRecordingService() =
@@ -117,6 +126,6 @@
userContextProvider.userContext,
RecordingService.REQUEST_CODE,
action,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
index 3f875bc..ad0ede4 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
@@ -38,6 +38,8 @@
import com.android.systemui.screenrecord.RecordingServiceStrings
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import com.android.traceur.MessageConstants.INTENT_EXTRA_TRACE_TYPE
+import com.android.traceur.TraceConfig
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -110,7 +112,13 @@
when (intent?.action) {
ACTION_START -> {
session.start()
- if (!issueRecordingState.recordScreen) {
+ with(session) {
+ traceConfig =
+ intent.getParcelableExtra(INTENT_EXTRA_TRACE_TYPE, TraceConfig::class.java)
+ takeBugReport = intent.getBooleanExtra(EXTRA_BUG_REPORT, false)
+ start()
+ }
+ if (!intent.getBooleanExtra(EXTRA_SCREEN_RECORD, false)) {
// If we don't want to record the screen, the ACTION_SHOW_START_NOTIF action
// will circumvent the RecordingService's screen recording start code.
return super.onStartCommand(Intent(ACTION_SHOW_START_NOTIF), flags, startId)
@@ -136,6 +144,8 @@
companion object {
private const val TAG = "IssueRecordingService"
private const val CHANNEL_ID = "issue_record"
+ const val EXTRA_SCREEN_RECORD = "extra_screenRecord"
+ const val EXTRA_BUG_REPORT = "extra_bugReport"
/**
* Get an intent to stop the issue recording service.
@@ -153,8 +163,17 @@
*
* @param context Context from the requesting activity
*/
- fun getStartIntent(context: Context): Intent =
- Intent(context, IssueRecordingService::class.java).setAction(ACTION_START)
+ fun getStartIntent(
+ context: Context,
+ traceConfig: TraceConfig,
+ screenRecord: Boolean,
+ bugReport: Boolean,
+ ): Intent =
+ Intent(context, IssueRecordingService::class.java)
+ .setAction(ACTION_START)
+ .putExtra(INTENT_EXTRA_TRACE_TYPE, traceConfig)
+ .putExtra(EXTRA_SCREEN_RECORD, screenRecord)
+ .putExtra(EXTRA_BUG_REPORT, bugReport)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
index ad9b4fe..4c01293 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
@@ -25,6 +25,7 @@
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
import com.android.systemui.settings.UserContextProvider
+import com.android.traceur.PresetTraceConfigs
import java.util.concurrent.Executor
private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
@@ -47,15 +48,17 @@
private val notificationManager: NotificationManager,
private val userContextProvider: UserContextProvider,
) {
+ var takeBugReport = false
+ var traceConfig = PresetTraceConfigs.getDefaultConfig()
fun start() {
- bgExecutor.execute { traceurConnection.startTracing(issueRecordingState.traceConfig) }
+ bgExecutor.execute { traceurConnection.startTracing(traceConfig) }
issueRecordingState.isRecording = true
}
fun stop(contentResolver: ContentResolver) {
bgExecutor.execute {
- if (issueRecordingState.traceConfig.longTrace) {
+ if (traceConfig.longTrace) {
Settings.Global.putInt(contentResolver, NOTIFY_SESSION_ENDED_SETTING, DISABLED)
}
traceurConnection.stopTracing()
@@ -71,7 +74,7 @@
UserHandle(userContextProvider.userContext.userId),
)
- if (issueRecordingState.takeBugreport) {
+ if (takeBugReport) {
iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
} else {
traceurConnection.shareTraces(screenRecording)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
index 0902c39..a1c3692 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
@@ -24,7 +24,6 @@
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.currentCoroutineContext
@@ -45,7 +44,6 @@
constructor(
@Application val scope: CoroutineScope,
keyguardRepository: KeyguardRepository,
- sharedNotificationContainerInteractor: SharedNotificationContainerInteractor,
repository: ShadeRepository,
) : BaseShadeInteractor {
init {
@@ -62,17 +60,17 @@
keyguardRepository.statusBarState,
repository.legacyShadeExpansion,
repository.qsExpansion,
- sharedNotificationContainerInteractor.isSplitShadeEnabled,
+ repository.isShadeLayoutWide,
) {
lockscreenShadeExpansion,
statusBarState,
legacyShadeExpansion,
qsExpansion,
- splitShadeEnabled ->
+ isShadeLayoutWide ->
when (statusBarState) {
// legacyShadeExpansion is 1 instead of 0 when QS is expanded
StatusBarState.SHADE ->
- if (!splitShadeEnabled && qsExpansion > 0f) 1f - qsExpansion
+ if (!isShadeLayoutWide && qsExpansion > 0f) 1f - qsExpansion
else legacyShadeExpansion
StatusBarState.KEYGUARD -> lockscreenShadeExpansion
// dragDownAmount, which drives lockscreenShadeExpansion resets to 0f when
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index c6f3d7d..564d52a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -16,17 +16,19 @@
package com.android.systemui.statusbar.events
-import android.annotation.IntDef
import androidx.core.animation.Animator
import androidx.core.animation.AnimatorSet
import androidx.core.animation.PathInterpolator
import com.android.systemui.Dumpable
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
import com.android.systemui.statusbar.policy.CallbackController
+import kotlinx.coroutines.flow.StateFlow
interface SystemStatusAnimationScheduler :
CallbackController<SystemStatusAnimationCallback>, Dumpable {
- @SystemAnimationState fun getAnimationState(): Int
+ /** StateFlow holding the current [SystemEventAnimationState] at any time. */
+ val animationState: StateFlow<SystemEventAnimationState>
fun onStatusEvent(event: StatusEvent)
@@ -63,34 +65,6 @@
}
}
-/** Animation state IntDef */
-@Retention(AnnotationRetention.SOURCE)
-@IntDef(
- value =
- [
- IDLE,
- ANIMATION_QUEUED,
- ANIMATING_IN,
- RUNNING_CHIP_ANIM,
- ANIMATING_OUT,
- SHOWING_PERSISTENT_DOT,
- ]
-)
-annotation class SystemAnimationState
-
-/** No animation is in progress */
-@SystemAnimationState const val IDLE = 0
-/** An animation is queued, and awaiting the debounce period */
-const val ANIMATION_QUEUED = 1
-/** System is animating out, and chip is animating in */
-const val ANIMATING_IN = 2
-/** Chip has animated in and is awaiting exit animation, and optionally playing its own animation */
-const val RUNNING_CHIP_ANIM = 3
-/** Chip is animating away and system is animating back */
-const val ANIMATING_OUT = 4
-/** Chip has animated away, and the persistent dot is showing */
-const val SHOWING_PERSISTENT_DOT = 5
-
/** Commonly-needed interpolators can go here */
@JvmField val STATUS_BAR_X_MOVE_OUT = PathInterpolator(0.33f, 0f, 0f, 1f)
@JvmField val STATUS_BAR_X_MOVE_IN = PathInterpolator(0f, 0f, 0f, 1f)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
index 5f9e426..5ff4423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
@@ -23,6 +23,12 @@
import androidx.core.animation.AnimatorSet
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingIn
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingOut
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimationQueued
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.RunningChipAnim
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.ShowingPersistentDot
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import com.android.systemui.util.Assert
import com.android.systemui.util.time.SystemClock
@@ -33,6 +39,7 @@
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.first
@@ -85,8 +92,8 @@
*/
private var currentlyDisplayedEvent: StatusEvent? = null
- /** StateFlow holding the current [SystemAnimationState] at any time. */
- private var animationState = MutableStateFlow(IDLE)
+ private val _animationState = MutableStateFlow(Idle)
+ override val animationState = _animationState.asStateFlow()
/** True if the persistent privacy dot should be active */
var hasPersistentDot = false
@@ -109,24 +116,22 @@
// Wait for animationState to become ANIMATION_QUEUED and scheduledEvent to be non null.
// Once this combination is stable for at least DEBOUNCE_DELAY, then start a chip enter
// animation
- animationState
+ _animationState
.combine(scheduledEvent) { animationState, scheduledEvent ->
Pair(animationState, scheduledEvent)
}
.debounce(DEBOUNCE_DELAY)
.collect { (animationState, event) ->
- if (animationState == ANIMATION_QUEUED && event != null) {
+ if (animationState == AnimationQueued && event != null) {
startAnimationLifecycle(event)
scheduledEvent.value = null
}
}
}
- coroutineScope.launch { animationState.collect { logger?.logAnimationStateUpdate(it) } }
+ coroutineScope.launch { _animationState.collect { logger?.logAnimationStateUpdate(it) } }
}
- @SystemAnimationState override fun getAnimationState(): Int = animationState.value
-
override fun onStatusEvent(event: StatusEvent) {
Assert.isMainThread()
@@ -146,11 +151,11 @@
logger?.logScheduleEvent(event)
scheduleEvent(event)
} else if (currentlyDisplayedEvent?.shouldUpdateFromEvent(event) == true) {
- logger?.logUpdateEvent(event, animationState.value)
+ logger?.logUpdateEvent(event, _animationState.value)
currentlyDisplayedEvent?.updateFromEvent(event)
if (event.forceVisible) hasPersistentDot = true
} else if (scheduledEvent.value?.shouldUpdateFromEvent(event) == true) {
- logger?.logUpdateEvent(event, animationState.value)
+ logger?.logUpdateEvent(event, _animationState.value)
scheduledEvent.value?.updateFromEvent(event)
} else {
logger?.logIgnoreEvent(event)
@@ -170,15 +175,15 @@
// the disappear animation will not animate into a dot but remove the chip entirely
hasPersistentDot = false
- if (animationState.value == SHOWING_PERSISTENT_DOT) {
+ if (_animationState.value == ShowingPersistentDot) {
// if we are currently showing a persistent dot, hide it and update the animationState
notifyHidePersistentDot()
if (scheduledEvent.value != null) {
- animationState.value = ANIMATION_QUEUED
+ _animationState.value = AnimationQueued
} else {
- animationState.value = IDLE
+ _animationState.value = Idle
}
- } else if (animationState.value == ANIMATING_OUT) {
+ } else if (_animationState.value == AnimatingOut) {
// if we are currently animating out, hide the dot. The animationState will be updated
// once the animation has ended in the onAnimationEnd callback
notifyHidePersistentDot()
@@ -206,9 +211,9 @@
cancelCurrentlyDisplayedEvent()
return
}
- if (animationState.value == IDLE) {
+ if (_animationState.value == Idle) {
// If we are in IDLE state, set it to ANIMATION_QUEUED now
- animationState.value = ANIMATION_QUEUED
+ _animationState.value = AnimationQueued
}
}
@@ -223,7 +228,7 @@
withTimeout(APPEAR_ANIMATION_DURATION) {
// wait for animationState to become RUNNING_CHIP_ANIM, then cancel the running
// animation job and run the disappear animation immediately
- animationState.first { it == RUNNING_CHIP_ANIM }
+ _animationState.first { it == RunningChipAnim }
currentlyRunningAnimationJob?.cancel()
runChipDisappearAnimation()
}
@@ -241,7 +246,7 @@
if (!event.showAnimation && event.forceVisible) {
// If animations are turned off, we'll transition directly to the dot
- animationState.value = SHOWING_PERSISTENT_DOT
+ _animationState.value = ShowingPersistentDot
notifyTransitionToPersistentDot(event)
return
}
@@ -277,7 +282,7 @@
if (hasPersistentDot) {
statusBarWindowControllerStore.defaultDisplay.setForceStatusBarVisible(true)
}
- animationState.value = ANIMATING_IN
+ _animationState.value = AnimatingIn
val animSet = collectStartAnimations()
if (animSet.totalDuration > 500) {
@@ -289,7 +294,7 @@
animSet.addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- animationState.value = RUNNING_CHIP_ANIM
+ _animationState.value = RunningChipAnim
}
}
)
@@ -299,15 +304,15 @@
private fun runChipDisappearAnimation() {
Assert.isMainThread()
val animSet2 = collectFinishAnimations()
- animationState.value = ANIMATING_OUT
+ _animationState.value = AnimatingOut
animSet2.addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- animationState.value =
+ _animationState.value =
when {
- hasPersistentDot -> SHOWING_PERSISTENT_DOT
- scheduledEvent.value != null -> ANIMATION_QUEUED
- else -> IDLE
+ hasPersistentDot -> ShowingPersistentDot
+ scheduledEvent.value != null -> AnimationQueued
+ else -> Idle
}
statusBarWindowControllerStore.defaultDisplay.setForceStatusBarVisible(false)
}
@@ -401,7 +406,7 @@
pw.println("Scheduled event: ${scheduledEvent.value}")
pw.println("Currently displayed event: $currentlyDisplayedEvent")
pw.println("Has persistent privacy dot: $hasPersistentDot")
- pw.println("Animation state: ${animationState.value}")
+ pw.println("Animation state: ${_animationState.value}")
pw.println("Listeners:")
if (listeners.isEmpty()) {
pw.println("(none)")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt
index 22b0b69..a1f7a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt
@@ -3,15 +3,14 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
import javax.inject.Inject
/** Logs for the SystemStatusAnimationScheduler. */
@SysUISingleton
class SystemStatusAnimationSchedulerLogger
@Inject
-constructor(
- @SystemStatusAnimationSchedulerLog private val logBuffer: LogBuffer,
-) {
+constructor(@SystemStatusAnimationSchedulerLog private val logBuffer: LogBuffer) {
fun logScheduleEvent(event: StatusEvent) {
logBuffer.log(
@@ -23,11 +22,11 @@
bool1 = event.forceVisible
bool2 = event.showAnimation
},
- { "Scheduling event: $str1(forceVisible=$bool1, priority=$int1, showAnimation=$bool2)" }
+ { "Scheduling event: $str1(forceVisible=$bool1, priority=$int1, showAnimation=$bool2)" },
)
}
- fun logUpdateEvent(event: StatusEvent, @SystemAnimationState animationState: Int) {
+ fun logUpdateEvent(event: StatusEvent, animationState: SystemEventAnimationState) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
@@ -36,12 +35,12 @@
int1 = event.priority
bool1 = event.forceVisible
bool2 = event.showAnimation
- int2 = animationState
+ str2 = animationState.name
},
{
"Updating current event from: $str1(forceVisible=$bool1, priority=$int1, " +
- "showAnimation=$bool2), animationState=${animationState.name()}"
- }
+ "showAnimation=$bool2), animationState=$str2"
+ },
)
}
@@ -55,7 +54,7 @@
bool1 = event.forceVisible
bool2 = event.showAnimation
},
- { "Ignore event: $str1(forceVisible=$bool1, priority=$int1, showAnimation=$bool2)" }
+ { "Ignore event: $str1(forceVisible=$bool1, priority=$int1, showAnimation=$bool2)" },
)
}
@@ -67,26 +66,14 @@
logBuffer.log(TAG, LogLevel.DEBUG, "Transition to persistent dot callback invoked")
}
- fun logAnimationStateUpdate(@SystemAnimationState animationState: Int) {
+ fun logAnimationStateUpdate(animationState: SystemEventAnimationState) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
- { int1 = animationState },
- { "AnimationState update: ${int1.name()}" }
+ { str1 = animationState.name },
+ { "AnimationState update: $str1" },
)
- animationState.name()
}
-
- private fun @receiver:SystemAnimationState Int.name() =
- when (this) {
- IDLE -> "IDLE"
- ANIMATION_QUEUED -> "ANIMATION_QUEUED"
- ANIMATING_IN -> "ANIMATING_IN"
- RUNNING_CHIP_ANIM -> "RUNNING_CHIP_ANIM"
- ANIMATING_OUT -> "ANIMATING_OUT"
- SHOWING_PERSISTENT_DOT -> "SHOWING_PERSISTENT_DOT"
- else -> "UNKNOWN_ANIMATION_STATE"
- }
}
private const val TAG = "SystemStatusAnimationSchedulerLog"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/shared/model/SystemEventAnimationState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/shared/model/SystemEventAnimationState.kt
new file mode 100644
index 0000000..2446b81
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/shared/model/SystemEventAnimationState.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.statusbar.events.shared.model
+
+/** Direct representation of the system event animation scheduler's current state */
+enum class SystemEventAnimationState {
+ /** No animation is in progress */
+ Idle,
+ /** An animation is queued, and awaiting the debounce period */
+ AnimationQueued,
+ /** System is animating out, and chip is animating in */
+ AnimatingIn,
+ /**
+ * Chip has animated in and is awaiting exit animation, and optionally playing its own animation
+ */
+ RunningChipAnim,
+ /** Chip is animating away and system is animating back */
+ AnimatingOut,
+ /** Chip has animated away, and the persistent dot is showing */
+ ShowingPersistentDot,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
index 5d37476..6042964 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
@@ -18,7 +18,7 @@
package com.android.systemui.statusbar.notification.stack.domain.interactor
import android.content.Context
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -29,6 +29,8 @@
import com.android.systemui.statusbar.policy.SplitShadeStateController
import dagger.Lazy
import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -36,17 +38,17 @@
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onStart
/** Encapsulates business-logic specifically related to the shared notification stack container. */
+@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
@SysUISingleton
class SharedNotificationContainerInteractor
@Inject
constructor(
- configurationRepository: ConfigurationRepository,
private val context: Context,
private val splitShadeStateController: Lazy<SplitShadeStateController>,
private val shadeInteractor: Lazy<ShadeInteractor>,
+ configurationInteractor: ConfigurationInteractor,
keyguardInteractor: KeyguardInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
@@ -59,9 +61,6 @@
/** An internal modification was made to notifications */
val notificationStackChanged = _notificationStackChanged.debounce(20L)
- private val configurationChangeEvents =
- configurationRepository.onAnyConfigurationChange.onStart { emit(Unit) }
-
/* Warning: Even though the value it emits only contains the split shade status, this flow must
* emit a value whenever the configuration *or* the split shade status changes. Adding a
* distinctUntilChanged() to this would cause configurationBasedDimensions to miss configuration
@@ -69,13 +68,14 @@
*/
private val dimensionsUpdateEventsWithShouldUseSplitShade: Flow<Boolean> =
if (SceneContainerFlag.isEnabled) {
- combine(configurationChangeEvents, shadeInteractor.get().isShadeLayoutWide) {
- _,
- isShadeLayoutWide ->
+ combine(
+ configurationInteractor.onAnyConfigurationChange,
+ shadeInteractor.get().isShadeLayoutWide,
+ ) { _, isShadeLayoutWide ->
isShadeLayoutWide
}
} else {
- configurationChangeEvents.map {
+ configurationInteractor.onAnyConfigurationChange.map {
splitShadeStateController.get().shouldUseSplitNotificationShade(context.resources)
}
}
@@ -115,11 +115,6 @@
isUdfpsSupported || !ambientIndicationVisible
}
- val isSplitShadeEnabled: Flow<Boolean> =
- configurationBasedDimensions
- .map { dimens: ConfigurationBasedDimensions -> dimens.useSplitShade }
- .distinctUntilChanged()
-
/** Top position (without translation) of the shared container. */
fun setTopPosition(top: Float) {
_topPosition.value = top
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 878ae91..9515029 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -484,19 +484,28 @@
}
fun keyguardAlpha(viewState: ViewStateAccessor, scope: CoroutineScope): Flow<Float> {
+ val isKeyguardOccluded =
+ keyguardTransitionInteractor.transitionValue(OCCLUDED).map { it == 1f }
+
+ val isKeyguardNotVisibleInState =
+ if (SceneContainerFlag.isEnabled) {
+ isKeyguardOccluded
+ } else {
+ anyOf(
+ isKeyguardOccluded,
+ keyguardTransitionInteractor
+ .transitionValue(scene = Scenes.Gone, stateWithoutSceneContainer = GONE)
+ .map { it == 1f },
+ )
+ }
+
// Transitions are not (yet) authoritative for NSSL; they still rely on StatusBarState to
// help determine when the device has fully moved to GONE or OCCLUDED state. Once SHADE
// state has been set, let shade alpha take over
val isKeyguardNotVisible =
- combine(
- anyOf(
- keyguardTransitionInteractor.transitionValue(OCCLUDED).map { it == 1f },
- keyguardTransitionInteractor
- .transitionValue(scene = Scenes.Gone, stateWithoutSceneContainer = GONE)
- .map { it == 1f },
- ),
- keyguardInteractor.statusBarState,
- ) { isKeyguardNotVisibleInState, statusBarState ->
+ combine(isKeyguardNotVisibleInState, keyguardInteractor.statusBarState) {
+ isKeyguardNotVisibleInState,
+ statusBarState ->
isKeyguardNotVisibleInState && statusBarState == SHADE
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f7fea7b..92b609e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -56,6 +56,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.Flags;
+import com.android.systemui.animation.back.FlingOnBackAnimationCallback;
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
@@ -236,9 +237,10 @@
}
};
- private final OnBackAnimationCallback mOnBackInvokedCallback = new OnBackAnimationCallback() {
+ private final OnBackAnimationCallback mOnBackInvokedCallback =
+ new FlingOnBackAnimationCallback() {
@Override
- public void onBackInvoked() {
+ public void onBackInvokedCompat() {
if (DEBUG) {
Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
}
@@ -249,21 +251,21 @@
}
@Override
- public void onBackProgressed(BackEvent event) {
+ public void onBackProgressedCompat(@NonNull BackEvent event) {
if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackProgressed(event);
}
}
@Override
- public void onBackCancelled() {
+ public void onBackCancelledCompat() {
if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackCancelled();
}
}
@Override
- public void onBackStarted(BackEvent event) {
+ public void onBackStartedCompat(@NonNull BackEvent event) {
if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackStarted(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerButtonViewModel.kt
new file mode 100644
index 0000000..78d2d16
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerButtonViewModel.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+import android.annotation.DrawableRes
+import android.annotation.StringRes
+import com.android.settingslib.volume.shared.model.RingerMode
+
+/** Models ringer button that corresponds to each ringer mode. */
+data class RingerButtonViewModel(
+ /** Image resource id for the image button. */
+ @DrawableRes val imageResId: Int,
+ /** Content description for a11y. */
+ @StringRes val contentDescriptionResId: Int,
+ /** Hint label for accessibility use. */
+ @StringRes val hintLabelResId: Int,
+ /** Used to notify view model when button is clicked. */
+ val ringerMode: RingerMode,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerDrawerState.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerDrawerState.kt
new file mode 100644
index 0000000..f321837
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerDrawerState.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+import com.android.settingslib.volume.shared.model.RingerMode
+
+/** Models volume dialog ringer drawer state */
+sealed interface RingerDrawerState {
+
+ /** When clicked to open drawer */
+ data class Open(val mode: RingerMode) : RingerDrawerState
+
+ /** When clicked to close drawer */
+ data class Closed(val mode: RingerMode) : RingerDrawerState
+
+ /** Initial state when volume dialog is shown with a closed drawer. */
+ interface Initial : RingerDrawerState {
+ companion object : Initial
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModel.kt
new file mode 100644
index 0000000..a09bfeb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModel.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+/** Models volume dialog ringer */
+data class RingerViewModel(
+ /** List of the available buttons according to the available modes */
+ val availableButtons: List<RingerButtonViewModel?>,
+ /** The index of the currently selected button */
+ val currentButtonIndex: Int,
+ /** For open and close animations */
+ val drawerState: RingerDrawerState,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
new file mode 100644
index 0000000..ac82ae3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
@@ -0,0 +1,172 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+import android.media.AudioAttributes
+import android.media.AudioManager.RINGER_MODE_NORMAL
+import android.media.AudioManager.RINGER_MODE_SILENT
+import android.media.AudioManager.RINGER_MODE_VIBRATE
+import android.os.VibrationEffect
+import com.android.settingslib.volume.shared.model.RingerMode
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.volume.Events
+import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
+import com.android.systemui.volume.dialog.ringer.domain.VolumeDialogRingerInteractor
+import com.android.systemui.volume.dialog.ringer.shared.model.VolumeDialogRingerModel
+import com.android.systemui.volume.dialog.shared.VolumeDialogLogger
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.stateIn
+
+private const val TAG = "VolumeDialogRingerDrawerViewModel"
+
+class VolumeDialogRingerDrawerViewModel
+@AssistedInject
+constructor(
+ @VolumeDialog private val coroutineScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val interactor: VolumeDialogRingerInteractor,
+ private val vibrator: VibratorHelper,
+ private val volumeDialogLogger: VolumeDialogLogger,
+) {
+
+ private val drawerState = MutableStateFlow<RingerDrawerState>(RingerDrawerState.Initial)
+
+ val ringerViewModel: Flow<RingerViewModel> =
+ combine(interactor.ringerModel, drawerState) { ringerModel, state ->
+ ringerModel.toViewModel(state)
+ }
+ .flowOn(backgroundDispatcher)
+ .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+ .filterNotNull()
+
+ // Vibration attributes.
+ private val sonificiationVibrationAttributes =
+ AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build()
+
+ fun onRingerButtonClicked(ringerMode: RingerMode) {
+ if (drawerState.value is RingerDrawerState.Open) {
+ Events.writeEvent(Events.EVENT_RINGER_TOGGLE, ringerMode.value)
+ provideTouchFeedback(ringerMode)
+ interactor.setRingerMode(ringerMode)
+ }
+ drawerState.value =
+ when (drawerState.value) {
+ is RingerDrawerState.Initial -> {
+ RingerDrawerState.Open(ringerMode)
+ }
+ is RingerDrawerState.Open -> {
+ RingerDrawerState.Closed(ringerMode)
+ }
+ is RingerDrawerState.Closed -> {
+ RingerDrawerState.Open(ringerMode)
+ }
+ }
+ }
+
+ private fun provideTouchFeedback(ringerMode: RingerMode) {
+ when (ringerMode.value) {
+ RINGER_MODE_NORMAL -> {
+ interactor.scheduleTouchFeedback()
+ null
+ }
+ RINGER_MODE_SILENT -> VibrationEffect.get(VibrationEffect.EFFECT_CLICK)
+ RINGER_MODE_VIBRATE -> VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ else -> VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ }?.let { vibrator.vibrate(it, sonificiationVibrationAttributes) }
+ }
+
+ private fun VolumeDialogRingerModel.toViewModel(
+ drawerState: RingerDrawerState
+ ): RingerViewModel {
+ val currentIndex = availableModes.indexOf(currentRingerMode)
+ if (currentIndex == -1) {
+ volumeDialogLogger.onCurrentRingerModeIsUnsupported(currentRingerMode)
+ }
+ return RingerViewModel(
+ availableButtons = availableModes.map { mode -> toButtonViewModel(mode) },
+ currentButtonIndex = currentIndex,
+ drawerState = drawerState,
+ )
+ }
+
+ private fun VolumeDialogRingerModel.toButtonViewModel(
+ ringerMode: RingerMode
+ ): RingerButtonViewModel? {
+ return when (ringerMode.value) {
+ RINGER_MODE_SILENT ->
+ RingerButtonViewModel(
+ imageResId = R.drawable.ic_speaker_mute,
+ contentDescriptionResId = R.string.volume_ringer_status_silent,
+ hintLabelResId = R.string.volume_ringer_hint_unmute,
+ ringerMode = ringerMode,
+ )
+ RINGER_MODE_VIBRATE ->
+ RingerButtonViewModel(
+ imageResId = R.drawable.ic_volume_ringer_vibrate,
+ contentDescriptionResId = R.string.volume_ringer_status_vibrate,
+ hintLabelResId = R.string.volume_ringer_hint_vibrate,
+ ringerMode = ringerMode,
+ )
+ RINGER_MODE_NORMAL ->
+ when {
+ isMuted && isEnabled ->
+ RingerButtonViewModel(
+ imageResId = R.drawable.ic_speaker_mute,
+ contentDescriptionResId = R.string.volume_ringer_status_normal,
+ hintLabelResId = R.string.volume_ringer_hint_unmute,
+ ringerMode = ringerMode,
+ )
+
+ availableModes.contains(RingerMode(RINGER_MODE_VIBRATE)) ->
+ RingerButtonViewModel(
+ imageResId = R.drawable.ic_speaker_on,
+ contentDescriptionResId = R.string.volume_ringer_status_normal,
+ hintLabelResId = R.string.volume_ringer_hint_vibrate,
+ ringerMode = ringerMode,
+ )
+
+ else ->
+ RingerButtonViewModel(
+ imageResId = R.drawable.ic_speaker_on,
+ contentDescriptionResId = R.string.volume_ringer_status_normal,
+ hintLabelResId = R.string.volume_ringer_hint_mute,
+ ringerMode = ringerMode,
+ )
+ }
+ else -> null
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): VolumeDialogRingerDrawerViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt
index 59c38c0..9a3aa7e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.volume.dialog.shared
+import com.android.settingslib.volume.shared.model.RingerMode
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.VolumeLog
@@ -43,4 +44,13 @@
{ "Dismiss: ${Events.DISMISS_REASONS[int1]}" },
)
}
+
+ fun onCurrentRingerModeIsUnsupported(ringerMode: RingerMode) {
+ logBuffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { int1 = ringerMode.value },
+ { "Current ringer mode: $int1, ringer mode is unsupported in ringer drawer options" },
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 7889b3c..61eeab3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -65,7 +65,6 @@
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.events.ANIMATING_OUT
import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.FakeExecutor
@@ -176,7 +175,7 @@
BiometricStatusInteractorImpl(
activityTaskManager,
biometricStatusRepository,
- fingerprintRepository
+ fingerprintRepository,
)
iconProvider = IconProvider(context)
// Set up default logo icon
@@ -245,7 +244,7 @@
@Test
fun testIgnoresAnimatedInWhenDialogAnimatingOut() {
val container = initializeFingerprintContainer(addToView = false)
- container.mContainerState = ANIMATING_OUT
+ container.mContainerState = 4 // STATE_ANIMATING_OUT
container.addToView()
waitForIdleSync()
@@ -278,7 +277,7 @@
.onDismissed(
eq(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED),
eq<ByteArray?>(null), /* credentialAttestation */
- eq(authContainer?.requestId ?: 0L)
+ eq(authContainer?.requestId ?: 0L),
)
assertThat(container.parent).isNull()
}
@@ -292,13 +291,13 @@
verify(callback)
.onSystemEvent(
eq(BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL),
- eq(authContainer?.requestId ?: 0L)
+ eq(authContainer?.requestId ?: 0L),
)
verify(callback)
.onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq<ByteArray?>(null), /* credentialAttestation */
- eq(authContainer?.requestId ?: 0L)
+ eq(authContainer?.requestId ?: 0L),
)
assertThat(container.parent).isNull()
}
@@ -313,7 +312,7 @@
.onDismissed(
eq(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE),
eq<ByteArray?>(null), /* credentialAttestation */
- eq(authContainer?.requestId ?: 0L)
+ eq(authContainer?.requestId ?: 0L),
)
assertThat(container.parent).isNull()
}
@@ -340,7 +339,7 @@
.onDismissed(
eq(AuthDialogCallback.DISMISSED_ERROR),
eq<ByteArray?>(null), /* credentialAttestation */
- eq(authContainer?.requestId ?: 0L)
+ eq(authContainer?.requestId ?: 0L),
)
assertThat(authContainer!!.parent).isNull()
}
@@ -454,7 +453,7 @@
val container =
initializeFingerprintContainer(
authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL,
- verticalListContentView = PromptVerticalListContentView.Builder().build()
+ verticalListContentView = PromptVerticalListContentView.Builder().build(),
)
// Two-step credential view should show -
// 1. biometric prompt without sensor 2. credential view ui
@@ -479,7 +478,7 @@
val container =
initializeFingerprintContainer(
authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL,
- contentViewWithMoreOptionsButton = contentView
+ contentViewWithMoreOptionsButton = contentView,
)
waitForIdleSync()
@@ -565,7 +564,7 @@
}
private fun initializeCredentialPasswordContainer(
- addToView: Boolean = true,
+ addToView: Boolean = true
): TestAuthContainerView {
whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(20)
whenever(lockPatternUtils.getKeyguardStoredPasswordQuality(eq(20)))
@@ -597,25 +596,25 @@
fingerprintProps = fingerprintSensorPropertiesInternal(),
verticalListContentView = verticalListContentView,
),
- addToView
+ addToView,
)
private fun initializeCoexContainer(
authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK,
- addToView: Boolean = true
+ addToView: Boolean = true,
) =
initializeContainer(
TestAuthContainerView(
authenticators = authenticators,
fingerprintProps = fingerprintSensorPropertiesInternal(),
- faceProps = faceSensorPropertiesInternal()
+ faceProps = faceSensorPropertiesInternal(),
),
- addToView
+ addToView,
)
private fun initializeContainer(
view: TestAuthContainerView,
- addToView: Boolean
+ addToView: Boolean,
): TestAuthContainerView {
authContainer = view
@@ -668,7 +667,7 @@
biometricStatusInteractor,
udfpsUtils,
iconProvider,
- activityTaskManager
+ activityTaskManager,
),
{ credentialViewModel },
fakeExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
index 4e7de81..4cad5f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -29,21 +29,24 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.statusbar.BatteryStatusChip
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingIn
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingOut
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimationQueued
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.RunningChipAnim
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.ShowingPersistentDot
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
-import junit.framework.Assert.assertEquals
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -54,6 +57,10 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
@@ -120,12 +127,12 @@
val batteryChip = createAndScheduleFakeBatteryEvent()
// assert that animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// skip debounce delay
advanceTimeBy(DEBOUNCE_DELAY + 1)
// status chip starts animating in after debounce delay
- assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingIn, systemStatusAnimationScheduler.animationState.value)
assertEquals(0f, batteryChip.contentView.alpha)
assertEquals(0f, batteryChip.view.alpha)
verify(listener, times(1)).onSystemEventAnimationBegin()
@@ -134,14 +141,14 @@
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
advanceTimeBy(APPEAR_ANIMATION_DURATION)
// assert that status chip is visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, batteryChip.contentView.alpha)
assertEquals(1f, batteryChip.view.alpha)
// skip status chip display time
advanceTimeBy(DISPLAY_LENGTH + 1)
- // assert that it is still visible but switched to the ANIMATING_OUT state
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // assert that it is still visible but switched to the AnimatingOut state
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, batteryChip.contentView.alpha)
assertEquals(1f, batteryChip.view.alpha)
verify(listener, times(1)).onSystemEventAnimationFinish(false)
@@ -149,7 +156,7 @@
// skip disappear animation
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
// assert that it is not visible anymore
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
assertEquals(0f, batteryChip.contentView.alpha)
assertEquals(0f, batteryChip.view.alpha)
}
@@ -166,7 +173,7 @@
createAndScheduleFakePrivacyEvent()
// THEN the privacy event still happens
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
}
@Test
@@ -177,12 +184,12 @@
val privacyChip = createAndScheduleFakePrivacyEvent()
// assert that animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// skip debounce delay
advanceTimeBy(DEBOUNCE_DELAY + 1)
// status chip starts animating in after debounce delay
- assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingIn, systemStatusAnimationScheduler.animationState.value)
assertEquals(0f, privacyChip.view.alpha)
verify(listener, times(1)).onSystemEventAnimationBegin()
@@ -190,13 +197,13 @@
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
advanceTimeBy(APPEAR_ANIMATION_DURATION + 1)
// assert that status chip is visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
// skip status chip display time
advanceTimeBy(DISPLAY_LENGTH + 1)
- // assert that it is still visible but switched to the ANIMATING_OUT state
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // assert that it is still visible but switched to the AnimatingOut state
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
verify(listener, times(1)).onSystemEventAnimationFinish(true)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
@@ -205,13 +212,13 @@
advanceTimeBy(DISAPPEAR_ANIMATION_DURATION + 1)
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
// assert that it the dot is now visible
- assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(ShowingPersistentDot, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
// notify SystemStatusAnimationScheduler to remove persistent dot
systemStatusAnimationScheduler.removePersistentDot()
- // assert that IDLE state is entered
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ // assert that Idle state is entered
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onHidePersistentDot()
}
@@ -225,19 +232,19 @@
batteryChip.view.alpha = 0f
// assert that animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// create and schedule high priority event
val privacyChip = createAndScheduleFakePrivacyEvent()
// assert that animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// skip debounce delay and appear animation duration
- fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+ fastForwardAnimationToState(RunningChipAnim)
// high priority status chip is visible while low priority status chip is not visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
assertEquals(0f, batteryChip.view.alpha)
}
@@ -250,11 +257,11 @@
// create and schedule low priority event
val batteryChip = createAndScheduleFakeBatteryEvent()
- // fast forward to RUNNING_CHIP_ANIM state
- fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+ // fast forward to RunningChipAnim state
+ fastForwardAnimationToState(RunningChipAnim)
// assert that chip is displayed
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, batteryChip.view.alpha)
// create and schedule high priority event
@@ -264,20 +271,20 @@
testScheduler.runCurrent()
// assert that currently displayed chip is immediately animated out
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
// skip disappear animation
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
// assert that high priority privacy chip animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// skip debounce delay and appear animation
advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
// high priority status chip is visible while low priority status chip is not visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
assertEquals(0f, batteryChip.view.alpha)
}
@@ -294,7 +301,7 @@
advanceTimeBy(DEBOUNCE_DELAY + 1)
// assert that chip is animated in
- assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingIn, systemStatusAnimationScheduler.animationState.value)
// create and schedule high priority event
val privacyChip = createAndScheduleFakePrivacyEvent()
@@ -303,7 +310,7 @@
testScheduler.runCurrent()
// assert that currently animated chip keeps animating
- assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingIn, systemStatusAnimationScheduler.animationState.value)
// skip appear animation
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
@@ -311,20 +318,20 @@
// assert that low priority chip is animated out immediately after finishing the appear
// animation
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
// skip disappear animation
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
// assert that high priority privacy chip animation is queued
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// skip debounce delay and appear animation
advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
// high priority status chip is visible while low priority status chip is not visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
assertEquals(0f, batteryChip.view.alpha)
}
@@ -346,7 +353,7 @@
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
// high priority status chip is visible while low priority status chip is not visible
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
assertEquals(1f, privacyChip.view.alpha)
assertEquals(0f, batteryChip.view.alpha)
}
@@ -359,14 +366,14 @@
// create and schedule high priority event
createAndScheduleFakePrivacyEvent()
- // skip chip animation lifecycle and fast forward to SHOWING_PERSISTENT_DOT state
- fastForwardAnimationToState(SHOWING_PERSISTENT_DOT)
- assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ // skip chip animation lifecycle and fast forward to ShowingPersistentDot state
+ fastForwardAnimationToState(ShowingPersistentDot)
+ assertEquals(ShowingPersistentDot, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
- // remove persistent dot and verify that animationState changes to IDLE
+ // remove persistent dot and verify that animationState changes to Idle
systemStatusAnimationScheduler.removePersistentDot()
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onHidePersistentDot()
}
@@ -377,14 +384,14 @@
val accessibilityDesc = "Some desc"
val mockView = mock<View>()
val mockAnimatableView =
- mock<BackgroundAnimatableView> { whenever(view).thenReturn(mockView) }
+ mock<BackgroundAnimatableView> { whenever(it.view).thenReturn(mockView) }
scheduleFakeEventWithView(
accessibilityDesc,
mockAnimatableView,
shouldAnnounceAccessibilityEvent = true,
)
- fastForwardAnimationToState(ANIMATING_OUT)
+ fastForwardAnimationToState(AnimatingOut)
verify(mockView).announceForAccessibility(eq(accessibilityDesc))
}
@@ -396,14 +403,14 @@
val accessibilityDesc = null
val mockView = mock<View>()
val mockAnimatableView =
- mock<BackgroundAnimatableView> { whenever(view).thenReturn(mockView) }
+ mock<BackgroundAnimatableView> { whenever(it.view).thenReturn(mockView) }
scheduleFakeEventWithView(
accessibilityDesc,
mockAnimatableView,
shouldAnnounceAccessibilityEvent = true,
)
- fastForwardAnimationToState(ANIMATING_OUT)
+ fastForwardAnimationToState(AnimatingOut)
verify(mockView, never()).announceForAccessibility(any())
}
@@ -415,14 +422,14 @@
val accessibilityDesc = "something"
val mockView = mock<View>()
val mockAnimatableView =
- mock<BackgroundAnimatableView> { whenever(view).thenReturn(mockView) }
+ mock<BackgroundAnimatableView> { whenever(it.view).thenReturn(mockView) }
scheduleFakeEventWithView(
accessibilityDesc,
mockAnimatableView,
shouldAnnounceAccessibilityEvent = false,
)
- fastForwardAnimationToState(ANIMATING_OUT)
+ fastForwardAnimationToState(AnimatingOut)
verify(mockView, never()).announceForAccessibility(any())
}
@@ -435,21 +442,21 @@
// create and schedule high priority event
createAndScheduleFakePrivacyEvent()
- // skip chip animation lifecycle and fast forward to RUNNING_CHIP_ANIM state
- fastForwardAnimationToState(RUNNING_CHIP_ANIM)
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ // skip chip animation lifecycle and fast forward to RunningChipAnim state
+ fastForwardAnimationToState(RunningChipAnim)
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
// request removal of persistent dot
systemStatusAnimationScheduler.removePersistentDot()
// skip display time and verify that disappear animation is run
advanceTimeBy(DISPLAY_LENGTH + 1)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
- // skip disappear animation and verify that animationState changes to IDLE instead of
- // SHOWING_PERSISTENT_DOT
+ // skip disappear animation and verify that animationState changes to Idle instead of
+ // ShowingPersistentDot
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
// verify that the persistent dot callbacks are not invoked
verify(listener, never()).onSystemStatusAnimationTransitionToPersistentDot(any())
verify(listener, never()).onHidePersistentDot()
@@ -463,9 +470,9 @@
// create and schedule high priority event
createAndScheduleFakePrivacyEvent()
- // fast forward to ANIMATING_OUT state
- fastForwardAnimationToState(ANIMATING_OUT)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // fast forward to AnimatingOut state
+ fastForwardAnimationToState(AnimatingOut)
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
// remove persistent dot
@@ -478,8 +485,8 @@
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
testScheduler.runCurrent()
- // verify that animationState changes to IDLE
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ // verify that animationState changes to Idle
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
}
@Test
@@ -494,11 +501,11 @@
// create and schedule a privacy event again (resets forceVisible to true)
createAndScheduleFakePrivacyEvent()
- // skip chip animation lifecycle and fast forward to SHOWING_PERSISTENT_DOT state
- fastForwardAnimationToState(SHOWING_PERSISTENT_DOT)
+ // skip chip animation lifecycle and fast forward to ShowingPersistentDot state
+ fastForwardAnimationToState(ShowingPersistentDot)
- // verify that we reach SHOWING_PERSISTENT_DOT and that listener callback is invoked
- assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ // verify that we reach ShowingPersistentDot and that listener callback is invoked
+ assertEquals(ShowingPersistentDot, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
}
@@ -511,21 +518,21 @@
createAndScheduleFakePrivacyEvent()
// request removal of persistent dot (sets forceVisible to false)
systemStatusAnimationScheduler.removePersistentDot()
- fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+ fastForwardAnimationToState(RunningChipAnim)
// create and schedule a privacy event again (resets forceVisible to true)
createAndScheduleFakePrivacyEvent()
// skip status chip display time
advanceTimeBy(DISPLAY_LENGTH + 1)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemEventAnimationFinish(anyBoolean())
// skip disappear animation
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
- // verify that we reach SHOWING_PERSISTENT_DOT and that listener callback is invoked
- assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ // verify that we reach ShowingPersistentDot and that listener callback is invoked
+ assertEquals(ShowingPersistentDot, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
}
@@ -537,9 +544,9 @@
// create and schedule high priority event
createAndScheduleFakePrivacyEvent()
- // skip chip animation lifecycle and fast forward to ANIMATING_OUT state
- fastForwardAnimationToState(ANIMATING_OUT)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // skip chip animation lifecycle and fast forward to AnimatingOut state
+ fastForwardAnimationToState(AnimatingOut)
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
// request removal of persistent dot
@@ -548,13 +555,13 @@
// schedule another high priority event while the event is animating out
createAndScheduleFakePrivacyEvent()
- // verify that the state is still ANIMATING_OUT
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // verify that the state is still AnimatingOut
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
- // skip disappear animation duration and verify that new state is ANIMATION_QUEUED
+ // skip disappear animation duration and verify that new state is AnimationQueued
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
testScheduler.runCurrent()
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
// also verify that onHidePersistentDot callback is called
verify(listener, times(1)).onHidePersistentDot()
}
@@ -567,16 +574,16 @@
// create and schedule high priority event
createAndScheduleFakePrivacyEvent()
- // skip chip animation lifecycle and fast forward to ANIMATING_OUT state
- fastForwardAnimationToState(ANIMATING_OUT)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // skip chip animation lifecycle and fast forward to AnimatingOut state
+ fastForwardAnimationToState(AnimatingOut)
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
// request removal of persistent dot
systemStatusAnimationScheduler.removePersistentDot()
- // verify that the state is still ANIMATING_OUT
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ // verify that the state is still AnimatingOut
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
// skip disappear animation duration
testScheduler.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION + 1)
@@ -591,33 +598,33 @@
// verify that onHidePersistentDot is invoked despite the animator callback being delayed
// (it's invoked more than DISAPPEAR_ANIMATION_DURATION after the dot removal was requested)
verify(listener, times(1)).onHidePersistentDot()
- // verify that animationState is IDLE
- assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ // verify that animationState is Idle
+ assertEquals(Idle, systemStatusAnimationScheduler.animationState.value)
}
- private fun TestScope.fastForwardAnimationToState(@SystemAnimationState animationState: Int) {
+ private fun TestScope.fastForwardAnimationToState(animationState: SystemEventAnimationState) {
// this function should only be called directly after posting a status event
- assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
- if (animationState == IDLE || animationState == ANIMATION_QUEUED) return
+ assertEquals(AnimationQueued, systemStatusAnimationScheduler.animationState.value)
+ if (animationState == Idle || animationState == AnimationQueued) return
// skip debounce delay
advanceTimeBy(DEBOUNCE_DELAY + 1)
// status chip starts animating in after debounce delay
- assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingIn, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemEventAnimationBegin()
- if (animationState == ANIMATING_IN) return
+ if (animationState == AnimatingIn) return
// skip appear animation
animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
advanceTimeBy(APPEAR_ANIMATION_DURATION)
- assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
- if (animationState == RUNNING_CHIP_ANIM) return
+ assertEquals(RunningChipAnim, systemStatusAnimationScheduler.animationState.value)
+ if (animationState == RunningChipAnim) return
// skip status chip display time
advanceTimeBy(DISPLAY_LENGTH + 1)
- assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(AnimatingOut, systemStatusAnimationScheduler.animationState.value)
verify(listener, times(1)).onSystemEventAnimationFinish(anyBoolean())
- if (animationState == ANIMATING_OUT) return
+ if (animationState == AnimatingOut) return
// skip disappear animation
animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 9593dfb..8c4ec4c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -28,8 +28,6 @@
import com.android.systemui.power.domain.interactor.PowerInteractorFactory
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor.ConfigurationBasedDimensions
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.CoroutineScope
@@ -56,7 +54,6 @@
fromGoneTransitionInteractor: FromGoneTransitionInteractor = mock(),
fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor = mock(),
fromOccludedTransitionInteractor: FromOccludedTransitionInteractor = mock(),
- sharedNotificationContainerInteractor: SharedNotificationContainerInteractor? = null,
powerInteractor: PowerInteractor = PowerInteractorFactory.create().powerInteractor,
testScope: CoroutineScope = TestScope(),
): WithDependencies {
@@ -69,23 +66,6 @@
whenever(it.transitionState).thenReturn(transitionStateFlow)
whenever(it.isFinishedIn(any(), any())).thenReturn(MutableStateFlow(false))
}
- val configurationDimensionFlow = MutableSharedFlow<ConfigurationBasedDimensions>()
- configurationDimensionFlow.tryEmit(
- ConfigurationBasedDimensions(
- useSplitShade = false,
- useLargeScreenHeader = false,
- marginHorizontal = 0,
- marginBottom = 0,
- marginTop = 0,
- marginTopLargeScreen = 0,
- keyguardSplitShadeTopMargin = 0,
- )
- )
- val sncInteractor =
- sharedNotificationContainerInteractor
- ?: mock<SharedNotificationContainerInteractor>().also {
- whenever(it.configurationBasedDimensions).thenReturn(configurationDimensionFlow)
- }
return WithDependencies(
repository = repository,
featureFlags = featureFlags,
@@ -104,7 +84,6 @@
fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
fromOccludedTransitionInteractor = { fromOccludedTransitionInteractor },
- sharedNotificationContainerInteractor = { sncInteractor },
applicationScope = testScope,
),
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
index e85114d..da261bf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
@@ -24,7 +24,6 @@
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
val Kosmos.keyguardInteractor: KeyguardInteractor by
Kosmos.Fixture {
@@ -39,7 +38,6 @@
fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
fromOccludedTransitionInteractor = { fromOccludedTransitionInteractor },
- sharedNotificationContainerInteractor = { sharedNotificationContainerInteractor },
applicationScope = testScope.backgroundScope,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
index 60141c6..6944e6c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -187,6 +187,7 @@
context
.getOrCreateTestableResources()
.addOverride(R.bool.config_use_split_notification_shade, splitShade)
+ shadeRepository.setShadeLayoutWide(splitShade)
testScope.runCurrent()
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
index 92075ea..39f58ae 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
@@ -26,7 +26,6 @@
import com.android.systemui.shade.ShadeModule
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.disableflags.data.repository.disableFlagsRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.dozeParameters
import com.android.systemui.statusbar.policy.data.repository.userSetupRepository
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
@@ -52,7 +51,6 @@
ShadeInteractorLegacyImpl(
scope = applicationCoroutineScope,
keyguardRepository = keyguardRepository,
- sharedNotificationContainerInteractor = sharedNotificationContainerInteractor,
repository = shadeRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
index 3234e66..83fc3e9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
@@ -14,26 +14,29 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.statusbar.notification.stack.domain.interactor
import android.content.applicationContext
-import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.largeScreenHeaderHelper
import com.android.systemui.statusbar.policy.splitShadeStateController
+import kotlinx.coroutines.ExperimentalCoroutinesApi
val Kosmos.sharedNotificationContainerInteractor by
Kosmos.Fixture {
SharedNotificationContainerInteractor(
- configurationRepository = configurationRepository,
context = applicationContext,
splitShadeStateController = { splitShadeStateController },
shadeInteractor = { shadeInteractor },
+ configurationInteractor = configurationInteractor,
keyguardInteractor = keyguardInteractor,
deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
- largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
new file mode 100644
index 0000000..db1c01a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.volume.dialog.ringer.ui.viewmodel
+
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.volume.dialog.ringer.domain.volumeDialogRingerInteractor
+import com.android.systemui.volume.dialog.shared.volumeDialogLogger
+
+val Kosmos.volumeDialogRingerDrawerViewModel by
+ Kosmos.Fixture {
+ VolumeDialogRingerDrawerViewModel(
+ backgroundDispatcher = testDispatcher,
+ coroutineScope = applicationCoroutineScope,
+ interactor = volumeDialogRingerInteractor,
+ vibrator = vibratorHelper,
+ volumeDialogLogger = volumeDialogLogger,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/shared/VolumeDialogLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/shared/VolumeDialogLoggerKosmos.kt
new file mode 100644
index 0000000..f9d4a99
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/shared/VolumeDialogLoggerKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.volume.dialog.shared
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
+
+val Kosmos.volumeDialogLogger by Kosmos.Fixture { VolumeDialogLogger(logcatLogBuffer()) }
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 2f4e8bb..7afcb13 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -176,6 +176,7 @@
"core_libraries",
"crumpet",
"dck_framework",
+ "desktop_stats",
"devoptions_settings",
"game",
"gpu",
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 7740411..448c42b7 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -82,7 +82,8 @@
@IntDef(prefix = { "AUTO_BRIGHTNESS_MODE_" }, value = {
AUTO_BRIGHTNESS_MODE_DEFAULT,
AUTO_BRIGHTNESS_MODE_IDLE,
- AUTO_BRIGHTNESS_MODE_DOZE
+ AUTO_BRIGHTNESS_MODE_DOZE,
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR
})
@Retention(RetentionPolicy.SOURCE)
public @interface AutomaticBrightnessMode{}
@@ -90,6 +91,7 @@
public static final int AUTO_BRIGHTNESS_MODE_DEFAULT = 0;
public static final int AUTO_BRIGHTNESS_MODE_IDLE = 1;
public static final int AUTO_BRIGHTNESS_MODE_DOZE = 2;
+ public static final int AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR = 3;
public static final int AUTO_BRIGHTNESS_MODE_MAX = AUTO_BRIGHTNESS_MODE_DOZE;
// How long the current sensor reading is assumed to be valid beyond the current time.
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 6a019f3..570d5d0 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -18,6 +18,7 @@
import static android.text.TextUtils.formatSimple;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
@@ -114,7 +115,7 @@
luxLevels = getLuxLevels(context.getResources().getIntArray(
com.android.internal.R.array.config_autoBrightnessLevelsIdle));
}
- case AUTO_BRIGHTNESS_MODE_DOZE -> {
+ case AUTO_BRIGHTNESS_MODE_DOZE, AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR -> {
luxLevels = displayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(mode, preset);
brightnessLevels =
displayDeviceConfig.getAutoBrightnessBrighteningLevels(mode, preset);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5b61f00..5c8430b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -19,6 +19,7 @@
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
@@ -1086,6 +1087,16 @@
brightnessMappers.put(AUTO_BRIGHTNESS_MODE_DOZE, dozeModeBrightnessMapper);
}
+ if (mFlags.areAutoBrightnessModesEnabled()
+ && mFlags.isAutoBrightnessModeBedtimeWearEnabled()) {
+ BrightnessMappingStrategy bedtimeBrightnessMapper =
+ BrightnessMappingStrategy.create(context, mDisplayDeviceConfig,
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR, mDisplayWhiteBalanceController);
+ if (bedtimeBrightnessMapper != null) {
+ brightnessMappers.put(AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR, bedtimeBrightnessMapper);
+ }
+ }
+
float userLux = BrightnessMappingStrategy.INVALID_LUX;
float userNits = BrightnessMappingStrategy.INVALID_NITS;
if (mAutomaticBrightnessController != null) {
diff --git a/services/core/java/com/android/server/display/config/DisplayBrightnessMappingConfig.java b/services/core/java/com/android/server/display/config/DisplayBrightnessMappingConfig.java
index e0bdda5..458438c 100644
--- a/services/core/java/com/android/server/display/config/DisplayBrightnessMappingConfig.java
+++ b/services/core/java/com/android/server/display/config/DisplayBrightnessMappingConfig.java
@@ -16,6 +16,7 @@
package com.android.server.display.config;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
@@ -247,6 +248,9 @@
case AUTO_BRIGHTNESS_MODE_DOZE -> {
return AutoBrightnessModeName.doze.getRawName();
}
+ case AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR -> {
+ return AutoBrightnessModeName.bedtime_wear.getRawName();
+ }
default -> throw new IllegalArgumentException("Unknown auto-brightness mode: " + mode);
}
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 509fa3e..bb4ae96 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -74,7 +74,6 @@
private final Context mContext;
private final Handler mHandler;
private final PackageManagerInternal mPackageManagerInternal;
- private final IntegrityFileManager mIntegrityFileManager;
/** Create an instance of {@link AppIntegrityManagerServiceImpl}. */
public static AppIntegrityManagerServiceImpl create(Context context) {
@@ -84,7 +83,6 @@
return new AppIntegrityManagerServiceImpl(
context,
LocalServices.getService(PackageManagerInternal.class),
- IntegrityFileManager.getInstance(),
handlerThread.getThreadHandler());
}
@@ -92,11 +90,9 @@
AppIntegrityManagerServiceImpl(
Context context,
PackageManagerInternal packageManagerInternal,
- IntegrityFileManager integrityFileManager,
Handler handler) {
mContext = context;
mPackageManagerInternal = packageManagerInternal;
- mIntegrityFileManager = integrityFileManager;
mHandler = handler;
IntentFilter integrityVerificationFilter = new IntentFilter();
@@ -144,39 +140,23 @@
@Override
@BinderThread
public String getCurrentRuleSetVersion() {
- getCallerPackageNameOrThrow(Binder.getCallingUid());
-
- RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
- return (ruleMetadata != null && ruleMetadata.getVersion() != null)
- ? ruleMetadata.getVersion()
- : "";
+ return "";
}
@Override
@BinderThread
public String getCurrentRuleSetProvider() {
- getCallerPackageNameOrThrow(Binder.getCallingUid());
-
- RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
- return (ruleMetadata != null && ruleMetadata.getRuleProvider() != null)
- ? ruleMetadata.getRuleProvider()
- : "";
+ return "";
}
@Override
public ParceledListSlice<Rule> getCurrentRules() {
- List<Rule> rules = Collections.emptyList();
- try {
- rules = mIntegrityFileManager.readRules(/* appInstallMetadata= */ null);
- } catch (Exception e) {
- Slog.e(TAG, "Error getting current rules", e);
- }
- return new ParceledListSlice<>(rules);
+ return new ParceledListSlice<>(Collections.emptyList());
}
@Override
public List<String> getWhitelistedRuleProviders() {
- return getAllowedRuleProviderSystemApps();
+ return Collections.emptyList();
}
private void handleIntegrityVerification(Intent intent) {
@@ -184,75 +164,4 @@
mPackageManagerInternal.setIntegrityVerificationResult(
verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
}
-
- private String getCallerPackageNameOrThrow(int callingUid) {
- String callerPackageName = getCallingRulePusherPackageName(callingUid);
- if (callerPackageName == null) {
- throw new SecurityException(
- "Only system packages specified in config_integrityRuleProviderPackages are "
- + "allowed to call this method.");
- }
- return callerPackageName;
- }
-
- private String getCallingRulePusherPackageName(int callingUid) {
- // Obtain the system apps that are allowlisted in config_integrityRuleProviderPackages.
- List<String> allowedRuleProviders = getAllowedRuleProviderSystemApps();
- if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(
- TAG,
- String.format(
- "Rule provider system app list contains: %s", allowedRuleProviders));
- }
-
- // Identify the package names in the caller list.
- List<String> callingPackageNames = getPackageListForUid(callingUid);
-
- // Find the intersection between the allowed and calling packages. Ideally, we will have
- // at most one package name here. But if we have more, it is fine.
- List<String> allowedCallingPackages = new ArrayList<>();
- for (String packageName : callingPackageNames) {
- if (allowedRuleProviders.contains(packageName)) {
- allowedCallingPackages.add(packageName);
- }
- }
-
- return allowedCallingPackages.isEmpty() ? null : allowedCallingPackages.get(0);
- }
-
- private List<String> getAllowedRuleProviderSystemApps() {
- List<String> integrityRuleProviders =
- Arrays.asList(
- mContext.getResources()
- .getStringArray(R.array.config_integrityRuleProviderPackages));
-
- // Filter out the rule provider packages that are not system apps.
- List<String> systemAppRuleProviders = new ArrayList<>();
- for (String ruleProvider : integrityRuleProviders) {
- if (isSystemApp(ruleProvider)) {
- systemAppRuleProviders.add(ruleProvider);
- }
- }
- return systemAppRuleProviders;
- }
-
- private boolean isSystemApp(String packageName) {
- try {
- PackageInfo existingPackageInfo =
- mContext.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
- return existingPackageInfo.applicationInfo != null
- && existingPackageInfo.applicationInfo.isSystemApp();
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- }
-
- private List<String> getPackageListForUid(int uid) {
- try {
- return Arrays.asList(mContext.getPackageManager().getPackagesForUid(uid));
- } catch (NullPointerException e) {
- Slog.w(TAG, String.format("No packages were found for uid: %d", uid));
- return List.of();
- }
- }
}
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 20c69ac..6eac826 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -955,6 +955,7 @@
<xs:enumeration value="default"/>
<xs:enumeration value="idle"/>
<xs:enumeration value="doze"/>
+ <xs:enumeration value="bedtime_wear"/>
</xs:restriction>
</xs:simpleType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index a8f18b3..a29e42c 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -21,6 +21,7 @@
public enum AutoBrightnessModeName {
method public String getRawName();
enum_constant public static final com.android.server.display.config.AutoBrightnessModeName _default;
+ enum_constant public static final com.android.server.display.config.AutoBrightnessModeName bedtime_wear;
enum_constant public static final com.android.server.display.config.AutoBrightnessModeName doze;
enum_constant public static final com.android.server.display.config.AutoBrightnessModeName idle;
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index 2c78504..2bc8af1 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -159,15 +159,16 @@
// Press home key to hide soft keyboard.
Log.i(TAG, "Press home");
- verifyInputViewStatus(
- () -> assertThat(mUiDevice.pressHome()).isTrue(),
- true /* expected */,
- false /* inputViewStarted */);
if (Flags.refactorInsetsController()) {
+ assertThat(mUiDevice.pressHome()).isTrue();
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
} else {
+ verifyInputViewStatus(
+ () -> assertThat(mUiDevice.pressHome()).isTrue(),
+ true /* expected */,
+ false /* inputViewStarted */);
assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
}
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 2220f43..2fd135e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -18,6 +18,7 @@
import static com.android.internal.display.BrightnessSynchronizer.brightnessIntToFloat;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.config.SensorData.TEMPERATURE_TYPE_SKIN;
@@ -885,6 +886,34 @@
mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(
AUTO_BRIGHTNESS_MODE_DOZE,
Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM), SMALL_DELTA);
+
+ // Wear Bedtime mode curve
+ assertArrayEquals(new float[]{0.0f, 10.0f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM), ZERO_DELTA);
+ assertArrayEquals(new float[]{0.20f, 0.30f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM), SMALL_DELTA);
+
+ assertArrayEquals(new float[]{0.0f, 20.0f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL), ZERO_DELTA);
+ assertArrayEquals(new float[]{0.30f, 0.65f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL), SMALL_DELTA);
+
+ assertArrayEquals(new float[]{0.0f, 30.0f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT), ZERO_DELTA);
+ assertArrayEquals(new float[]{0.65f, 0.95f},
+ mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(
+ AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+ Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT), SMALL_DELTA);
}
@Test
@@ -1296,6 +1325,51 @@
+ "</screenBrightnessRampSlowIncreaseIdle>\n";
}
+ private String getBedTimeModeWearCurveConfig() {
+ return "<luxToBrightnessMapping>\n"
+ + "<mode>bedtime_wear</mode>\n"
+ + "<setting>dim</setting>\n"
+ + "<map>\n"
+ + "<point>\n"
+ + "<first>0</first>\n"
+ + "<second>0.2</second>\n"
+ + "</point>\n"
+ + "<point>\n"
+ + "<first>10</first>\n"
+ + "<second>0.3</second>\n"
+ + "</point>\n"
+ + "</map>\n"
+ + "</luxToBrightnessMapping>\n"
+ + "<luxToBrightnessMapping>\n"
+ + "<mode>bedtime_wear</mode>\n"
+ + "<setting>normal</setting>\n"
+ + "<map>\n"
+ + "<point>\n"
+ + "<first>0</first>\n"
+ + "<second>0.3</second>\n"
+ + "</point>\n"
+ + "<point>\n"
+ + "<first>20</first>\n"
+ + "<second>0.65</second>\n"
+ + "</point>\n"
+ + "</map>\n"
+ + "</luxToBrightnessMapping>\n"
+ + "<luxToBrightnessMapping>\n"
+ + "<mode>bedtime_wear</mode>\n"
+ + "<setting>bright</setting>\n"
+ + "<map>\n"
+ + "<point>\n"
+ + "<first>0</first>\n"
+ + "<second>0.65</second>\n"
+ + "</point>\n"
+ + "<point>\n"
+ + "<first>30</first>\n"
+ + "<second>0.95</second>\n"
+ + "</point>\n"
+ + "</map>\n"
+ + "</luxToBrightnessMapping>\n";
+ }
+
private String getPowerThrottlingConfig() {
return "<powerThrottlingConfig >\n"
+ "<brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed>\n"
@@ -1481,6 +1555,7 @@
+ "</point>\n"
+ "</map>\n"
+ "</luxToBrightnessMapping>\n"
+ + getBedTimeModeWearCurveConfig()
+ "<idleStylusTimeoutMillis>1000</idleStylusTimeoutMillis>\n"
+ "</autoBrightness>\n"
+ getPowerThrottlingConfig()
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index a2e6d4c..93aa10b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -135,7 +135,6 @@
@Mock PlatformCompat mPlatformCompat;
@Mock Context mMockContext;
@Mock Resources mMockResources;
- @Mock IntegrityFileManager mIntegrityFileManager;
@Mock Handler mHandler;
private final Context mRealContext = InstrumentationRegistry.getTargetContext();
@@ -169,7 +168,6 @@
new AppIntegrityManagerServiceImpl(
mMockContext,
mPackageManagerInternal,
- mIntegrityFileManager,
mHandler);
mSpyPackageManager = spy(mRealContext.getPackageManager());
@@ -177,7 +175,6 @@
when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
- when(mIntegrityFileManager.initialized()).thenReturn(true);
// These are needed to override the Settings.Global.get result.
when(mMockContext.getContentResolver()).thenReturn(mRealContext.getContentResolver());
setIntegrityCheckIncludesRuleProvider(true);
@@ -224,71 +221,6 @@
1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
}
- @Test
- public void handleBroadcast_notInitialized() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- when(mIntegrityFileManager.initialized()).thenReturn(false);
- ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext)
- .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
- Intent intent = makeVerificationIntent();
-
- broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
- runJobInHandler();
-
- // The evaluation will still run since we still evaluate manifest based rules.
- verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(
- 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- }
-
- @Test
- public void verifierAsInstaller_skipIntegrityVerification() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- setIntegrityCheckIncludesRuleProvider(false);
- ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext, atLeastOnce())
- .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
- Intent intent = makeVerificationIntent(TEST_FRAMEWORK_PACKAGE);
-
- broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
- runJobInHandler();
-
- verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(
- 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- }
-
- @Test
- public void getCurrentRules() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- Rule rule = new Rule(IntegrityFormula.Application.packageNameEquals("package"), Rule.DENY);
- when(mIntegrityFileManager.readRules(any())).thenReturn(Arrays.asList(rule));
-
- assertThat(mService.getCurrentRules().getList()).containsExactly(rule);
- }
-
- @Test
- public void getWhitelistedRuleProviders_returnsEmptyForNonSystemApps() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp(false);
-
- assertThat(mService.getWhitelistedRuleProviders()).isEmpty();
- }
-
- @Test
- public void getWhitelistedRuleProviders() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
-
- assertThat(mService.getWhitelistedRuleProviders()).containsExactly(TEST_FRAMEWORK_PACKAGE);
- }
-
private void allowlistUsAsRuleProvider() {
Resources mockResources = mock(Resources.class);
when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 79b3a7c..94be3d4 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -127,7 +127,9 @@
/**
* Exception from the satellite service containing the {@link SatelliteResult} error code.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static class SatelliteException extends Exception {
@SatelliteResult private final int mErrorCode;
@@ -257,140 +259,210 @@
/**
* The request was successfully processed.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_SUCCESS = 0;
+
/**
* A generic error which should be used only when other specific errors cannot be used.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_ERROR = 1;
+
/**
* Error received from the satellite server.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_SERVER_ERROR = 2;
+
/**
* Error received from the vendor service. This generic error code should be used
* only when the error cannot be mapped to other specific service error codes.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_SERVICE_ERROR = 3;
+
/**
* Error received from satellite modem. This generic error code should be used only when
* the error cannot be mapped to other specific modem error codes.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_MODEM_ERROR = 4;
+
/**
* Error received from the satellite network. This generic error code should be used only when
* the error cannot be mapped to other specific network error codes.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NETWORK_ERROR = 5;
+
/**
* Telephony is not in a valid state to receive requests from clients.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6;
+
/**
* Satellite modem is not in a valid state to receive requests from clients.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7;
+
/**
* Either vendor service, or modem, or Telephony framework has received a request with
* invalid arguments from its clients.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8;
+
/**
* Telephony framework failed to send a request or receive a response from the vendor service
* or satellite modem due to internal error.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_REQUEST_FAILED = 9;
+
/**
* Radio did not start or is resetting.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 10;
+
/**
* The request is not supported by either the satellite modem or the network.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 11;
+
/**
* Satellite modem or network has no resources available to handle requests from clients.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NO_RESOURCES = 12;
+
/**
* Satellite service is not provisioned yet.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 13;
+
/**
* Satellite service provision is already in progress.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 14;
+
/**
* The ongoing request was aborted by either the satellite modem or the network.
* This error is also returned when framework decides to abort current send request as one
* of the previous send request failed.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_REQUEST_ABORTED = 15;
+
/**
* The device/subscriber is barred from accessing the satellite service.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_ACCESS_BARRED = 16;
+
/**
* Satellite modem timeout to receive ACK or response from the satellite network after
* sending a request to the network.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NETWORK_TIMEOUT = 17;
+
/**
* Satellite network is not reachable from the modem.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NOT_REACHABLE = 18;
+
/**
* The device/subscriber is not authorized to register with the satellite service provider.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NOT_AUTHORIZED = 19;
+
/**
* The device does not support satellite.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_NOT_SUPPORTED = 20;
/**
* The current request is already in-progress.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21;
/**
* Satellite modem is currently busy due to which current request cannot be processed.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_MODEM_BUSY = 22;
/**
* Telephony process is not currently available or satellite is not supported.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_ILLEGAL_STATE = 23;
/**
* Telephony framework timeout to receive ACK or response from the satellite modem after
* sending a request to the modem.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_MODEM_TIMEOUT = 24;
@@ -475,27 +547,41 @@
/**
* Unknown Non-Terrestrial radio technology. This generic radio technology should be used
* only when the radio technology cannot be mapped to other specific radio technologies.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0;
+
/**
* 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1;
+
/**
* 3GPP 5G NR over Non-Terrestrial-Networks technology.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2;
+
/**
* 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3;
+
/**
* Proprietary technology.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4;
@@ -510,16 +596,35 @@
@Retention(RetentionPolicy.SOURCE)
public @interface NTRadioTechnology {}
- /** Suggested device hold position is unknown. */
+ /**
+ * Suggested device hold position is unknown.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DEVICE_HOLD_POSITION_UNKNOWN = 0;
- /** User is suggested to hold the device in portrait mode. */
+
+ /**
+ * User is suggested to hold the device in portrait mode.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DEVICE_HOLD_POSITION_PORTRAIT = 1;
- /** User is suggested to hold the device in landscape mode with left hand. */
+
+ /**
+ * User is suggested to hold the device in landscape mode with left hand.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DEVICE_HOLD_POSITION_LANDSCAPE_LEFT = 2;
- /** User is suggested to hold the device in landscape mode with right hand. */
+
+ /**
+ * User is suggested to hold the device in landscape mode with right hand.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT = 3;
@@ -533,18 +638,37 @@
@Retention(RetentionPolicy.SOURCE)
public @interface DeviceHoldPosition {}
- /** Display mode is unknown. */
+ /**
+ * Display mode is unknown.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DISPLAY_MODE_UNKNOWN = 0;
- /** Display mode of the device used for satellite communication for non-foldable phones. */
+
+ /**
+ * Display mode of the device used for satellite communication for non-foldable phones.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DISPLAY_MODE_FIXED = 1;
- /** Display mode of the device used for satellite communication for foldabale phones when the
- * device is opened. */
+
+ /**
+ * Display mode of the device used for satellite communication for foldabale phones when the
+ * device is opened.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DISPLAY_MODE_OPENED = 2;
- /** Display mode of the device used for satellite communication for foldabable phones when the
- * device is closed. */
+
+ /**
+ * Display mode of the device used for satellite communication for foldabable phones when the
+ * device is closed.
+ * @hide
+ */
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DISPLAY_MODE_CLOSED = 3;
@@ -561,13 +685,18 @@
/**
* The emergency call is handed over to oem-enabled satellite SOS messaging. SOS messages are
* sent to SOS providers, which will then forward the messages to emergency providers.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1;
+
/**
* The emergency call is handed over to carrier-enabled satellite T911 messaging. T911 messages
* are sent directly to local emergency providers.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2;
@@ -614,7 +743,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestEnabled(@NonNull EnableRequestAttributes attributes,
@@ -660,7 +792,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsEnabled(@NonNull @CallbackExecutor Executor executor,
@@ -717,7 +852,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsDemoModeEnabled(@NonNull @CallbackExecutor Executor executor,
@@ -774,7 +912,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsEmergencyModeEnabled(@NonNull @CallbackExecutor Executor executor,
@@ -832,7 +973,10 @@
* service is supported on the device and {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
+ *
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsSupported(@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
@@ -887,7 +1031,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestCapabilities(@NonNull @CallbackExecutor Executor executor,
@@ -936,56 +1083,80 @@
/**
* The default state indicating that datagram transfer is idle.
* This should be sent if there are no message transfer activity happening.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0;
+
/**
* A transition state indicating that a datagram is being sent.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING = 1;
+
/**
* An end state indicating that datagram sending completed successfully.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
* will be sent if no more messages are pending.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2;
+
/**
* An end state indicating that datagram sending completed with a failure.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
* must be sent before reporting any additional datagram transfer state changes. All pending
* messages will be reported as failed, to the corresponding applications.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3;
+
/**
* A transition state indicating that a datagram is being received.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 4;
+
/**
* An end state indicating that datagram receiving completed successfully.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
* will be sent if no more messages are pending.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS = 5;
+
/**
* An end state indicating that datagram receive operation found that there are no
* messages to be retrieved from the satellite.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
* will be sent if no more messages are pending.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6;
+
/**
* An end state indicating that datagram receive completed with a failure.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
* will be sent if no more messages are pending.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7;
+
/**
* A transition state indicating that Telephony is waiting for satellite modem to connect to a
* satellite network before sending a datagram or polling for datagrams. If the satellite modem
@@ -994,14 +1165,19 @@
* {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING} will be sent. Otherwise,
* either {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED} or
* {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED} will be sent.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT = 8;
+
/**
* The datagram transfer state is unknown. This generic datagram transfer state should be used
* only when the datagram transfer state cannot be mapped to other specific datagram transfer
* states.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1;
@@ -1024,58 +1200,86 @@
/**
* Satellite modem is in idle state.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_IDLE = 0;
+
/**
* Satellite modem is listening for incoming datagrams.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_LISTENING = 1;
+
/**
* Satellite modem is sending and/or receiving datagrams.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2;
+
/**
* Satellite modem is retrying to send and/or receive datagrams.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3;
+
/**
* Satellite modem is powered off.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_OFF = 4;
+
/**
* Satellite modem is unavailable.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5;
+
/**
* The satellite modem is powered on but the device is not registered to a satellite cell.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_NOT_CONNECTED = 6;
+
/**
* The satellite modem is powered on and the device is registered to a satellite cell.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_CONNECTED = 7;
+
/**
* The satellite modem is being powered on.
* @hide
*/
public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8;
+
/**
* The satellite modem is being powered off.
* @hide
*/
public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9;
+
/**
* Satellite modem state is unknown. This generic modem state should be used only when the
* modem state cannot be mapped to other specific modem states.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1;
@@ -1099,43 +1303,56 @@
/**
* Datagram type is unknown. This generic datagram type should be used only when the
* datagram type cannot be mapped to other specific datagram types.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DATAGRAM_TYPE_UNKNOWN = 0;
+
/**
* Datagram type indicating that the datagram to be sent or received is of type SOS message.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DATAGRAM_TYPE_SOS_MESSAGE = 1;
+
/**
* Datagram type indicating that the datagram to be sent or received is of type
* location sharing.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2;
+
/**
* This type of datagram is used to keep the device in satellite connected state or check if
* there is any incoming message.
* @hide
*/
public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3;
+
/**
* Datagram type indicating that the datagram to be sent or received is of type SOS message and
* is the last message to emergency service provider indicating still needs help.
* @hide
*/
public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP = 4;
+
/**
* Datagram type indicating that the datagram to be sent or received is of type SOS message and
* is the last message to emergency service provider indicating no more help is needed.
* @hide
*/
public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5;
+
/**
* Datagram type indicating that the message to be sent or received is of type SMS.
* @hide
*/
public static final int DATAGRAM_TYPE_SMS = 6;
+
/**
* Datagram type indicating that the message to be sent is an SMS checking
* for pending incoming SMS.
@@ -1166,7 +1383,9 @@
/**
* Satellite communication restricted by geolocation. This can be
* triggered based upon geofence input provided by carrier to enable or disable satellite.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1;
@@ -1174,7 +1393,9 @@
* Satellite communication restricted by entitlement server. This can be triggered based on
* the EntitlementStatus value received from the entitlement server to enable or disable
* satellite.
+ * @hide
*/
+ @SystemApi
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2;
@@ -1201,7 +1422,10 @@
* @param callback The callback to notify of satellite transmission updates.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@SuppressWarnings("SamShouldBeLast")
@@ -1284,7 +1508,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void stopTransmissionUpdates(@NonNull SatelliteTransmissionUpdateCallback callback,
@@ -1342,7 +1569,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void provisionService(@NonNull String token, @NonNull byte[] provisionData,
@@ -1397,7 +1627,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void deprovisionService(@NonNull String token,
@@ -1440,7 +1673,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@SatelliteResult public int registerForProvisionStateChanged(
@@ -1492,7 +1728,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void unregisterForProvisionStateChanged(
@@ -1530,7 +1769,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsProvisioned(@NonNull @CallbackExecutor Executor executor,
@@ -1585,7 +1827,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@SatelliteResult public int registerForModemStateChanged(
@@ -1639,7 +1884,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void unregisterForModemStateChanged(
@@ -1679,7 +1927,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@SatelliteResult public int registerForIncomingDatagram(
@@ -1735,7 +1986,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void unregisterForIncomingDatagram(@NonNull SatelliteDatagramCallback callback) {
@@ -1773,7 +2027,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void pollPendingDatagrams(@NonNull @CallbackExecutor Executor executor,
@@ -1828,7 +2085,10 @@
* @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void sendDatagram(@DatagramType int datagramType,
@@ -1876,7 +2136,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestIsCommunicationAllowedForCurrentLocation(
@@ -1934,7 +2197,10 @@
* will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestTimeForNextSatelliteVisibility(@NonNull @CallbackExecutor Executor executor,
@@ -1992,7 +2258,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void setDeviceAlignedWithSatellite(boolean isAligned) {
@@ -2032,7 +2301,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalArgumentException if the subscription is invalid.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void requestAttachEnabledForCarrier(int subId, boolean enableSatellite,
@@ -2066,7 +2338,10 @@
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if the subscription is invalid.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void requestIsAttachEnabledForCarrier(int subId,
@@ -2091,7 +2366,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalArgumentException if the subscription is invalid.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void addAttachRestrictionForCarrier(int subId,
@@ -2136,7 +2414,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalArgumentException if the subscription is invalid.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void removeAttachRestrictionForCarrier(int subId,
@@ -2180,7 +2461,10 @@
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if the subscription is invalid.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@SatelliteCommunicationRestrictionReason
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@@ -2230,7 +2514,10 @@
* {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void requestNtnSignalStrength(@NonNull @CallbackExecutor Executor executor,
@@ -2293,7 +2580,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void registerForNtnSignalStrengthChanged(@NonNull @CallbackExecutor Executor executor,
@@ -2342,7 +2632,10 @@
* @throws IllegalArgumentException if the callback is not valid or has already been
* unregistered.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void unregisterForNtnSignalStrengthChanged(@NonNull NtnSignalStrengthCallback callback) {
@@ -2376,7 +2669,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@SatelliteResult public int registerForCapabilitiesChanged(
@@ -2419,7 +2715,10 @@
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public void unregisterForCapabilitiesChanged(
@@ -2452,7 +2751,10 @@
*
* @return List of plmn for carrier satellite service. If no plmn is available, empty list will
* be returned.
+ *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@NonNull public List<String> getSatellitePlmnsForCarrier(int subId) {