Merge "Refactor BadgedImageView to extend FrameLayout"
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 005c447..a6a007f 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -46,6 +46,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArrayMap;
+import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -681,8 +682,8 @@
final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
final double perc = batteryLevel / 100d;
// TODO: maybe don't give credits to bankrupt apps until battery level >= 50%
- if (ledger.getCurrentBalance() < minBalance) {
- final long shortfall = minBalance - getBalanceLocked(userId, pkgName);
+ final long shortfall = minBalance - ledger.getCurrentBalance();
+ if (shortfall > 0) {
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, REGULATION_BASIC_INCOME,
null, (long) (perc * shortfall)), true);
@@ -1170,5 +1171,57 @@
void dumpLocked(IndentingPrintWriter pw) {
pw.println();
mBalanceThresholdAlarmQueue.dump(pw);
+
+ pw.println();
+ pw.println("Ongoing events:");
+ pw.increaseIndent();
+ boolean printedEvents = false;
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ for (int u = mCurrentOngoingEvents.numMaps() - 1; u >= 0; --u) {
+ final int userId = mCurrentOngoingEvents.keyAt(u);
+ for (int p = mCurrentOngoingEvents.numElementsForKey(userId) - 1; p >= 0; --p) {
+ final String pkgName = mCurrentOngoingEvents.keyAt(u, p);
+ final SparseArrayMap<String, OngoingEvent> ongoingEvents =
+ mCurrentOngoingEvents.get(userId, pkgName);
+
+ boolean printedApp = false;
+
+ for (int e = ongoingEvents.numMaps() - 1; e >= 0; --e) {
+ final int eventId = ongoingEvents.keyAt(e);
+ for (int t = ongoingEvents.numElementsForKey(eventId) - 1; t >= 0; --t) {
+ if (!printedApp) {
+ printedApp = true;
+ pw.println(appToString(userId, pkgName));
+ pw.increaseIndent();
+ }
+ printedEvents = true;
+
+ OngoingEvent ongoingEvent = ongoingEvents.valueAt(e, t);
+
+ pw.print(EconomicPolicy.eventToString(ongoingEvent.eventId));
+ if (ongoingEvent.tag != null) {
+ pw.print("(");
+ pw.print(ongoingEvent.tag);
+ pw.print(")");
+ }
+ pw.print(" runtime=");
+ TimeUtils.formatDuration(nowElapsed - ongoingEvent.startTimeElapsed, pw);
+ pw.print(" delta/sec=");
+ pw.print(ongoingEvent.deltaPerSec);
+ pw.print(" refCount=");
+ pw.print(ongoingEvent.refCount);
+ pw.println();
+ }
+ }
+
+ if (printedApp) {
+ pw.decreaseIndent();
+ }
+ }
+ }
+ if (!printedEvents) {
+ pw.print("N/A");
+ }
+ pw.decreaseIndent();
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 20a300a..36895a5 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -567,20 +567,23 @@
final String pkgName = event.getPackageName();
if (DEBUG) {
Slog.d(TAG, "Processing event " + event.getEventType()
+ + " (" + event.mInstanceId + ")"
+ " for " + appToString(userId, pkgName));
}
final long nowElapsed = SystemClock.elapsedRealtime();
switch (event.getEventType()) {
case UsageEvents.Event.ACTIVITY_RESUMED:
mAgent.noteOngoingEventLocked(userId, pkgName,
- EconomicPolicy.REWARD_TOP_ACTIVITY, null, nowElapsed);
+ EconomicPolicy.REWARD_TOP_ACTIVITY, String.valueOf(event.mInstanceId),
+ nowElapsed);
break;
case UsageEvents.Event.ACTIVITY_PAUSED:
case UsageEvents.Event.ACTIVITY_STOPPED:
case UsageEvents.Event.ACTIVITY_DESTROYED:
final long now = getCurrentTimeMillis();
mAgent.stopOngoingActionLocked(userId, pkgName,
- EconomicPolicy.REWARD_TOP_ACTIVITY, null, nowElapsed, now);
+ EconomicPolicy.REWARD_TOP_ACTIVITY, String.valueOf(event.mInstanceId),
+ nowElapsed, now);
break;
case UsageEvents.Event.USER_INTERACTION:
case UsageEvents.Event.CHOOSER_ACTION:
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
index a234ae6..f4917ad 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
@@ -138,6 +138,11 @@
dumpTime(pw, transaction.endTimeMs);
pw.print(": ");
pw.print(EconomicPolicy.eventToString(transaction.eventId));
+ if (transaction.tag != null) {
+ pw.print("(");
+ pw.print(transaction.tag);
+ pw.print(")");
+ }
pw.print(" --> ");
pw.println(narcToString(transaction.delta));
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 154c42f..ee44198 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -17888,6 +17888,7 @@
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
field public static final int S_UI8 = 53; // 0x35
+ field public static final long USAGE_COMPOSER_OVERLAY = 2048L; // 0x800L
field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L
field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L
field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L
@@ -49046,6 +49047,7 @@
method @NonNull public android.view.SurfaceControl build();
method @NonNull public android.view.SurfaceControl.Builder setBufferSize(@IntRange(from=0) int, @IntRange(from=0) int);
method @NonNull public android.view.SurfaceControl.Builder setFormat(int);
+ method @NonNull public android.view.SurfaceControl.Builder setHidden(boolean);
method @NonNull public android.view.SurfaceControl.Builder setName(@NonNull String);
method @NonNull public android.view.SurfaceControl.Builder setOpaque(boolean);
method @NonNull public android.view.SurfaceControl.Builder setParent(@Nullable android.view.SurfaceControl);
@@ -49060,11 +49062,18 @@
method @NonNull public android.view.SurfaceControl.Transaction merge(@NonNull android.view.SurfaceControl.Transaction);
method @NonNull public android.view.SurfaceControl.Transaction reparent(@NonNull android.view.SurfaceControl, @Nullable android.view.SurfaceControl);
method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float);
+ method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer);
method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int);
+ method @NonNull public android.view.SurfaceControl.Transaction setBufferTransform(@NonNull android.view.SurfaceControl, int);
+ method @NonNull public android.view.SurfaceControl.Transaction setCrop(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect);
+ method @NonNull public android.view.SurfaceControl.Transaction setDamageRegion(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Region);
method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int);
method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int, int);
method @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int);
method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int);
+ method @NonNull public android.view.SurfaceControl.Transaction setOpaque(@NonNull android.view.SurfaceControl, boolean);
+ method @NonNull public android.view.SurfaceControl.Transaction setPosition(@NonNull android.view.SurfaceControl, float, float);
+ method @NonNull public android.view.SurfaceControl.Transaction setScale(@NonNull android.view.SurfaceControl, float, float);
method @NonNull public android.view.SurfaceControl.Transaction setVisibility(@NonNull android.view.SurfaceControl, boolean);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.SurfaceControl.Transaction> CREATOR;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index c9b8ba2..5a6ea89 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -70,6 +70,7 @@
field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE";
field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
+ field public static final String BLUETOOTH_MAP = "android.permission.BLUETOOTH_MAP";
field public static final String BRICK = "android.permission.BRICK";
field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
field public static final String BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS";
@@ -5875,9 +5876,11 @@
method public android.media.AudioTrack createAudioTrackSource(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
method public int getFocusDuckingBehavior();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioFocusInfo> getFocusStack();
method public int getStatus();
method public boolean removeUidDeviceAffinity(int);
method public boolean removeUserIdDeviceAffinity(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean sendFocusLoss(@NonNull android.media.AudioFocusInfo) throws java.lang.IllegalStateException;
method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setRegistration(String);
method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index cad30dd..a4a8f31 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -25,6 +25,7 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.SurfaceControl;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -129,6 +130,15 @@
public static final long USAGE_GPU_SAMPLED_IMAGE = 1 << 8;
/** Usage: The buffer will be written to by the GPU */
public static final long USAGE_GPU_COLOR_OUTPUT = 1 << 9;
+ /**
+ * The buffer will be used as a composer HAL overlay layer.
+ *
+ * This flag is currently only needed when using
+ * {@link android.view.SurfaceControl.Transaction#setBuffer(SurfaceControl, HardwareBuffer)}
+ * to set a buffer. In all other cases, the framework adds this flag
+ * internally to buffers that could be presented in a composer overlay.
+ */
+ public static final long USAGE_COMPOSER_OVERLAY = 1 << 11;
/** Usage: The buffer must not be used outside of a protected hardware path */
public static final long USAGE_PROTECTED_CONTENT = 1 << 14;
/** Usage: The buffer will be read by a hardware video encoder */
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8292f26..aa4b83a 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -192,14 +192,15 @@
// We only want to use ANGLE if the developer has explicitly chosen something other than
// default driver.
- final boolean requested = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE);
- if (requested) {
+ final boolean forceAngle = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE);
+ final boolean forceNative = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE);
+ if (forceAngle || forceNative) {
Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn);
}
final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName);
- return requested || gameModeEnabledAngle;
+ return !forceNative && (forceAngle || gameModeEnabledAngle);
}
private int getVulkanVersion(PackageManager pm) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 83a6bc0..73ffd66 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -44,7 +44,6 @@
import android.graphics.BLASTBufferQueue;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -1930,9 +1929,7 @@
mScreenshotSize.set(mSurfaceSize.x, mSurfaceSize.y);
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(hardwareBuffer);
-
- t.setBuffer(mScreenshotSurfaceControl, graphicBuffer);
+ t.setBuffer(mScreenshotSurfaceControl, hardwareBuffer);
t.setColorSpace(mScreenshotSurfaceControl, screenshotBuffer.getColorSpace());
// Place on top everything else.
t.setLayer(mScreenshotSurfaceControl, Integer.MAX_VALUE);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index af7d86c..3b52709 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -120,6 +120,8 @@
long relativeToObject, int zorder);
private static native void nativeSetPosition(long transactionObj, long nativeObject,
float x, float y);
+ private static native void nativeSetScale(long transactionObj, long nativeObject,
+ float x, float y);
private static native void nativeSetSize(long transactionObj, long nativeObject, int w, int h);
private static native void nativeSetTransparentRegionHint(long transactionObj,
long nativeObject, Region region);
@@ -202,9 +204,13 @@
private static native void nativeReparent(long transactionObj, long nativeObject,
long newParentNativeObject);
private static native void nativeSetBuffer(long transactionObj, long nativeObject,
- GraphicBuffer buffer);
+ HardwareBuffer buffer);
+ private static native void nativeSetBufferTransform(long transactionObj, long nativeObject,
+ int transform);
private static native void nativeSetColorSpace(long transactionObj, long nativeObject,
int colorSpace);
+ private static native void nativeSetDamageRegion(long transactionObj, long nativeObject,
+ Region region);
private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);
@@ -1333,7 +1339,6 @@
* Set the initial visibility for the SurfaceControl.
*
* @param hidden Whether the Surface is initially HIDDEN.
- * @hide
*/
@NonNull
public Builder setHidden(boolean hidden) {
@@ -2840,16 +2845,38 @@
}
/**
- * @hide
+ * Sets the SurfaceControl to the specified position relative to the parent
+ * SurfaceControl
+ *
+ * @param sc The SurfaceControl to change position
+ * @param x the X position
+ * @param y the Y position
+ * @return this transaction
*/
- @UnsupportedAppUsage
- public Transaction setPosition(SurfaceControl sc, float x, float y) {
+ @NonNull
+ public Transaction setPosition(@NonNull SurfaceControl sc, float x, float y) {
checkPreconditions(sc);
nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
return this;
}
/**
+ * Sets the SurfaceControl to the specified scale with (0, 0) as the center point
+ * of the scale.
+ *
+ * @param sc The SurfaceControl to change scale
+ * @param scaleX the X scale
+ * @param scaleY the Y scale
+ * @return this transaction
+ */
+ @NonNull
+ public Transaction setScale(@NonNull SurfaceControl sc, float scaleX, float scaleY) {
+ checkPreconditions(sc);
+ nativeSetScale(mNativeObject, sc.mNativeObject, scaleX, scaleY);
+ return this;
+ }
+
+ /**
* Set the default buffer size for the SurfaceControl, if there is a
* {@link Surface} associated with the control, then
* this will be the default size for buffers dequeued from it.
@@ -3056,7 +3083,9 @@
* @param sc SurfaceControl to set crop of.
* @param crop Bounds of the crop to apply.
* @hide
+ * @deprecated Use {@link #setCrop(SurfaceControl, Rect)} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
checkPreconditions(sc);
@@ -3071,6 +3100,28 @@
}
/**
+ * Bounds the surface and its children to the bounds specified. Size of the surface will be
+ * ignored and only the crop and buffer size will be used to determine the bounds of the
+ * surface. If no crop is specified and the surface has no buffer, the surface bounds is
+ * only constrained by the size of its parent bounds.
+ *
+ * @param sc SurfaceControl to set crop of.
+ * @param crop Bounds of the crop to apply.
+ * @return this This transaction for chaining
+ */
+ public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
+ checkPreconditions(sc);
+ if (crop != null) {
+ nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
+ crop.left, crop.top, crop.right, crop.bottom);
+ } else {
+ nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
+ }
+
+ return this;
+ }
+
+ /**
* Same as {@link Transaction#setWindowCrop(SurfaceControl, Rect)} but sets the crop rect
* top left at 0, 0.
*
@@ -3215,11 +3266,34 @@
}
/**
- * Sets the opacity of the surface. Setting the flag is equivalent to creating the
- * Surface with the {@link #OPAQUE} flag.
- * @hide
+ * Indicates whether the surface must be considered opaque, even if its pixel format is
+ * set to translucent. This can be useful if an application needs full RGBA 8888 support
+ * for instance but will still draw every pixel opaque.
+ * <p>
+ * This flag only determines whether opacity will be sampled from the alpha channel.
+ * Plane-alpha from calls to setAlpha() can still result in blended composition
+ * regardless of the opaque setting.
+ *
+ * Combined effects are (assuming a buffer format with an alpha channel):
+ * <ul>
+ * <li>OPAQUE + alpha(1.0) == opaque composition
+ * <li>OPAQUE + alpha(0.x) == blended composition
+ * <li>OPAQUE + alpha(0.0) == no composition
+ * <li>!OPAQUE + alpha(1.0) == blended composition
+ * <li>!OPAQUE + alpha(0.x) == blended composition
+ * <li>!OPAQUE + alpha(0.0) == no composition
+ * </ul>
+ * If the underlying buffer lacks an alpha channel, it is as if setOpaque(true)
+ * were set automatically.
+ *
+ * @see Builder#setOpaque(boolean)
+ *
+ * @param sc The SurfaceControl to update
+ * @param isOpaque true if the buffer's alpha should be ignored, false otherwise
+ * @return this
*/
- public Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+ @NonNull
+ public Transaction setOpaque(@NonNull SurfaceControl sc, boolean isOpaque) {
checkPreconditions(sc);
if (isOpaque) {
nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
@@ -3498,14 +3572,57 @@
* created as type {@link #FX_SURFACE_BLAST}
*
* @hide
+ * @deprecated Use {@link #setBuffer(SurfaceControl, HardwareBuffer)} instead
*/
+ @Deprecated
public Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) {
+ return setBuffer(sc, HardwareBuffer.createFromGraphicBuffer(buffer));
+ }
+
+ /**
+ * Updates the HardwareBuffer displayed for the SurfaceControl.
+ *
+ * Note that the buffer must be allocated with {@link HardwareBuffer#USAGE_COMPOSER_OVERLAY}
+ * as well as {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE} as the surface control might
+ * be composited using either an overlay or using the GPU.
+ *
+ * @param sc The SurfaceControl to update
+ * @param buffer The buffer to be displayed
+ * @return this
+ */
+ public @NonNull Transaction setBuffer(@NonNull SurfaceControl sc,
+ @Nullable HardwareBuffer buffer) {
checkPreconditions(sc);
nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer);
return this;
}
/**
+ * Sets the buffer transform that should be applied to the current buffer.
+ *
+ * @param sc The SurfaceControl to update
+ * @param transform The transform to apply to the buffer.
+ * @return this
+ */
+ public @NonNull Transaction setBufferTransform(@NonNull SurfaceControl sc,
+ /* TODO: Mark the intdef */ int transform) {
+ checkPreconditions(sc);
+ nativeSetBufferTransform(mNativeObject, sc.mNativeObject, transform);
+ return this;
+ }
+
+ /**
+ * Updates the region for the content on this surface updated in this transaction.
+ *
+ * If unspecified, the complete surface is assumed to be damaged.
+ */
+ public @NonNull Transaction setDamageRegion(@NonNull SurfaceControl sc,
+ @Nullable Region region) {
+ nativeSetDamageRegion(mNativeObject, sc.mNativeObject, region);
+ return this;
+ }
+
+ /**
* Set the color space for the SurfaceControl. The supported color spaces are SRGB
* and Display P3, other color spaces will be treated as SRGB. This can only be used for
* SurfaceControls that were created as type {@link #FX_SURFACE_BLAST}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index fb5fded..67d0c52 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -597,6 +597,14 @@
transaction->setPosition(ctrl, x, y);
}
+static void nativeSetScale(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
+ jfloat xScale, jfloat yScale) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setMatrix(ctrl, xScale, 0, 0, yScale);
+}
+
static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
jobject sourceObj, jobject dstObj, jlong orientation) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -620,9 +628,19 @@
jobject bufferObject) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
- sp<GraphicBuffer> buffer(
- android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env, bufferObject));
- transaction->setBuffer(ctrl, buffer);
+ sp<GraphicBuffer> graphicBuffer(GraphicBuffer::fromAHardwareBuffer(
+ android_hardware_HardwareBuffer_getNativeHardwareBuffer(env, bufferObject)));
+ transaction->setBuffer(ctrl, graphicBuffer);
+}
+
+static void nativeSetBufferTransform(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint transform) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setTransform(ctrl, transform);
+ bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) ==
+ NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ transaction->setTransformToDisplayInverse(ctrl, transformToInverseDisplay);
}
static void nativeSetColorSpace(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
@@ -740,6 +758,37 @@
}
}
+static void nativeSetDamageRegion(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jobject regionObj) {
+ SurfaceControl* const surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ if (regionObj == nullptr) {
+ transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION);
+ return;
+ }
+
+ graphics::RegionIterator iterator(env, regionObj);
+ if (!iterator.isValid()) {
+ transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION);
+ return;
+ }
+
+ Region region;
+ while (!iterator.isDone()) {
+ ARect rect = iterator.getRect();
+ region.orSelf(static_cast<const Rect&>(rect));
+ iterator.next();
+ }
+
+ if (region.getBounds().isEmpty()) {
+ transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION);
+ return;
+ }
+
+ transaction->setSurfaceDamageRegion(surfaceControl, region);
+}
+
static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jfloat alpha) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1905,10 +1954,14 @@
(void*)nativeSetRelativeLayer },
{"nativeSetPosition", "(JJFF)V",
(void*)nativeSetPosition },
+ {"nativeSetScale", "(JJFF)V",
+ (void*)nativeSetScale },
{"nativeSetSize", "(JJII)V",
(void*)nativeSetSize },
{"nativeSetTransparentRegionHint", "(JJLandroid/graphics/Region;)V",
(void*)nativeSetTransparentRegionHint },
+ { "nativeSetDamageRegion", "(JJLandroid/graphics/Region;)V",
+ (void*)nativeSetDamageRegion },
{"nativeSetAlpha", "(JJF)V",
(void*)nativeSetAlpha },
{"nativeSetColor", "(JJ[F)V",
@@ -2018,8 +2071,9 @@
(void*)nativeGetDisplayedContentSample },
{"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
(void*)nativeSetGeometry },
- {"nativeSetBuffer", "(JJLandroid/graphics/GraphicBuffer;)V",
+ {"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;)V",
(void*)nativeSetBuffer },
+ {"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform},
{"nativeSetColorSpace", "(JJI)V",
(void*)nativeSetColorSpace },
{"nativeSyncInputWindows", "(J)V",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4c36732..0894877 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2066,7 +2066,7 @@
<permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
android:protectionLevel="signature|privileged" />
- <!-- Control access to email providers exclusively for Bluetooth
+ <!-- @SystemApi Control access to email providers exclusively for Bluetooth
@hide
-->
<permission android:name="android.permission.BLUETOOTH_MAP"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
index eea6e3c..c4bd73b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
@@ -16,7 +16,6 @@
package com.android.wm.shell.common;
-import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.view.SurfaceControl;
@@ -63,8 +62,6 @@
if (buffer == null || buffer.getHardwareBuffer() == null) {
return;
}
- final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- buffer.getHardwareBuffer());
mScreenshot = new SurfaceControl.Builder()
.setName("ScreenshotUtils screenshot")
.setFormat(PixelFormat.TRANSLUCENT)
@@ -73,7 +70,7 @@
.setBLASTLayer()
.build();
- mTransaction.setBuffer(mScreenshot, graphicBuffer);
+ mTransaction.setBuffer(mScreenshot, buffer.getHardwareBuffer());
mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
mTransaction.reparent(mScreenshot, mSurfaceControl);
mTransaction.setLayer(mScreenshot, mLayer);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 6643ca1..4ecc0b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -380,9 +380,7 @@
}
private void drawSizeMatchSnapshot() {
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
- mTransaction.setBuffer(mSurfaceControl, graphicBuffer)
+ mTransaction.setBuffer(mSurfaceControl, mSnapshot.getHardwareBuffer())
.setColorSpace(mSurfaceControl, mSnapshot.getColorSpace())
.apply();
}
@@ -428,20 +426,20 @@
// Scale the mismatch dimensions to fill the task bounds
mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
mTransaction.setMatrix(childSurfaceControl, mSnapshotMatrix, mTmpFloat9);
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
- mTransaction.setBuffer(childSurfaceControl, graphicBuffer);
+ mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
if (aspectRatioMismatch) {
GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(),
PixelFormat.RGBA_8888,
GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
| GraphicBuffer.USAGE_SW_WRITE_RARELY);
+ // TODO: Support this on HardwareBuffer
final Canvas c = background.lockCanvas();
drawBackgroundAndBars(c, frame);
background.unlockCanvasAndPost(c);
- mTransaction.setBuffer(mSurfaceControl, background);
+ mTransaction.setBuffer(mSurfaceControl,
+ HardwareBuffer.createFromGraphicBuffer(background));
}
mTransaction.apply();
childSurfaceControl.release();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 147e735..7f6fb90 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -460,4 +460,8 @@
boolean register);
void setTestDeviceConnectionState(in AudioDeviceAttributes device, boolean connected);
+
+ List<AudioFocusInfo> getFocusStack();
+
+ boolean sendFocusLoss(in AudioFocusInfo focusLoser, in IAudioPolicyCallback apcb);
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 0f08d79..3ba1d1f 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
@@ -230,7 +231,7 @@
* If set to {@code true}, it is mandatory to set an
* {@link AudioPolicy.AudioPolicyFocusListener} in order to successfully build
* an {@code AudioPolicy} instance.
- * @param enforce true if the policy will govern audio focus decisions.
+ * @param isFocusPolicy true if the policy will govern audio focus decisions.
* @return the same Builder instance.
*/
@NonNull
@@ -723,6 +724,45 @@
}
/**
+ * Returns the list of entries in the focus stack.
+ * The list is ordered with increasing rank of focus ownership, where the last entry is at the
+ * top of the focus stack and is the current focus owner.
+ * @return the ordered list of focus owners
+ * @see AudioManager#registerAudioPolicy(AudioPolicy)
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public @NonNull List<AudioFocusInfo> getFocusStack() {
+ try {
+ return getService().getFocusStack();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Send AUDIOFOCUS_LOSS to a specific stack entry, causing it to be notified of the focus
+ * loss, and for it to exit the focus stack (its focus listener will not be invoked after that).
+ * This operation is only valid for a registered policy (with
+ * {@link AudioManager#registerAudioPolicy(AudioPolicy)}) that is also set as the policy focus
+ * listener (with {@link Builder#setAudioPolicyFocusListener(AudioPolicyFocusListener)}.
+ * @param focusLoser the stack entry that is exiting the stack through a focus loss
+ * @return false if the focusLoser wasn't found in the stack, true otherwise
+ * @throws IllegalStateException if used on an unregistered policy, or a registered policy
+ * with no {@link AudioPolicyFocusListener} set
+ * @see AudioManager#registerAudioPolicy(AudioPolicy)
+ * @see Builder#setAudioPolicyStatusListener(AudioPolicyStatusListener)
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public boolean sendFocusLoss(@NonNull AudioFocusInfo focusLoser) throws IllegalStateException {
+ Objects.requireNonNull(focusLoser);
+ try {
+ return getService().sendFocusLoss(focusLoser, cb());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Create an {@link AudioRecord} instance that is associated with the given {@link AudioMix}.
* Audio buffers recorded through the created instance will contain the mix of the audio
* streams that fed the given mixer.
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index ceba4d6..f76811e 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -364,7 +364,7 @@
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
- sp<GraphicBuffer> graphic_buffer(reinterpret_cast<GraphicBuffer*>(buffer));
+ sp<GraphicBuffer> graphic_buffer(GraphicBuffer::fromAHardwareBuffer(buffer));
std::optional<sp<Fence>> fence = std::nullopt;
if (acquire_fence_fd != -1) {
diff --git a/packages/SystemUI/res/values-h800dp/dimens.xml b/packages/SystemUI/res/values-h800dp/dimens.xml
index f057603..1d6f279 100644
--- a/packages/SystemUI/res/values-h800dp/dimens.xml
+++ b/packages/SystemUI/res/values-h800dp/dimens.xml
@@ -22,5 +22,5 @@
<dimen name="large_clock_text_size">200dp</dimen>
<!-- With the large clock, move up slightly from the center -->
- <dimen name="keyguard_large_clock_top_margin">-104dp</dimen>
+ <dimen name="keyguard_large_clock_top_margin">-112dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ddec6cb..d4398a8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -30,10 +30,10 @@
<dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
<!-- dimensions for the navigation bar handle -->
- <dimen name="navigation_handle_radius">1dp</dimen>
- <dimen name="navigation_handle_bottom">6dp</dimen>
+ <dimen name="navigation_handle_radius">2dp</dimen>
+ <dimen name="navigation_handle_bottom">10dp</dimen>
<dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen>
- <dimen name="navigation_home_handle_width">72dp</dimen>
+ <dimen name="navigation_home_handle_width">108dp</dimen>
<!-- Size of the nav bar edge panels, should be greater to the
edge sensitivity + the drag threshold -->
@@ -602,7 +602,7 @@
<!-- When large clock is showing, offset the smartspace by this amount -->
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
<!-- With the large clock, move up slightly from the center -->
- <dimen name="keyguard_large_clock_top_margin">-52dp</dimen>
+ <dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
<!-- Default line spacing multiplier between hours and minutes of the keyguard clock -->
<item name="keyguard_clock_line_spacing_scale" type="dimen" format="float">.7</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 19cb020..b7a5aae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -275,11 +275,9 @@
}
private void updateClockLayout() {
- int largeClockTopMargin = 0;
- if (mSmartspaceController.isEnabled()) {
- largeClockTopMargin = getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_large_clock_top_margin);
- }
+ int largeClockTopMargin = getContext().getResources().getDimensionPixelSize(
+ R.dimen.keyguard_large_clock_top_margin);
+
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT,
MATCH_PARENT);
lp.topMargin = largeClockTopMargin;
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java
index 4aa46f18..58cf35f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java
@@ -16,12 +16,14 @@
package com.android.systemui.communal;
+import static com.android.systemui.communal.dagger.CommunalModule.COMMUNAL_CONDITIONS;
+
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.communal.conditions.CommunalConditionsMonitor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.util.condition.Monitor;
import com.google.android.collect.Lists;
@@ -31,6 +33,7 @@
import java.util.concurrent.Executor;
import javax.inject.Inject;
+import javax.inject.Named;
/**
* A Monitor for reporting a {@link CommunalSource} presence.
@@ -42,7 +45,7 @@
// A list of {@link Callback} that have registered to receive updates.
private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList();
- private final CommunalConditionsMonitor mConditionsMonitor;
+ private final Monitor mConditionsMonitor;
private final Executor mExecutor;
private CommunalSource mCurrentSource;
@@ -53,7 +56,7 @@
// Whether the class is currently listening for condition changes.
private boolean mListeningForConditions = false;
- private final CommunalConditionsMonitor.Callback mConditionsCallback =
+ private final Monitor.Callback mConditionsCallback =
allConditionsMet -> {
if (mAllCommunalConditionsMet != allConditionsMet) {
if (DEBUG) Log.d(TAG, "communal conditions changed: " + allConditionsMet);
@@ -66,7 +69,7 @@
@VisibleForTesting
@Inject
public CommunalSourceMonitor(@Main Executor executor,
- CommunalConditionsMonitor communalConditionsMonitor) {
+ @Named(COMMUNAL_CONDITIONS) Monitor communalConditionsMonitor) {
mExecutor = executor;
mConditionsMonitor = communalConditionsMonitor;
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/conditions/CommunalConditionsMonitor.java b/packages/SystemUI/src/com/android/systemui/communal/conditions/CommunalConditionsMonitor.java
deleted file mode 100644
index 1197816..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/conditions/CommunalConditionsMonitor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2021 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.communal.conditions;
-
-
-import static com.android.systemui.communal.dagger.CommunalModule.COMMUNAL_CONDITIONS;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.util.condition.Condition;
-import com.android.systemui.util.condition.Monitor;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * A concrete implementation of {@Monitor} with conditions for monitoring when communal mode should
- * be enabled.
- */
-@SysUISingleton
-public class CommunalConditionsMonitor extends Monitor {
- @Inject
- public CommunalConditionsMonitor(
- @Named(COMMUNAL_CONDITIONS) Set<Condition> communalConditions) {
- super(communalConditions);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.java b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.java
index f27ae34..e1f1ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.java
+++ b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.java
@@ -34,6 +34,8 @@
import com.android.systemui.idle.LightSensorEventsDebounceAlgorithm;
import com.android.systemui.idle.dagger.IdleViewComponent;
import com.android.systemui.util.condition.Condition;
+import com.android.systemui.util.condition.Monitor;
+import com.android.systemui.util.condition.dagger.MonitorComponent;
import java.util.Collections;
import java.util.HashSet;
@@ -135,4 +137,14 @@
return Optional.empty();
}
}
+
+ /** */
+ @Provides
+ @Named(COMMUNAL_CONDITIONS)
+ static Monitor provideCommunalSourceMonitor(
+ @Named(COMMUNAL_CONDITIONS) Set<Condition> communalConditions,
+ MonitorComponent.Factory factory) {
+ final MonitorComponent component = factory.create(communalConditions, new HashSet<>());
+ return component.getMonitor();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 5bd02cc..10efec3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -48,6 +48,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
@@ -562,7 +563,8 @@
return this;
}
- CustomTile build() {
+ @VisibleForTesting
+ public CustomTile build() {
if (mUserContext == null) {
throw new NullPointerException("UserContext cannot be null");
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ac95bf5..c2a9e3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -169,7 +169,7 @@
mFgsManagerTileProvider = fgsManagerTileProvider;
}
- public QSTile createTile(String tileSpec) {
+ public final QSTile createTile(String tileSpec) {
QSTileImpl tile = createTileInternal(tileSpec);
if (tile != null) {
tile.initialize();
@@ -178,7 +178,7 @@
return tile;
}
- private QSTileImpl createTileInternal(String tileSpec) {
+ protected QSTileImpl createTileInternal(String tileSpec) {
// Stock tiles.
switch (tileSpec) {
case "wifi":
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
index 75cf4d1..939a297 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
@@ -54,7 +54,7 @@
qsLogger: QSLogger?,
private val fgsManagerDialogFactory: FgsManagerDialogFactory,
private val runningFgsController: RunningFgsController
-) : QSTileImpl<QSTile.State?>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+) : QSTileImpl<QSTile.State>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger), RunningFgsController.Callback {
override fun handleInitialize() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index f6e19bf..8cf7288 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -49,8 +49,9 @@
}
private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
- // TODO(b/194178072) Handle RSSI hiding when multi carrier
private val iconManager: StatusBarIconController.TintedIconManager
+ private val iconContainer: StatusIconContainer
+ private val carrierIconSlots: List<String>
private val qsCarrierGroupController: QSCarrierGroupController
private var visible = false
set(value) {
@@ -117,10 +118,19 @@
batteryMeterViewController.ignoreTunerUpdates()
batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
- val iconContainer: StatusIconContainer = statusBar.findViewById(R.id.statusIcons)
+ iconContainer = statusBar.findViewById(R.id.statusIcons)
iconManager = StatusBarIconController.TintedIconManager(iconContainer, featureFlags)
iconManager.setTint(Utils.getColorAttrDefaultColor(statusBar.context,
android.R.attr.textColorPrimary))
+
+ carrierIconSlots = if (featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) {
+ listOf(
+ statusBar.context.getString(com.android.internal.R.string.status_bar_no_calling),
+ statusBar.context.getString(com.android.internal.R.string.status_bar_call_strength)
+ )
+ } else {
+ listOf(statusBar.context.getString(com.android.internal.R.string.status_bar_mobile))
+ }
qsCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(statusBar.findViewById(R.id.carrier_group))
.build()
@@ -185,9 +195,20 @@
private fun updateListeners() {
qsCarrierGroupController.setListening(visible)
if (visible) {
+ updateSingleCarrier(qsCarrierGroupController.isSingleCarrier)
+ qsCarrierGroupController.setOnSingleCarrierChangedListener { updateSingleCarrier(it) }
statusBarIconController.addIconGroup(iconManager)
} else {
+ qsCarrierGroupController.setOnSingleCarrierChangedListener(null)
statusBarIconController.removeIconGroup(iconManager)
}
}
+
+ private fun updateSingleCarrier(singleCarrier: Boolean) {
+ if (singleCarrier) {
+ iconContainer.removeIgnoredSlots(carrierIconSlots)
+ } else {
+ iconContainer.addIgnoredSlots(carrierIconSlots)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
index a7e9cdb..8b6e982 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
@@ -23,7 +23,6 @@
import org.jetbrains.annotations.NotNull;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -38,7 +37,7 @@
public class Monitor implements CallbackController<Monitor.Callback> {
private final String mTag = getClass().getSimpleName();
- private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
+ private final ArrayList<Callback> mCallbacks = new ArrayList<>();
// Set of all conditions that need to be monitored.
private final Set<Condition> mConditions;
@@ -66,9 +65,9 @@
mAllConditionsMet = newAllConditionsMet;
// Updates all callbacks.
- final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
+ final Iterator<Callback> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
- final Callback callback = iterator.next().get();
+ final Callback callback = iterator.next();
if (callback == null) {
iterator.remove();
} else {
@@ -78,7 +77,7 @@
};
@Inject
- public Monitor(Set<Condition> conditions) {
+ public Monitor(Set<Condition> conditions, Set<Callback> callbacks) {
mConditions = conditions;
// If there is no condition, give green pass.
@@ -89,12 +88,20 @@
// Initializes the conditions map and registers a callback for each condition.
mConditions.forEach((condition -> mConditionsMap.put(condition, false)));
+
+ if (callbacks == null) {
+ return;
+ }
+
+ for (Callback callback : callbacks) {
+ addCallback(callback);
+ }
}
@Override
public void addCallback(@NotNull Callback callback) {
if (shouldLog()) Log.d(mTag, "adding callback");
- mCallbacks.add(new WeakReference<>(callback));
+ mCallbacks.add(callback);
// Updates the callback immediately.
callback.onConditionsChanged(mAllConditionsMet);
@@ -109,9 +116,9 @@
@Override
public void removeCallback(@NotNull Callback callback) {
if (shouldLog()) Log.d(mTag, "removing callback");
- final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
+ final Iterator<Callback> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
- final Callback cb = iterator.next().get();
+ final Callback cb = iterator.next();
if (cb == null || cb == callback) {
iterator.remove();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
new file mode 100644
index 0000000..fc67973
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.util.condition.dagger;
+
+import com.android.systemui.util.condition.Condition;
+import com.android.systemui.util.condition.Monitor;
+
+import java.util.Set;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * Component for {@link Monitor}.
+ */
+@Subcomponent
+public interface MonitorComponent {
+ /**
+ * Factory for {@link MonitorComponent}.
+ */
+ @Subcomponent.Factory
+ interface Factory {
+ MonitorComponent create(@BindsInstance Set<Condition> conditions,
+ @BindsInstance Set<Monitor.Callback> callbacks);
+ }
+
+ /**
+ * Provides {@link Monitor}.
+ * @return
+ */
+ Monitor getMonitor();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
index 981bf01..7892d6e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
@@ -18,6 +18,7 @@
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.RingerModeTrackerImpl;
+import com.android.systemui.util.condition.dagger.MonitorComponent;
import com.android.systemui.util.wrapper.UtilWrapperModule;
import dagger.Binds;
@@ -26,6 +27,9 @@
/** Dagger Module for code in the util package. */
@Module(includes = {
UtilWrapperModule.class
+ },
+ subcomponents = {
+ MonitorComponent.class,
})
public interface UtilModule {
/** */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalManagerUpdaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalManagerUpdaterTest.java
index 9a9b7c4..4a29ada 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalManagerUpdaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalManagerUpdaterTest.java
@@ -28,8 +28,8 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.communal.conditions.CommunalConditionsMonitor;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.condition.Monitor;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -45,7 +45,7 @@
@Mock
private CommunalManager mCommunalManager;
@Mock
- private CommunalConditionsMonitor mCommunalConditionsMonitor;
+ private Monitor mCommunalConditionsMonitor;
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -55,7 +55,7 @@
mContext.addMockSystemService(CommunalManager.class, mCommunalManager);
doAnswer(invocation -> {
- final CommunalConditionsMonitor.Callback callback = invocation.getArgument(0);
+ final Monitor.Callback callback = invocation.getArgument(0);
callback.onConditionsChanged(true);
return null;
}).when(mCommunalConditionsMonitor).addCallback(any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java
index 409dd94..df1cc76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java
@@ -31,8 +31,8 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.communal.conditions.CommunalConditionsMonitor;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.condition.Monitor;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -49,9 +49,9 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class CommunalSourceMonitorTest extends SysuiTestCase {
- @Mock private CommunalConditionsMonitor mCommunalConditionsMonitor;
+ @Mock private Monitor mCommunalConditionsMonitor;
- @Captor private ArgumentCaptor<CommunalConditionsMonitor.Callback> mConditionsCallbackCaptor;
+ @Captor private ArgumentCaptor<Monitor.Callback> mConditionsCallbackCaptor;
private CommunalSourceMonitor mCommunalSourceMonitor;
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -156,7 +156,7 @@
private void setConditionsMet(boolean value) {
mExecutor.runAllReady();
verify(mCommunalConditionsMonitor).addCallback(mConditionsCallbackCaptor.capture());
- final CommunalConditionsMonitor.Callback conditionsCallback =
+ final Monitor.Callback conditionsCallback =
mConditionsCallbackCaptor.getValue();
conditionsCallback.onConditionsChanged(value);
mExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
new file mode 100644
index 0000000..af33daf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 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.tileimpl
+
+import android.content.ComponentName
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.external.CustomTile
+import com.android.systemui.qs.tiles.AirplaneModeTile
+import com.android.systemui.qs.tiles.AlarmTile
+import com.android.systemui.qs.tiles.BatterySaverTile
+import com.android.systemui.qs.tiles.BluetoothTile
+import com.android.systemui.qs.tiles.CameraToggleTile
+import com.android.systemui.qs.tiles.CastTile
+import com.android.systemui.qs.tiles.CellularTile
+import com.android.systemui.qs.tiles.ColorInversionTile
+import com.android.systemui.qs.tiles.DataSaverTile
+import com.android.systemui.qs.tiles.DeviceControlsTile
+import com.android.systemui.qs.tiles.DndTile
+import com.android.systemui.qs.tiles.FgsManagerTile
+import com.android.systemui.qs.tiles.FlashlightTile
+import com.android.systemui.qs.tiles.HotspotTile
+import com.android.systemui.qs.tiles.InternetTile
+import com.android.systemui.qs.tiles.LocationTile
+import com.android.systemui.qs.tiles.MicrophoneToggleTile
+import com.android.systemui.qs.tiles.NfcTile
+import com.android.systemui.qs.tiles.NightDisplayTile
+import com.android.systemui.qs.tiles.OneHandedModeTile
+import com.android.systemui.qs.tiles.QRCodeScannerTile
+import com.android.systemui.qs.tiles.QuickAccessWalletTile
+import com.android.systemui.qs.tiles.ReduceBrightColorsTile
+import com.android.systemui.qs.tiles.RotationLockTile
+import com.android.systemui.qs.tiles.ScreenRecordTile
+import com.android.systemui.qs.tiles.UiModeNightTile
+import com.android.systemui.qs.tiles.UserTile
+import com.android.systemui.qs.tiles.WifiTile
+import com.android.systemui.qs.tiles.WorkModeTile
+import com.android.systemui.util.leak.GarbageMonitor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito.inOrder
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+private val specMap = mapOf(
+ "wifi" to WifiTile::class.java,
+ "internet" to InternetTile::class.java,
+ "bt" to BluetoothTile::class.java,
+ "cell" to CellularTile::class.java,
+ "dnd" to DndTile::class.java,
+ "inversion" to ColorInversionTile::class.java,
+ "airplane" to AirplaneModeTile::class.java,
+ "work" to WorkModeTile::class.java,
+ "rotation" to RotationLockTile::class.java,
+ "flashlight" to FlashlightTile::class.java,
+ "location" to LocationTile::class.java,
+ "cast" to CastTile::class.java,
+ "hotspot" to HotspotTile::class.java,
+ "user" to UserTile::class.java,
+ "battery" to BatterySaverTile::class.java,
+ "saver" to DataSaverTile::class.java,
+ "night" to NightDisplayTile::class.java,
+ "nfc" to NfcTile::class.java,
+ "dark" to UiModeNightTile::class.java,
+ "screenrecord" to ScreenRecordTile::class.java,
+ "reduce_brightness" to ReduceBrightColorsTile::class.java,
+ "cameratoggle" to CameraToggleTile::class.java,
+ "mictoggle" to MicrophoneToggleTile::class.java,
+ "controls" to DeviceControlsTile::class.java,
+ "alarm" to AlarmTile::class.java,
+ "wallet" to QuickAccessWalletTile::class.java,
+ "qr_code_scanner" to QRCodeScannerTile::class.java,
+ "onehanded" to OneHandedModeTile::class.java,
+ "fgsmanager" to FgsManagerTile::class.java
+)
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class QSFactoryImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var qsHost: QSHost
+ @Mock(answer = Answers.RETURNS_SELF) private lateinit var customTileBuilder: CustomTile.Builder
+ @Mock private lateinit var customTile: CustomTile
+
+ @Mock private lateinit var wifiTile: WifiTile
+ @Mock private lateinit var internetTile: InternetTile
+ @Mock private lateinit var bluetoothTile: BluetoothTile
+ @Mock private lateinit var cellularTile: CellularTile
+ @Mock private lateinit var dndTile: DndTile
+ @Mock private lateinit var colorInversionTile: ColorInversionTile
+ @Mock private lateinit var airplaneTile: AirplaneModeTile
+ @Mock private lateinit var workTile: WorkModeTile
+ @Mock private lateinit var rotationTile: RotationLockTile
+ @Mock private lateinit var flashlightTile: FlashlightTile
+ @Mock private lateinit var locationTile: LocationTile
+ @Mock private lateinit var castTile: CastTile
+ @Mock private lateinit var hotspotTile: HotspotTile
+ @Mock private lateinit var userTile: UserTile
+ @Mock private lateinit var batterySaverTile: BatterySaverTile
+ @Mock private lateinit var dataSaverTile: DataSaverTile
+ @Mock private lateinit var nightDisplayTile: NightDisplayTile
+ @Mock private lateinit var nfcTile: NfcTile
+ @Mock private lateinit var memoryTile: GarbageMonitor.MemoryTile
+ @Mock private lateinit var darkModeTile: UiModeNightTile
+ @Mock private lateinit var screenRecordTile: ScreenRecordTile
+ @Mock private lateinit var reduceBrightColorsTile: ReduceBrightColorsTile
+ @Mock private lateinit var cameraToggleTile: CameraToggleTile
+ @Mock private lateinit var microphoneToggleTile: MicrophoneToggleTile
+ @Mock private lateinit var deviceControlsTile: DeviceControlsTile
+ @Mock private lateinit var alarmTile: AlarmTile
+ @Mock private lateinit var quickAccessWalletTile: QuickAccessWalletTile
+ @Mock private lateinit var qrCodeScannerTile: QRCodeScannerTile
+ @Mock private lateinit var oneHandedModeTile: OneHandedModeTile
+ @Mock private lateinit var fgsManagerTile: FgsManagerTile
+
+ private lateinit var factory: QSFactoryImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(qsHost.context).thenReturn(mContext)
+ whenever(qsHost.userContext).thenReturn(mContext)
+ whenever(customTileBuilder.build()).thenReturn(customTile)
+
+ factory = QSFactoryImpl(
+ { qsHost },
+ { customTileBuilder },
+ { wifiTile },
+ { internetTile },
+ { bluetoothTile },
+ { cellularTile },
+ { dndTile },
+ { colorInversionTile },
+ { airplaneTile },
+ { workTile },
+ { rotationTile },
+ { flashlightTile },
+ { locationTile },
+ { castTile },
+ { hotspotTile },
+ { userTile },
+ { batterySaverTile },
+ { dataSaverTile },
+ { nightDisplayTile },
+ { nfcTile },
+ { memoryTile },
+ { darkModeTile },
+ { screenRecordTile },
+ { reduceBrightColorsTile },
+ { cameraToggleTile },
+ { microphoneToggleTile },
+ { deviceControlsTile },
+ { alarmTile },
+ { quickAccessWalletTile },
+ { qrCodeScannerTile },
+ { oneHandedModeTile },
+ { fgsManagerTile }
+ )
+ // When adding/removing tiles, fix also [specMap]
+ }
+
+ @Test
+ fun testCorrectTileClassStock() {
+ specMap.forEach { spec, klazz ->
+ assertThat(factory.createTile(spec)).isInstanceOf(klazz)
+ }
+ }
+
+ @Test
+ fun testCustomTileClass() {
+ val customSpec = CustomTile.toSpec(ComponentName("test", "test"))
+ assertThat(factory.createTile(customSpec)).isInstanceOf(CustomTile::class.java)
+ }
+
+ @Test
+ fun testBadTileNull() {
+ assertThat(factory.createTile("-432~")).isNull()
+ }
+
+ @Test
+ fun testTileInitializedAndStale() {
+ specMap.forEach { spec, _ ->
+ val tile = factory.createTile(spec) as QSTileImpl<*>
+ val inOrder = inOrder(tile)
+ inOrder.verify(tile).initialize()
+ inOrder.verify(tile).postStale()
+ }
+
+ val customSpec = CustomTile.toSpec(ComponentName("test", "test"))
+ val tile = factory.createTile(customSpec) as QSTileImpl<*>
+ val inOrder = inOrder(tile)
+ inOrder.verify(tile).initialize()
+ inOrder.verify(tile).postStale()
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
index 2d548e9..a8544a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
@@ -1,8 +1,8 @@
package com.android.systemui.statusbar.phone
-import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.view.View
+import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation
@@ -42,6 +42,7 @@
var viewVisibility = View.GONE
private lateinit var splitShadeHeaderController: SplitShadeHeaderController
+ private lateinit var carrierIconSlots: List<String>
@Before
fun setup() {
@@ -67,12 +68,13 @@
featureFlags,
batteryMeterViewController
)
+ carrierIconSlots = listOf(
+ context.getString(com.android.internal.R.string.status_bar_mobile))
}
@Test
fun setVisible_onlyInSplitShade() {
- splitShadeHeaderController.splitShadeMode = true
- splitShadeHeaderController.shadeExpanded = true
+ makeShadeVisible()
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
splitShadeHeaderController.splitShadeMode = false
@@ -81,17 +83,38 @@
@Test
fun updateListeners_registersWhenVisible() {
- splitShadeHeaderController.splitShadeMode = true
- splitShadeHeaderController.shadeExpanded = true
+ makeShadeVisible()
verify(qsCarrierGroupController).setListening(true)
verify(statusBarIconController).addIconGroup(any())
}
@Test
fun shadeExpandedFraction_updatesAlpha() {
- splitShadeHeaderController.splitShadeMode = true
- splitShadeHeaderController.shadeExpanded = true
+ makeShadeVisible()
splitShadeHeaderController.shadeExpandedFraction = 0.5f
verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
}
-}
\ No newline at end of file
+
+ @Test
+ fun singleCarrier_enablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
+
+ makeShadeVisible()
+
+ verify(statusIcons).removeIgnoredSlots(carrierIconSlots)
+ }
+
+ @Test
+ fun dualCarrier_disablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
+
+ makeShadeVisible()
+
+ verify(statusIcons).addIgnoredSlots(carrierIconSlots)
+ }
+
+ private fun makeShadeVisible() {
+ splitShadeHeaderController.splitShadeMode = true
+ splitShadeHeaderController.shadeExpanded = true
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
index 878bdea..d645449 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
@@ -58,7 +58,7 @@
mCondition3 = spy(new FakeCondition());
mConditions = new HashSet<>(Arrays.asList(mCondition1, mCondition2, mCondition3));
- mConditionMonitor = new Monitor(mConditions);
+ mConditionMonitor = new Monitor(mConditions, null /*callbacks*/);
}
@Test
@@ -98,7 +98,7 @@
@Test
public void addCallback_noConditions_reportAllConditionsMet() {
- final Monitor monitor = new Monitor(new HashSet<>());
+ final Monitor monitor = new Monitor(new HashSet<>(), null /*callbacks*/);
final Monitor.Callback callback = mock(Monitor.Callback.class);
monitor.addCallback(callback);
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values-land/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values-land/dimens.xml
index 1f5834d..a03dcbd 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values-land/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values-land/dimens.xml
@@ -18,5 +18,5 @@
-->
<resources>
<!-- The height of the bottom navigation gesture area. -->
- <dimen name="navigation_bar_gesture_height">32dp</dimen>
+ <dimen name="navigation_bar_gesture_height">24dp</dimen>
</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
index ac1f022..c5d0c9e 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
@@ -18,13 +18,13 @@
-->
<resources>
<!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">16dp</dimen>
+ <dimen name="navigation_bar_height">24dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
- <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <dimen name="navigation_bar_height_landscape">24dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
- <dimen name="navigation_bar_width">16dp</dimen>
+ <dimen name="navigation_bar_width">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_frame_height">48dp</dimen>
<!-- The height of the bottom navigation gesture area. -->
- <dimen name="navigation_bar_gesture_height">32dp</dimen>
+ <dimen name="navigation_bar_gesture_height">24dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
index ac1f022..c5d0c9e 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
@@ -18,13 +18,13 @@
-->
<resources>
<!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">16dp</dimen>
+ <dimen name="navigation_bar_height">24dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
- <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <dimen name="navigation_bar_height_landscape">24dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
- <dimen name="navigation_bar_width">16dp</dimen>
+ <dimen name="navigation_bar_width">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_frame_height">48dp</dimen>
<!-- The height of the bottom navigation gesture area. -->
- <dimen name="navigation_bar_gesture_height">32dp</dimen>
+ <dimen name="navigation_bar_gesture_height">24dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
index ac1f022..c5d0c9e 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
@@ -18,13 +18,13 @@
-->
<resources>
<!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">16dp</dimen>
+ <dimen name="navigation_bar_height">24dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
- <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <dimen name="navigation_bar_height_landscape">24dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
- <dimen name="navigation_bar_width">16dp</dimen>
+ <dimen name="navigation_bar_width">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_frame_height">48dp</dimen>
<!-- The height of the bottom navigation gesture area. -->
- <dimen name="navigation_bar_gesture_height">32dp</dimen>
+ <dimen name="navigation_bar_gesture_height">24dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
index ac1f022..c5d0c9e 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
@@ -18,13 +18,13 @@
-->
<resources>
<!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">16dp</dimen>
+ <dimen name="navigation_bar_height">24dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
- <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <dimen name="navigation_bar_height_landscape">24dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
- <dimen name="navigation_bar_width">16dp</dimen>
+ <dimen name="navigation_bar_width">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_frame_height">48dp</dimen>
<!-- The height of the bottom navigation gesture area. -->
- <dimen name="navigation_bar_gesture_height">32dp</dimen>
+ <dimen name="navigation_bar_gesture_height">24dp</dimen>
</resources>
\ No newline at end of file
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 20606f0..8dce8e9 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -385,9 +385,8 @@
}
public boolean isValid() {
- return (mGameMode == GameManager.GAME_MODE_PERFORMANCE
- || mGameMode == GameManager.GAME_MODE_BATTERY)
- && (!mAllowDownscale || getCompatChangeId() != 0);
+ return mGameMode == GameManager.GAME_MODE_PERFORMANCE
+ || mGameMode == GameManager.GAME_MODE_BATTERY;
}
/**
@@ -839,7 +838,7 @@
}
long scaleId = modeConfig.getCompatChangeId();
if (scaleId == 0) {
- Slog.w(TAG, "Invalid downscaling change id " + scaleId + " for "
+ Slog.i(TAG, "Invalid downscaling change id " + scaleId + " for "
+ packageName);
return;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6238198..f857064 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -10142,6 +10142,27 @@
return AudioManager.SUCCESS;
}
+ /** @see AudioPolicy#getFocusStack() */
+ public List<AudioFocusInfo> getFocusStack() {
+ enforceModifyAudioRoutingPermission();
+ return mMediaFocusControl.getFocusStack();
+ }
+
+ /** @see AudioPolicy#sendFocusLoss */
+ public boolean sendFocusLoss(@NonNull AudioFocusInfo focusLoser,
+ @NonNull IAudioPolicyCallback apcb) {
+ Objects.requireNonNull(focusLoser);
+ Objects.requireNonNull(apcb);
+ enforceModifyAudioRoutingPermission();
+ if (!mAudioPolicies.containsKey(apcb.asBinder())) {
+ throw new IllegalStateException("Only registered AudioPolicy can change focus");
+ }
+ if (!mAudioPolicies.get(apcb.asBinder()).mHasFocusListener) {
+ throw new IllegalStateException("AudioPolicy must have focus listener to change focus");
+ }
+ return mMediaFocusControl.sendFocusLoss(focusLoser);
+ }
+
/** see AudioManager.hasRegisteredDynamicPolicy */
public boolean hasRegisteredDynamicPolicy() {
synchronized (mAudioPolicies) {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 66f6235..69a4c23 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -27,6 +27,7 @@
import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
import android.media.MediaMetrics;
+import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.Build;
@@ -221,6 +222,51 @@
}
}
+ /**
+ * Return a copy of the focus stack for external consumption (composed of AudioFocusInfo
+ * instead of FocusRequester instances)
+ * @return a SystemApi-friendly version of the focus stack, in the same order (last entry
+ * is top of focus stack, i.e. latest focus owner)
+ * @see AudioPolicy#getFocusStack()
+ */
+ @NonNull List<AudioFocusInfo> getFocusStack() {
+ synchronized (mAudioFocusLock) {
+ final ArrayList<AudioFocusInfo> stack = new ArrayList<>(mFocusStack.size());
+ for (FocusRequester fr : mFocusStack) {
+ stack.add(fr.toAudioFocusInfo());
+ }
+ return stack;
+ }
+ }
+
+ /**
+ * Send AUDIOFOCUS_LOSS to a specific stack entry.
+ * Note this method is supporting an external API, and is restricted to LOSS in order to
+ * prevent allowing the stack to be in an invalid state (e.g. entry inside stack has focus)
+ * @param focusLoser the stack entry that is exiting the stack through a focus loss
+ * @return false if the focusLoser wasn't found in the stack, true otherwise
+ * @see AudioPolicy#sendFocusLoss(AudioFocusInfo)
+ */
+ boolean sendFocusLoss(@NonNull AudioFocusInfo focusLoser) {
+ synchronized (mAudioFocusLock) {
+ FocusRequester loserToRemove = null;
+ for (FocusRequester fr : mFocusStack) {
+ if (fr.getClientId().equals(focusLoser.getClientId())) {
+ fr.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null,
+ false /*forceDuck*/);
+ loserToRemove = fr;
+ break;
+ }
+ }
+ if (loserToRemove != null) {
+ mFocusStack.remove(loserToRemove);
+ loserToRemove.release();
+ return true;
+ }
+ }
+ return false;
+ }
+
@GuardedBy("mAudioFocusLock")
private void notifyTopOfAudioFocusStack() {
// notify the top of the stack it gained focus
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 0564e85..fdcf1fc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
+import android.Manifest;
import android.accounts.IAccountManager;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -170,6 +171,20 @@
@Override
public int onCommand(String cmd) {
+ switch (Binder.getCallingUid()) {
+ case Process.ROOT_UID:
+ case Process.SHELL_UID:
+ break;
+ default:
+ // This is called from a test and is allowed as non-shell with the right permission
+ if ("install-incremental".equals(cmd)) {
+ mContext.enforceCallingPermission(Manifest.permission.USE_SYSTEM_DATA_LOADERS,
+ "Caller missing USE_SYSTEM_DATA_LOADERS permission to use " + cmd);
+ } else {
+ throw new IllegalArgumentException("Caller must be root or shell");
+ }
+ }
+
if (cmd == null) {
return handleDefaultCommands(cmd);
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 111087f..a3b0e3e 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -1197,6 +1197,7 @@
@Nullable @UserIdInt Integer userId,
@NonNull Function<String, PackageStateInternal> pkgSettingFunction)
throws NameNotFoundException {
+ mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy);
synchronized (mLock) {
mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index eb68952..44d3623 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -167,7 +167,6 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
-import android.graphics.GraphicBuffer;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
@@ -4092,8 +4091,7 @@
// Make IME snapshot as trusted overlay
InputMonitor.setTrustedOverlayInputInfo(imeSurface, t, getDisplayId(),
"IME-snapshot-surface");
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(buffer);
- t.setBuffer(imeSurface, graphicBuffer);
+ t.setBuffer(imeSurface, buffer);
t.setColorSpace(mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB));
t.setRelativeLayer(imeSurface, activity.getSurfaceControl(), 1);
t.setPosition(imeSurface, mInputMethodWindow.getDisplayFrame().left,
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index d1d7cc6..d9dbf48 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.pm.SigningDetails
import android.content.pm.parsing.component.ParsedActivityImpl
import android.content.pm.parsing.component.ParsedIntentInfoImpl
import android.content.pm.verify.domain.DomainVerificationManager
@@ -26,6 +27,7 @@
import android.os.Build
import android.os.Process
import android.util.ArraySet
+import android.util.IndentingPrintWriter
import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.pm.parsing.pkg.AndroidPackage
@@ -46,6 +48,7 @@
import org.mockito.Mockito.anyLong
import org.mockito.Mockito.anyString
import org.mockito.Mockito.eq
+import org.mockito.Mockito.mock
import org.mockito.Mockito.verifyNoMoreInteractions
import java.util.UUID
import java.util.concurrent.atomic.AtomicBoolean
@@ -204,6 +207,14 @@
service(Type.QUERENT, "getInfo") {
getDomainVerificationInfo(it.targetPackageName)
},
+ service(Type.QUERENT, "printState") {
+ printState(mock(IndentingPrintWriter::class.java), null, null)
+ },
+ service(Type.QUERENT, "printStateInternal") {
+ printState(mock(IndentingPrintWriter::class.java), null, null) {
+ mockPkgState(it, UUID.randomUUID())
+ }
+ },
service(Type.VERIFIER, "setStatus") {
setDomainVerificationStatus(
it.targetDomainSetId,
@@ -311,6 +322,7 @@
}
)
}
+ whenever(signingDetails) { SigningDetails.UNKNOWN }
}
fun mockPkgState(packageName: String, domainSetId: UUID) =
@@ -327,6 +339,7 @@
}
}
whenever(isSystem) { false }
+ whenever(signingDetails) { SigningDetails.UNKNOWN }
}
}
@@ -794,8 +807,12 @@
}
val valueAsInt = value as? Int
- if (valueAsInt != null && valueAsInt == DomainVerificationManager.STATUS_OK) {
- throw AssertionError("Expected call to return false, was $value")
+ if (valueAsInt != null) {
+ if (valueAsInt == DomainVerificationManager.STATUS_OK) {
+ throw AssertionError("Expected call to return false, was $value")
+ }
+ } else {
+ throw AssertionError("Expected call to fail")
}
} catch (e: SecurityException) {
} catch (e: PackageManager.NameNotFoundException) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7d24b76..1ebf6cd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5953,6 +5953,7 @@
sDefaults.putInt(
KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG,
120000);
+ sDefaults.putAll(ImsServiceEntitlement.getDefaults());
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 866fd2c..ba95841 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -530,6 +530,8 @@
int RIL_REQUEST_GET_SLICING_CONFIG = 224;
int RIL_REQUEST_ENABLE_VONR = 225;
int RIL_REQUEST_IS_VONR_ENABLED = 226;
+ int RIL_REQUEST_SET_USAGE_SETTING = 227;
+ int RIL_REQUEST_GET_USAGE_SETTING = 228;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;