Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/Android.bp b/Android.bp
index aae78a0..b620634 100644
--- a/Android.bp
+++ b/Android.bp
@@ -568,6 +568,7 @@
"libcore-platform-compat-config",
"services-platform-compat-config",
"documents-ui-compat-config",
+ "calendar-provider-compat-config",
],
libs: ["framework-updatable-stubs-module_libs_api"],
static_libs: [
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d642f21..3ca5f0d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -732,6 +732,10 @@
public static final int SAMPLING_STRATEGY_BOOT_TIME_SAMPLING =
FrameworkStatsLog.RUNTIME_APP_OP_ACCESS__SAMPLING_STRATEGY__BOOT_TIME_SAMPLING;
+ /** @hide */
+ public static final int SAMPLING_STRATEGY_UNIFORM_OPS =
+ FrameworkStatsLog.RUNTIME_APP_OP_ACCESS__SAMPLING_STRATEGY__UNIFORM_OPS;
+
/**
* Strategies used for message sampling
* @hide
@@ -741,7 +745,8 @@
SAMPLING_STRATEGY_DEFAULT,
SAMPLING_STRATEGY_UNIFORM,
SAMPLING_STRATEGY_RARELY_USED,
- SAMPLING_STRATEGY_BOOT_TIME_SAMPLING
+ SAMPLING_STRATEGY_BOOT_TIME_SAMPLING,
+ SAMPLING_STRATEGY_UNIFORM_OPS
})
public @interface SamplingStrategy {}
@@ -8350,7 +8355,7 @@
* @hide
*/
private static boolean isCollectingStackTraces() {
- if (sConfig.getSampledOpCode() == OP_NONE &&
+ if (sConfig.getSampledOpCode() == OP_NONE && sConfig.getAcceptableLeftDistance() == 0 &&
sConfig.getExpirationTimeSinceBootMillis() >= SystemClock.elapsedRealtime()) {
return false;
}
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 4b0d2f8..bca6f39 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -175,14 +175,33 @@
*
* Caching can be disabled completely by initializing {@code sEnabled} to false and rebuilding.
*
+ * To test a binder cache, create one or more tests that exercise the binder method. This
+ * should be done twice: once with production code and once with a special image that sets
+ * {@code DEBUG} and {@code VERIFY} true. In the latter case, verify that no cache
+ * inconsistencies are reported. If a cache inconsistency is reported, however, it might be a
+ * false positive. This happens if the server side data can be read and written non-atomically
+ * with respect to cache invalidation.
+ *
* @param <Query> The class used to index cache entries: must be hashable and comparable
* @param <Result> The class holding cache entries; use a boxed primitive if possible
*
* {@hide}
*/
public abstract class PropertyInvalidatedCache<Query, Result> {
- private static final long NONCE_UNSET = 0;
- private static final long NONCE_DISABLED = -1;
+ /**
+ * Reserved nonce values. The code is written assuming that these
+ * values are contiguous.
+ */
+ private static final int NONCE_UNSET = 0;
+ private static final int NONCE_DISABLED = 1;
+ private static final int NONCE_CORKED = 2;
+ private static final int NONCE_RESERVED = NONCE_CORKED + 1;
+
+ /**
+ * The names of the nonces
+ */
+ private static final String[] sNonceName =
+ new String[]{ "unset", "disabled", "corked" };
private static final String TAG = "PropertyInvalidatedCache";
private static final boolean DEBUG = false;
@@ -195,11 +214,28 @@
@GuardedBy("mLock")
private long mMisses = 0;
+ @GuardedBy("mLock")
+ private long mMissDisabled[] = new long[]{ 0, 0, 0 };
+
+ @GuardedBy("mLock")
+ private long mMissOverflow = 0;
+
+ @GuardedBy("mLock")
+ private long mHighWaterMark = 0;
+
// Most invalidation is done in a static context, so the counters need to be accessible.
@GuardedBy("sCorkLock")
private static final HashMap<String, Long> sInvalidates = new HashMap<>();
/**
+ * Record the number of invalidate or cork calls that were nops because
+ * the cache was already corked. This is static because invalidation is
+ * done in a static context.
+ */
+ @GuardedBy("sCorkLock")
+ private static final HashMap<String, Long> sCorkedInvalidates = new HashMap<>();
+
+ /**
* If sEnabled is false then all cache operations are stubbed out. Set
* it to false inside test processes.
*/
@@ -271,7 +307,15 @@
true /* LRU access order */) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
- return size() > maxEntries;
+ final int size = size();
+ if (size > mHighWaterMark) {
+ mHighWaterMark = size;
+ }
+ if (size > maxEntries) {
+ mMissOverflow++;
+ return true;
+ }
+ return false;
}
};
synchronized (sCorkLock) {
@@ -363,14 +407,21 @@
// Let access to mDisabled race: it's atomic anyway.
long currentNonce = (!isDisabledLocal()) ? getCurrentNonce() : NONCE_DISABLED;
for (;;) {
- if (currentNonce == NONCE_DISABLED || currentNonce == NONCE_UNSET) {
+ if (currentNonce == NONCE_DISABLED || currentNonce == NONCE_UNSET ||
+ currentNonce == NONCE_CORKED) {
+ if (!mDisabled) {
+ // Do not bother collecting statistics if the cache is
+ // locally disabled.
+ synchronized (mLock) {
+ mMissDisabled[(int) currentNonce]++;
+ }
+ }
+
if (DEBUG) {
if (!mDisabled) {
Log.d(TAG, String.format(
"cache %s %s for %s",
- cacheName(),
- currentNonce == NONCE_DISABLED ? "disabled" : "unset",
- queryToString(query)));
+ cacheName(), sNonceName[(int) currentNonce], queryToString(query)));
}
}
return recompute(query);
@@ -383,10 +434,10 @@
if (cachedResult != null) mHits++;
} else {
if (DEBUG) {
- Log.d(TAG,
- String.format("clearing cache %s because nonce changed [%s] -> [%s]",
- cacheName(),
- mLastSeenNonce, currentNonce));
+ Log.d(TAG, String.format(
+ "clearing cache %s of %d entries because nonce changed [%s] -> [%s]",
+ cacheName(), mCache.size(),
+ mLastSeenNonce, currentNonce));
}
mCache.clear();
mLastSeenNonce = currentNonce;
@@ -517,6 +568,8 @@
if (DEBUG) {
Log.d(TAG, "ignoring invalidation due to cork: " + name);
}
+ final long count = sCorkedInvalidates.getOrDefault(name, (long) 0);
+ sCorkedInvalidates.put(name, count + 1);
return;
}
invalidateCacheLocked(name);
@@ -538,7 +591,7 @@
long newValue;
do {
newValue = NoPreloadHolder.next();
- } while (newValue == NONCE_UNSET || newValue == NONCE_DISABLED);
+ } while (newValue >= 0 && newValue < NONCE_RESERVED);
final String newValueString = Long.toString(newValue);
if (DEBUG) {
Log.d(TAG,
@@ -567,13 +620,21 @@
* @param name Name of the cache-key property to cork
*/
public static void corkInvalidations(@NonNull String name) {
+ if (!sEnabled) {
+ if (DEBUG) {
+ Log.w(TAG, String.format(
+ "cache cork %s suppressed", name));
+ }
+ return;
+ }
+
synchronized (sCorkLock) {
int numberCorks = sCorks.getOrDefault(name, 0);
if (DEBUG) {
Log.d(TAG, String.format("corking %s: numberCorks=%s", name, numberCorks));
}
- // If we're the first ones to cork this cache, set the cache to the unset state so
+ // If we're the first ones to cork this cache, set the cache to the corked state so
// existing caches talk directly to their services while we've corked updates.
// Make sure we don't clobber a disabled cache value.
@@ -584,8 +645,11 @@
if (numberCorks == 0) {
final long nonce = SystemProperties.getLong(name, NONCE_UNSET);
if (nonce != NONCE_UNSET && nonce != NONCE_DISABLED) {
- SystemProperties.set(name, Long.toString(NONCE_UNSET));
+ SystemProperties.set(name, Long.toString(NONCE_CORKED));
}
+ } else {
+ final long count = sCorkedInvalidates.getOrDefault(name, (long) 0);
+ sCorkedInvalidates.put(name, count + 1);
}
sCorks.put(name, numberCorks + 1);
if (DEBUG) {
@@ -602,6 +666,14 @@
* @param name Name of the cache-key property to uncork
*/
public static void uncorkInvalidations(@NonNull String name) {
+ if (!sEnabled) {
+ if (DEBUG) {
+ Log.w(TAG, String.format(
+ "cache uncork %s suppressed", name));
+ }
+ return;
+ }
+
synchronized (sCorkLock) {
int numberCorks = sCorks.getOrDefault(name, 0);
if (DEBUG) {
@@ -729,8 +801,9 @@
boolean nonceChanged = (getCurrentNonce() != mLastSeenNonce);
if (!nonceChanged && !debugCompareQueryResults(proposedResult, resultToCompare)) {
Log.e(TAG, String.format(
- "cache %s inconsistent for %s",
- cacheName(), queryToString(query)));
+ "cache %s inconsistent for %s is %s should be %s",
+ cacheName(), queryToString(query),
+ proposedResult, resultToCompare));
}
// Always return the "true" result in verification mode.
return resultToCompare;
@@ -784,18 +857,23 @@
private void dumpContents(PrintWriter pw, String[] args) {
long invalidateCount;
-
+ long corkedInvalidates;
synchronized (sCorkLock) {
invalidateCount = sInvalidates.getOrDefault(mPropertyName, (long) 0);
+ corkedInvalidates = sCorkedInvalidates.getOrDefault(mPropertyName, (long) 0);
}
synchronized (mLock) {
pw.println(String.format(" Cache Property Name: %s", cacheName()));
- pw.println(String.format(" Hits: %d, Misses: %d, Invalidates: %d",
- mHits, mMisses, invalidateCount));
+ pw.println(String.format(" Hits: %d, Misses: %d, Invalidates: %d, Overflows: %d",
+ mHits, mMisses, invalidateCount, mMissOverflow));
+ pw.println(String.format(" Miss-corked: %d, Miss-unset: %d, Miss-other: %d," +
+ " CorkedInvalidates: %d",
+ mMissDisabled[NONCE_CORKED], mMissDisabled[NONCE_UNSET],
+ mMissDisabled[NONCE_DISABLED], corkedInvalidates));
pw.println(String.format(" Last Observed Nonce: %d", mLastSeenNonce));
- pw.println(String.format(" Current Size: %d, Max Size: %d",
- mCache.entrySet().size(), mMaxEntries));
+ pw.println(String.format(" Current Size: %d, Max Size: %d, HW Mark: %d",
+ mCache.size(), mMaxEntries, mHighWaterMark));
pw.println(String.format(" Enabled: %s", mDisabled ? "false" : "true"));
Set<Map.Entry<Query, Result>> cacheEntries = mCache.entrySet();
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 31da83a..6922072 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -308,7 +308,7 @@
false /* isScreenRound */,
false /* alwaysConsumeSystemBars */, null /* displayCutout */,
LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
- 0 /* legacySystemUiFlags */, typeSideMap)
+ 0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, typeSideMap)
.getInsets(mTypes);
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index a679b37..c383bc7 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -501,6 +501,7 @@
private PendingControlRequest mPendingImeControlRequest;
private int mLastLegacySoftInputMode;
+ private int mLastLegacyWindowFlags;
private int mLastLegacySystemUiFlags;
private DisplayCutout mLastDisplayCutout;
private boolean mStartingAnimation;
@@ -569,8 +570,8 @@
WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
- mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags,
- null /* typeSideMap */);
+ mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacyWindowFlags,
+ mLastLegacySystemUiFlags, null /* typeSideMap */);
mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims);
if (DEBUG) {
for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) {
@@ -706,13 +707,14 @@
@VisibleForTesting
public WindowInsets calculateInsets(boolean isScreenRound,
boolean alwaysConsumeSystemBars, DisplayCutout cutout,
- int legacySoftInputMode, int legacySystemUiFlags) {
+ int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags) {
mLastLegacySoftInputMode = legacySoftInputMode;
+ mLastLegacyWindowFlags = legacyWindowFlags;
mLastLegacySystemUiFlags = legacySystemUiFlags;
mLastDisplayCutout = cutout;
mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
isScreenRound, alwaysConsumeSystemBars, cutout,
- legacySoftInputMode, legacySystemUiFlags,
+ legacySoftInputMode, legacyWindowFlags, legacySystemUiFlags,
null /* typeSideMap */);
return mLastInsets;
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 91e75911..6b0b509 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -22,13 +22,14 @@
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
-import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.indexOf;
import static android.view.WindowInsets.Type.isVisibleInsetsType;
+import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -38,7 +39,6 @@
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
@@ -171,7 +171,7 @@
*/
public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState,
boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout,
- int legacySoftInputMode, int legacySystemUiFlags,
+ int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
Insets[] typeInsetsMap = new Insets[Type.SIZE];
Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
@@ -218,10 +218,17 @@
}
}
final int softInputAdjustMode = legacySoftInputMode & SOFT_INPUT_MASK_ADJUST;
+
+ @InsetsType int compatInsetsTypes = systemBars() | displayCutout();
+ if (softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE) {
+ compatInsetsTypes |= ime();
+ }
+ if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
+ compatInsetsTypes &= ~statusBars();
+ }
+
return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
- alwaysConsumeSystemBars, cutout, softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE
- ? systemBars() | displayCutout() | ime()
- : systemBars() | displayCutout(),
+ alwaysConsumeSystemBars, cutout, compatInsetsTypes,
sNewInsetsMode == NEW_INSETS_MODE_FULL
&& (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f2cec25..fe6f33d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2257,7 +2257,8 @@
mLastWindowInsets = mInsetsController.calculateInsets(
mContext.getResources().getConfiguration().isScreenRound(),
mAttachInfo.mAlwaysConsumeSystemBars, mPendingDisplayCutout.get(),
- mWindowAttributes.softInputMode, (mWindowAttributes.systemUiVisibility
+ mWindowAttributes.softInputMode, mWindowAttributes.flags,
+ (mWindowAttributes.systemUiVisibility
| mWindowAttributes.subtreeSystemUiVisibility));
Rect visibleInsets = mInsetsController.calculateVisibleInsets(
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 4d6b72f..5e94758 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,7 +17,6 @@
package android.view;
-import static android.view.WindowInsets.Type.CAPTION_BAR;
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.IME;
@@ -95,7 +94,7 @@
private final boolean mStableInsetsConsumed;
private final boolean mDisplayCutoutConsumed;
- private final int mCompatInsetTypes;
+ private final int mCompatInsetsTypes;
private final boolean mCompatIgnoreVisibility;
/**
@@ -150,8 +149,8 @@
@Nullable Insets[] typeMaxInsetsMap,
boolean[] typeVisibilityMap,
boolean isRound,
- boolean alwaysConsumeSystemBars, DisplayCutout displayCutout, int compatInsetTypes,
- boolean compatIgnoreVisibility) {
+ boolean alwaysConsumeSystemBars, DisplayCutout displayCutout,
+ @InsetsType int compatInsetsTypes, boolean compatIgnoreVisibility) {
mSystemWindowInsetsConsumed = typeInsetsMap == null;
mTypeInsetsMap = mSystemWindowInsetsConsumed
? new Insets[SIZE]
@@ -165,7 +164,7 @@
mTypeVisibilityMap = typeVisibilityMap;
mIsRound = isRound;
mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
- mCompatInsetTypes = compatInsetTypes;
+ mCompatInsetsTypes = compatInsetsTypes;
mCompatIgnoreVisibility = compatIgnoreVisibility;
mDisplayCutoutConsumed = displayCutout == null;
@@ -183,7 +182,7 @@
src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
src.mTypeVisibilityMap, src.mIsRound,
src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src),
- src.mCompatInsetTypes,
+ src.mCompatInsetsTypes,
src.mCompatIgnoreVisibility);
}
@@ -310,11 +309,11 @@
@NonNull
public Insets getSystemWindowInsets() {
Insets result = mCompatIgnoreVisibility
- ? getInsetsIgnoringVisibility(mCompatInsetTypes & ~ime())
- : getInsets(mCompatInsetTypes);
+ ? getInsetsIgnoringVisibility(mCompatInsetsTypes & ~ime())
+ : getInsets(mCompatInsetsTypes);
// We can't query max insets for IME, so we need to add it manually after.
- if ((mCompatInsetTypes & ime()) != 0 && mCompatIgnoreVisibility) {
+ if ((mCompatInsetsTypes & ime()) != 0 && mCompatIgnoreVisibility) {
result = Insets.max(result, getInsets(ime()));
}
return result;
@@ -503,7 +502,7 @@
mTypeVisibilityMap,
mIsRound, mAlwaysConsumeSystemBars,
null /* displayCutout */,
- mCompatInsetTypes, mCompatIgnoreVisibility);
+ mCompatInsetsTypes, mCompatIgnoreVisibility);
}
@@ -554,7 +553,7 @@
mTypeVisibilityMap,
mIsRound, mAlwaysConsumeSystemBars,
displayCutoutCopyConstructorArgument(this),
- mCompatInsetTypes, mCompatIgnoreVisibility);
+ mCompatInsetsTypes, mCompatIgnoreVisibility);
}
// TODO(b/119190588): replace @code with @link below
@@ -627,7 +626,7 @@
@Deprecated
@NonNull
public Insets getStableInsets() {
- return getInsets(mTypeMaxInsetsMap, mCompatInsetTypes);
+ return getInsets(mTypeMaxInsetsMap, mCompatInsetsTypes);
}
/**
@@ -939,7 +938,7 @@
: mDisplayCutout == null
? DisplayCutout.NO_CUTOUT
: mDisplayCutout.inset(left, top, right, bottom),
- mCompatInsetTypes, mCompatIgnoreVisibility);
+ mCompatInsetsTypes, mCompatIgnoreVisibility);
}
@Override
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 28a18da..2fe7c02 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -276,7 +276,7 @@
if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
isScreenRound, alwaysConsumeSystemBars, displayCutout.get(),
- SOFT_INPUT_ADJUST_NOTHING,
+ SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
SYSTEM_UI_FLAG_VISIBLE, null /* typeSideMap */);
} else {
return new WindowInsets.Builder()
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index bfcf52a..eb69525 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -86,7 +86,7 @@
false,
new DisplayCutout(
Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
- SOFT_INPUT_ADJUST_RESIZE, 0);
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mImeConsumer = (ImeInsetsSourceConsumer) mController.getSourceConsumer(ITYPE_IME);
});
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index c36f106..801cd4d 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -165,7 +165,7 @@
false,
new DisplayCutout(
Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
- SOFT_INPUT_ADJUST_RESIZE, 0);
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mController.onFrameChanged(new Rect(0, 0, 100, 100));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 5260ef8..c7d835c 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -29,6 +29,7 @@
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -77,7 +78,7 @@
mState.getSource(ITYPE_IME).setVisible(true);
SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap);
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, typeSideMap);
assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
@@ -96,7 +97,7 @@
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, null);
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null);
assertEquals(100, insets.getStableInsetBottom());
assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars()));
assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
@@ -115,7 +116,7 @@
mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -131,7 +132,7 @@
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, null);
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
assertEquals(100, insets.getInsets(ime()).bottom);
assertTrue(insets.isVisible(ime()));
@@ -147,11 +148,28 @@
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
SYSTEM_UI_FLAG_LAYOUT_STABLE, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING,
+ DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
+ 0 /* legacySystemUiFlags */, null);
+ assertEquals(0, insets.getSystemWindowInsetTop());
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_systemUiFlagLayoutStable_windowFlagFullscreen() {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN,
+ SYSTEM_UI_FLAG_LAYOUT_STABLE, null);
+ assertEquals(0, insets.getSystemWindowInsetTop());
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
0 /* legacySystemUiFlags */, null);
assertEquals(0, insets.getSystemWindowInsetTop());
}
@@ -195,7 +213,7 @@
mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -211,7 +229,7 @@
mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -226,7 +244,7 @@
mState.getSource(ITYPE_IME).setVisible(true);
mState.removeSource(ITYPE_IME);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, null);
+ DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c710bed..0679142 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -198,6 +198,8 @@
<permission name="android.permission.MANAGE_USERS" />
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
+ <permission name="android.permission.LOG_COMPAT_CHANGE" />
+ <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
</privapp-permissions>
<privapp-permissions package="com.android.providers.contacts">
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
index de5ed54..5c87d30 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
@@ -283,5 +283,50 @@
String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
transcode(testVideoName, transcodedVideoName);
- }*/
+ } */
+
+ @Test
+ public void testBenchmarkingHEVCToAVCWith107FramesWithoutAudio() throws Exception {
+ String videoNameWithoutExtension = "video_1920x1080_107frame_hevc_4Mbps_30fps";
+ String testVideoName = videoNameWithoutExtension + ".mp4";
+ String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+ transcode(testVideoName, transcodedVideoName);
+ }
+
+ @Test
+ public void testBenchmarkingHEVCToAVCWith928FramesWithoutAudio() throws Exception {
+ String videoNameWithoutExtension = "video_1920x1080_928frame_hevc_4Mbps_30fps";
+ String testVideoName = videoNameWithoutExtension + ".mp4";
+ String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+ transcode(testVideoName, transcodedVideoName);
+ }
+
+ @Test
+ public void testBenchmarkingHEVCToAVCWith1863FramesWithoutAudio() throws Exception {
+ String videoNameWithoutExtension = "video_1920x1080_1863frame_hevc_4Mbps_30fps";
+ String testVideoName = videoNameWithoutExtension + ".mp4";
+ String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+ transcode(testVideoName, transcodedVideoName);
+ }
+
+ @Test
+ public void testBenchmarkingHEVCToAVCWith3863FramesWithoutAudio() throws Exception {
+ String videoNameWithoutExtension = "video_1920x1080_3863frame_hevc_4Mbps_30fps";
+ String testVideoName = videoNameWithoutExtension + ".mp4";
+ String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+ transcode(testVideoName, transcodedVideoName);
+ }
+
+ @Test
+ public void testBenchmarkingHEVCToAVCWith9374FramesWithoutAudio() throws Exception {
+ String videoNameWithoutExtension = "video_1920x1080_9374frame_hevc_4Mbps_30fps";
+ String testVideoName = videoNameWithoutExtension + ".mp4";
+ String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
+
+ transcode(testVideoName, transcodedVideoName);
+ }
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 6ecf303..dfc4758 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -140,7 +140,8 @@
"testables",
"truth-prebuilt",
"dagger2",
- "jsr330"
+ "jsr330",
+ "WindowManager-Shell",
],
libs: [
"android.test.runner",
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 2a2ba1b..14097b1 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -39,4 +39,6 @@
-keep public class * extends com.android.systemui.SystemUI {
public <init>(android.content.Context);
-}
\ No newline at end of file
+}
+
+-keep class com.android.wm.shell.*
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config_tv.xml b/packages/SystemUI/res/values/config_tv.xml
index ffd58dc..d8c9428 100644
--- a/packages/SystemUI/res/values/config_tv.xml
+++ b/packages/SystemUI/res/values/config_tv.xml
@@ -22,4 +22,13 @@
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
when the PIP menu is shown in center. -->
<string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
+
+ <!-- Whether to enable microphone disclosure indicator
+ (com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar). -->
+ <bool name="audio_recording_disclosure_enabled">true</bool>
+
+ <!-- Whether the indicator should expand and show the recording application's label.
+ When disabled (false) the "minimized" indicator would appear on the screen whenever an
+ application is recording, but will not reveal to the user what application this is. -->
+ <bool name="audio_recording_disclosure_reveal_packages">false</bool>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 1354585..434bf49 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -207,12 +207,6 @@
/** Whether or not the BubbleStackView has been added to the WindowManager. */
private boolean mAddedToWindowManager = false;
- /**
- * Value from {@link NotificationShadeWindowController#getForceHasTopUi()} when we forced top UI
- * due to expansion. We'll restore this value when the stack collapses.
- */
- private boolean mHadTopUi = false;
-
// Listens to user switch so bubbles can be saved and restored.
private final NotificationLockscreenUserManager mNotifUserManager;
@@ -1304,7 +1298,7 @@
// Collapsing? Do this first before remaining steps.
if (update.expandedChanged && !update.expanded) {
mStackView.setExpanded(false);
- mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
+ mNotificationShadeWindowController.setRequestTopUi(false, TAG);
}
// Do removals, if any.
@@ -1394,8 +1388,7 @@
if (update.expandedChanged && update.expanded) {
if (mStackView != null) {
mStackView.setExpanded(true);
- mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
- mNotificationShadeWindowController.setForceHasTopUi(true);
+ mNotificationShadeWindowController.setRequestTopUi(true, TAG);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index b2e9164..ef51abb 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -2129,7 +2129,6 @@
private boolean mShowing;
private float mScrimAlpha;
private ResetOrientationData mResetOrientationData;
- private boolean mHadTopUi;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final NotificationShadeDepthController mDepthController;
private final SysUiState mSysUiState;
@@ -2397,8 +2396,7 @@
public void show() {
super.show();
mShowing = true;
- mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
- mNotificationShadeWindowController.setForceHasTopUi(true);
+ mNotificationShadeWindowController.setRequestTopUi(true, TAG);
mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true)
.commitUpdate(mContext.getDisplayId());
@@ -2499,7 +2497,7 @@
dismissOverflow(true);
dismissPowerOptions(true);
if (mControlsUiController != null) mControlsUiController.hide();
- mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
+ mNotificationShadeWindowController.setRequestTopUi(false, TAG);
mDepthController.updateGlobalDialogVisibility(0, null /* view */);
mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false)
.commitUpdate(mContext.getDisplayId());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index cdcfac8..d264af9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -84,7 +84,6 @@
private final Map<View, MenuItem> mMenuItemsByView = new ArrayMap<>();
private OnMenuEventListener mMenuListener;
private boolean mDismissRtl;
- private boolean mIsForeground;
private ValueAnimator mFadeAnimator;
private boolean mAnimating;
@@ -191,9 +190,7 @@
@Override
public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
mParent = (ExpandableNotificationRow) parent;
- createMenuViews(true /* resetState */,
- sbn != null && (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
- != 0);
+ createMenuViews(true /* resetState */);
}
@Override
@@ -237,8 +234,7 @@
// Menu hasn't been created yet, no need to do anything.
return;
}
- createMenuViews(!isMenuVisible() /* resetState */,
- (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
+ createMenuViews(!isMenuVisible() /* resetState */);
}
@Override
@@ -253,9 +249,7 @@
mParent.removeListener();
}
- private void createMenuViews(boolean resetState, final boolean isForeground) {
- mIsForeground = isForeground;
-
+ private void createMenuViews(boolean resetState) {
final Resources res = mContext.getResources();
mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -266,7 +260,7 @@
SHOW_NOTIFICATION_SNOOZE, 0) == 1;
// Construct the menu items based on the notification
- if (!isForeground && showSnooze) {
+ if (showSnooze) {
// Only show snooze for non-foreground notifications, and if the setting is on
mSnoozeItem = createSnoozeItem(mContext);
}
@@ -283,7 +277,7 @@
mInfoItem = createInfoItem(mContext);
}
- if (!isForeground && showSnooze) {
+ if (showSnooze) {
mRightMenuItems.add(mSnoozeItem);
}
mRightMenuItems.add(mInfoItem);
@@ -789,7 +783,7 @@
public void setDismissRtl(boolean dismissRtl) {
mDismissRtl = dismissRtl;
if (mMenuContainer != null) {
- createMenuViews(true, mIsForeground);
+ createMenuViews(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 07eaaa1..bf85852 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -19,8 +19,6 @@
import static com.android.systemui.statusbar.phone.HeadsUpAppearanceController.CONTENT_FADE_DELAY;
import static com.android.systemui.statusbar.phone.HeadsUpAppearanceController.CONTENT_FADE_DURATION;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -807,6 +805,7 @@
} else {
super.applyToView(view);
}
+ sTempProperties.setAnimationEndAction(null);
boolean inShelf = iconAppearAmount == 1.0f;
icon.setIsInShelf(inShelf);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index 5164440..bc73be1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -61,6 +61,8 @@
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import java.util.function.Consumer;
import javax.inject.Inject;
@@ -432,7 +434,7 @@
}
private void applyHasTopUi(State state) {
- mHasTopUiChanged = state.mForceHasTopUi || isExpanded(state);
+ mHasTopUiChanged = !state.mComponentsForcingTopUi.isEmpty() || isExpanded(state);
}
private void applyNotTouchable(State state) {
@@ -635,12 +637,17 @@
apply(mCurrentState);
}
- public boolean getForceHasTopUi() {
- return mCurrentState.mForceHasTopUi;
- }
-
- public void setForceHasTopUi(boolean forceHasTopUi) {
- mCurrentState.mForceHasTopUi = forceHasTopUi;
+ /**
+ * SystemUI may need top-ui to avoid jank when performing animations. After the
+ * animation is performed, the component should remove itself from the list of features that
+ * are forcing SystemUI to be top-ui.
+ */
+ public void setRequestTopUi(boolean requestTopUi, String componentTag) {
+ if (requestTopUi) {
+ mCurrentState.mComponentsForcingTopUi.add(componentTag);
+ } else {
+ mCurrentState.mComponentsForcingTopUi.remove(componentTag);
+ }
apply(mCurrentState);
}
@@ -663,7 +670,7 @@
boolean mBackdropShowing;
boolean mWallpaperSupportsAmbientMode;
boolean mNotTouchable;
- boolean mForceHasTopUi;
+ Set<String> mComponentsForcingTopUi = new HashSet<>();
/**
* The {@link StatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c14a5ef..b65bd45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -213,7 +213,6 @@
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -2397,18 +2396,31 @@
new WirelessChargingAnimation.Callback() {
@Override
public void onAnimationStarting() {
+ mNotificationShadeWindowController.setRequestTopUi(true, TAG);
CrossFadeHelper.fadeOut(mNotificationPanelViewController.getView(), 1);
}
@Override
public void onAnimationEnded() {
CrossFadeHelper.fadeIn(mNotificationPanelViewController.getView());
+ mNotificationShadeWindowController.setRequestTopUi(false, TAG);
}
}, mDozing).show(animationDelay);
} else {
// workspace
WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
- transmittingBatteryLevel, batteryLevel, null, false).show(animationDelay);
+ transmittingBatteryLevel, batteryLevel,
+ new WirelessChargingAnimation.Callback() {
+ @Override
+ public void onAnimationStarting() {
+ mNotificationShadeWindowController.setRequestTopUi(true, TAG);
+ }
+
+ @Override
+ public void onAnimationEnded() {
+ mNotificationShadeWindowController.setRequestTopUi(false, TAG);
+ }
+ }, false).show(animationDelay);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 53ac657..9c3395f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -79,7 +79,7 @@
/**
* Host for the remote input.
*/
-public class RemoteInputView extends LinearLayout implements View.OnClickListener, TextWatcher {
+public class RemoteInputView extends LinearLayout implements View.OnClickListener {
private static final String TAG = "RemoteInput";
@@ -88,6 +88,8 @@
public final Object mToken = new Object();
+ private final SendButtonTextWatcher mTextWatcher;
+ private final TextView.OnEditorActionListener mEditorActionHandler;
private RemoteEditText mEditText;
private ImageButton mSendButton;
private ProgressBar mProgressBar;
@@ -113,6 +115,8 @@
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mTextWatcher = new SendButtonTextWatcher();
+ mEditorActionHandler = new EditorActionHandler();
mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class);
mStatusBarManagerService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -128,30 +132,7 @@
mSendButton.setOnClickListener(this);
mEditText = (RemoteEditText) getChildAt(0);
- mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- final boolean isSoftImeEvent = event == null
- && (actionId == EditorInfo.IME_ACTION_DONE
- || actionId == EditorInfo.IME_ACTION_NEXT
- || actionId == EditorInfo.IME_ACTION_SEND);
- final boolean isKeyboardEnterKey = event != null
- && KeyEvent.isConfirmKey(event.getKeyCode())
- && event.getAction() == KeyEvent.ACTION_DOWN;
-
- if (isSoftImeEvent || isKeyboardEnterKey) {
- if (mEditText.length() > 0) {
- sendRemoteInput(prepareRemoteInputFromText());
- }
- // Consume action to prevent IME from closing.
- return true;
- }
- return false;
- }
- });
- mEditText.addTextChangedListener(this);
mEditText.setInnerFocusable(false);
- mEditText.mRemoteInputView = this;
}
protected Intent prepareRemoteInputFromText() {
@@ -292,6 +273,9 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mEditText.mRemoteInputView = this;
+ mEditText.setOnEditorActionListener(mEditorActionHandler);
+ mEditText.addTextChangedListener(mTextWatcher);
if (mEntry.getRow().isChangingPosition()) {
if (getVisibility() == VISIBLE && mEditText.isFocusable()) {
mEditText.requestFocus();
@@ -302,6 +286,9 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ mEditText.removeTextChangedListener(mTextWatcher);
+ mEditText.setOnEditorActionListener(null);
+ mEditText.mRemoteInputView = null;
if (mEntry.getRow().isChangingPosition() || isTemporarilyDetached()) {
return;
}
@@ -412,17 +399,6 @@
mSendButton.setEnabled(mEditText.getText().length() != 0);
}
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
-
- @Override
- public void afterTextChanged(Editable s) {
- updateSendButton();
- }
-
public void close() {
mEditText.defocusIfNeeded(false /* animated */);
}
@@ -545,6 +521,45 @@
return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
}
+ /** Handler for button click on send action in IME. */
+ private class EditorActionHandler implements TextView.OnEditorActionListener {
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ final boolean isSoftImeEvent = event == null
+ && (actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT
+ || actionId == EditorInfo.IME_ACTION_SEND);
+ final boolean isKeyboardEnterKey = event != null
+ && KeyEvent.isConfirmKey(event.getKeyCode())
+ && event.getAction() == KeyEvent.ACTION_DOWN;
+
+ if (isSoftImeEvent || isKeyboardEnterKey) {
+ if (mEditText.length() > 0) {
+ sendRemoteInput(prepareRemoteInputFromText());
+ }
+ // Consume action to prevent IME from closing.
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /** Observes text change events and updates the visibility of the send button accordingly. */
+ private class SendButtonTextWatcher implements TextWatcher {
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ updateSendButton();
+ }
+ }
+
/**
* An EditText that changes appearance based on whether it's focusable and becomes
* un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -599,7 +614,7 @@
if (!focused) {
defocusIfNeeded(true /* animate */);
}
- if (!mRemoteInputView.mRemoved) {
+ if (mRemoteInputView != null && !mRemoteInputView.mRemoved) {
mLightBarController.setDirectReplying(focused);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 6bc0565..c0602762 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -26,6 +26,7 @@
import android.os.UserHandle;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.statusbar.CommandQueue;
@@ -72,6 +73,11 @@
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
+
+ if (mContext.getResources().getBoolean(R.bool.audio_recording_disclosure_enabled)) {
+ // Creating AudioRecordingDisclosureBar and just letting it run
+ new AudioRecordingDisclosureBar(mContext);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 36e360d..8e4e123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -112,6 +112,13 @@
*/
private final AudioActivityObserver[] mAudioActivityObservers;
/**
+ * Whether the indicator should expand and show the recording application's label.
+ * If disabled ({@code false}) the "minimized" ({@link #STATE_MINIMIZED}) indicator would appear
+ * on the screen whenever an application is recording, but will not reveal to the user what
+ * application this is.
+ */
+ private final boolean mRevealRecordingPackages;
+ /**
* Set of applications that we've notified the user about since the indicator came up. Meaning
* that if an application is in this list then at some point since the indicator came up, it
* was expanded showing this application's title.
@@ -137,6 +144,8 @@
public AudioRecordingDisclosureBar(Context context) {
mContext = context;
+ mRevealRecordingPackages = mContext.getResources().getBoolean(
+ R.bool.audio_recording_disclosure_reveal_packages);
mExemptPackages = new ArraySet<>(
Arrays.asList(mContext.getResources().getStringArray(
R.array.audio_recording_disclosure_exempt_apps)));
@@ -149,11 +158,6 @@
};
}
- private String[] getGlobalStringArray(String setting) {
- String result = Settings.Global.getString(mContext.getContentResolver(), setting);
- return TextUtils.isEmpty(result) ? new String[0] : result.split(",");
- }
-
@UiThread
@Override
public void onAudioActivityStateChange(boolean active, String packageName) {
@@ -190,7 +194,9 @@
break;
case STATE_MINIMIZED:
- expand(packageName);
+ if (mRevealRecordingPackages) {
+ expand(packageName);
+ }
break;
case STATE_DISAPPEARING:
@@ -228,9 +234,8 @@
@UiThread
private void show(String packageName) {
- final String label = getApplicationLabel(packageName);
if (DEBUG) {
- Log.d(TAG, "Showing indicator for " + packageName + " (" + label + ")...");
+ Log.d(TAG, "Showing indicator for " + packageName);
}
mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
@@ -247,18 +252,30 @@
mTextView = mTextsContainers.findViewById(R.id.text);
mBgEnd = mIndicatorView.findViewById(R.id.bg_end);
- // Swap background drawables depending on layout directions (both drawables have rounded
- // corners only on one side)
- if (mIsLtr) {
- mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
- mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
- } else {
- mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
- mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
- }
-
// Set up the notification text
- mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
+ if (mRevealRecordingPackages) {
+ // Swap background drawables depending on layout directions (both drawables have rounded
+ // corners only on one side)
+ if (mIsLtr) {
+ mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+ mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+ } else {
+ mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+ mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+ }
+
+ final String label = getApplicationLabel(packageName);
+ mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
+ } else {
+ mTextsContainers.setVisibility(View.GONE);
+ mIconContainerBg.setVisibility(View.GONE);
+ mTextView.setVisibility(View.GONE);
+ mBgEnd.setVisibility(View.GONE);
+ mTextsContainers = null;
+ mIconContainerBg = null;
+ mTextView = null;
+ mBgEnd = null;
+ }
// Initially change the visibility to INVISIBLE, wait until and receives the size and
// then animate it moving from "off" the screen correctly
@@ -296,7 +313,11 @@
@Override
public void onAnimationEnd(Animator animation) {
startPulsatingAnimation();
- onExpanded();
+ if (mRevealRecordingPackages) {
+ onExpanded();
+ } else {
+ onMinimized();
+ }
}
});
set.start();
@@ -321,6 +342,8 @@
@UiThread
private void expand(String packageName) {
+ assertRevealingRecordingPackages();
+
final String label = getApplicationLabel(packageName);
if (DEBUG) {
Log.d(TAG, "Expanding for " + packageName + " (" + label + ")...");
@@ -348,6 +371,8 @@
@UiThread
private void minimize() {
+ assertRevealingRecordingPackages();
+
if (DEBUG) Log.d(TAG, "Minimizing...");
final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth();
final AnimatorSet set = new AnimatorSet();
@@ -393,6 +418,8 @@
@UiThread
private void onExpanded() {
+ assertRevealingRecordingPackages();
+
if (DEBUG) Log.d(TAG, "Expanded");
mState = STATE_SHOWN;
@@ -404,11 +431,13 @@
if (DEBUG) Log.d(TAG, "Minimized");
mState = STATE_MINIMIZED;
- if (!mPendingNotificationPackages.isEmpty()) {
- // There is a new application that started recording, tell the user about it.
- expand(mPendingNotificationPackages.poll());
- } else {
- hideIndicatorIfNeeded();
+ if (mRevealRecordingPackages) {
+ if (!mPendingNotificationPackages.isEmpty()) {
+ // There is a new application that started recording, tell the user about it.
+ expand(mPendingNotificationPackages.poll());
+ } else {
+ hideIndicatorIfNeeded();
+ }
}
}
@@ -451,7 +480,14 @@
animator.start();
}
+ private String[] getGlobalStringArray(String setting) {
+ String result = Settings.Global.getString(mContext.getContentResolver(), setting);
+ return TextUtils.isEmpty(result) ? new String[0] : result.split(",");
+ }
+
private String getApplicationLabel(String packageName) {
+ assertRevealingRecordingPackages();
+
final PackageManager pm = mContext.getPackageManager();
final ApplicationInfo appInfo;
try {
@@ -461,4 +497,11 @@
}
return pm.getApplicationLabel(appInfo).toString();
}
+
+ private void assertRevealingRecordingPackages() {
+ if (!mRevealRecordingPackages) {
+ Log.e(TAG, "Not revealing recording packages",
+ DEBUG ? new RuntimeException("Should not be called") : null);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2eca00e..b323190 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -44,6 +44,7 @@
import static android.app.AppOpsManager.SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_RARELY_USED;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
+import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
@@ -5936,11 +5937,13 @@
int newLeftDistance = AppOpsManager.leftCircularDistance(opCode,
mSampledAppOpCode, _NUM_OP);
- if (mAcceptableLeftDistance < newLeftDistance) {
+ if (mAcceptableLeftDistance < newLeftDistance
+ && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) {
return;
}
- if (mAcceptableLeftDistance > newLeftDistance) {
+ if (mAcceptableLeftDistance > newLeftDistance
+ && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) {
mAcceptableLeftDistance = newLeftDistance;
mMessagesCollectedCount = 0.0f;
}
@@ -5978,13 +5981,13 @@
if (mSampledPackage == null) {
if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
mSamplingStrategy = SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
- resampleAppOpForPackageLocked(packageName);
+ resampleAppOpForPackageLocked(packageName, true);
}
} else if (mRarelyUsedPackages.contains(packageName)) {
mRarelyUsedPackages.remove(packageName);
if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
mSamplingStrategy = SAMPLING_STRATEGY_RARELY_USED;
- resampleAppOpForPackageLocked(packageName);
+ resampleAppOpForPackageLocked(packageName, true);
}
}
}
@@ -6001,16 +6004,22 @@
/** Resamples package and appop to watch from the list provided. */
private void resamplePackageAndAppOpLocked(@NonNull List<String> packageNames) {
if (!packageNames.isEmpty()) {
- mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM;
- resampleAppOpForPackageLocked(packageNames.get(
- ThreadLocalRandom.current().nextInt(packageNames.size())));
+ if (ThreadLocalRandom.current().nextFloat() < 0.5f) {
+ mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM;
+ resampleAppOpForPackageLocked(packageNames.get(
+ ThreadLocalRandom.current().nextInt(packageNames.size())), true);
+ } else {
+ mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM_OPS;
+ resampleAppOpForPackageLocked(packageNames.get(
+ ThreadLocalRandom.current().nextInt(packageNames.size())), false);
+ }
}
}
/** Resamples appop for the chosen package and initializes sampling state */
- private void resampleAppOpForPackageLocked(@NonNull String packageName) {
+ private void resampleAppOpForPackageLocked(@NonNull String packageName, boolean pickOp) {
mMessagesCollectedCount = 0.0f;
- mSampledAppOpCode = ThreadLocalRandom.current().nextInt(_NUM_OP);
+ mSampledAppOpCode = pickOp ? ThreadLocalRandom.current().nextInt(_NUM_OP) : OP_NONE;
mAcceptableLeftDistance = _NUM_OP;
mSampledPackage = packageName;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 265ef19..17b805f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -25546,7 +25546,8 @@
private void applyMimeGroupChanges(String packageName, String mimeGroup) {
if (mComponentResolver.updateMimeGroup(packageName, mimeGroup)) {
- clearPackagePreferredActivities(packageName, UserHandle.USER_ALL);
+ Binder.withCleanCallingIdentity(() ->
+ clearPackagePreferredActivities(packageName, UserHandle.USER_ALL));
}
mPmInternal.writeSettings(false);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f13dfdd..68445f6 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -615,8 +615,9 @@
static Rect getSystemBarInsets(Rect frame, InsetsState state) {
return state.calculateInsets(frame, null /* ignoringVisibilityState */,
false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
- null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacySystemUiFlags */,
- null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect();
+ null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacyWindowFlags */,
+ 0 /* legacySystemUiFlags */, null /* typeSideMap */).getInsets(
+ WindowInsets.Type.systemBars()).toRect();
}
void dump(PrintWriter pw, String prefix) {