summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java69
-rw-r--r--core/java/android/app/ClientTransactionHandler.java2
-rw-r--r--core/java/android/app/LocalActivityManager.java4
-rw-r--r--core/java/android/app/servertransaction/DestroyActivityItem.java2
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutor.java4
-rw-r--r--core/java/android/hardware/display/AmbientBrightnessDayStats.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityDisplay.java22
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java17
-rw-r--r--services/core/java/com/android/server/display/BrightnessTracker.java31
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java1
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsCollection.java1
-rw-r--r--services/core/java/com/android/server/pm/InstantAppRegistry.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowController.java32
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java43
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java67
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java76
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java25
-rw-r--r--services/java/com/android/server/SystemServer.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java9
-rw-r--r--tools/aapt/ResourceTable.cpp4
-rw-r--r--tools/aapt2/cmd/Link.cpp2
33 files changed, 349 insertions, 214 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ff970bf82a7a..5a6331919d76 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -167,9 +167,9 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.text.DateFormat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -223,7 +223,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private static final boolean REPORT_TO_ACTIVITY = true;
// Maximum number of recent tokens to maintain for debugging purposes
- private static final int MAX_RECENT_TOKENS = 10;
+ private static final int MAX_DESTROYED_ACTIVITIES = 10;
/**
* Denotes an invalid sequence number corresponding to a process state change.
@@ -257,7 +257,7 @@ public final class ActivityThread extends ClientTransactionHandler {
final H mH = new H();
final Executor mExecutor = new HandlerExecutor(mH);
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
- final ArrayDeque<Integer> mRecentTokens = new ArrayDeque<>();
+ final ArrayList<DestroyedActivityInfo> mRecentDestroyedActivities = new ArrayList<>();
// List of new activities (via ActivityRecord.nextIdle) that should
// be reported when next we idle.
@@ -340,6 +340,26 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ /**
+ * TODO(b/71506345): Remove this once bug is resolved.
+ */
+ private static final class DestroyedActivityInfo {
+ private final Integer mToken;
+ private final String mReason;
+ private final long mTime;
+
+ DestroyedActivityInfo(Integer token, String reason) {
+ mToken = token;
+ mReason = reason;
+ mTime = System.currentTimeMillis();
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "[token:" + mToken + " | time:" + mTime + " | reason:" + mReason
+ + "]");
+ }
+ }
+
// The lock of mProviderMap protects the following variables.
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
= new ArrayMap<ProviderKey, ProviderClientRecord>();
@@ -2164,14 +2184,28 @@ public final class ActivityThread extends ClientTransactionHandler {
@Override
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "mActivities:");
+ pw.println(prefix + "Activities:");
- for (ArrayMap.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
- pw.println(prefix + " [token:" + entry.getKey().hashCode() + " record:"
- + entry.getValue().toString() + "]");
+ if (!mActivities.isEmpty()) {
+ final Iterator<Map.Entry<IBinder, ActivityClientRecord>> activitiesIterator =
+ mActivities.entrySet().iterator();
+
+ while (activitiesIterator.hasNext()) {
+ final ArrayMap.Entry<IBinder, ActivityClientRecord> entry =
+ activitiesIterator.next();
+ pw.println(prefix + " [token:" + entry.getKey().hashCode() + " record:"
+ + entry.getValue().toString() + "]");
+ }
}
- pw.println(prefix + "mRecentTokens:" + mRecentTokens);
+ if (!mRecentDestroyedActivities.isEmpty()) {
+ pw.println(prefix + "Recent destroyed activities:");
+ for (int i = 0, size = mRecentDestroyedActivities.size(); i < size; i++) {
+ final DestroyedActivityInfo info = mRecentDestroyedActivities.get(i);
+ pw.print(prefix);
+ info.dump(pw, " ");
+ }
+ }
}
public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
@@ -2858,11 +2892,6 @@ public final class ActivityThread extends ClientTransactionHandler {
r.setState(ON_CREATE);
mActivities.put(r.token, r);
- mRecentTokens.push(r.token.hashCode());
-
- if (mRecentTokens.size() > MAX_RECENT_TOKENS) {
- mRecentTokens.removeLast();
- }
} catch (SuperNotCalledException e) {
throw e;
@@ -4419,7 +4448,7 @@ public final class ActivityThread extends ClientTransactionHandler {
/** Core implementation of activity destroy call. */
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
- int configChanges, boolean getNonConfigInstance) {
+ int configChanges, boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = mActivities.get(token);
Class<? extends Activity> activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
@@ -4471,6 +4500,12 @@ public final class ActivityThread extends ClientTransactionHandler {
r.setState(ON_DESTROY);
}
mActivities.remove(token);
+ mRecentDestroyedActivities.add(0, new DestroyedActivityInfo(token.hashCode(), reason));
+
+ final int recentDestroyedActivitiesSize = mRecentDestroyedActivities.size();
+ if (recentDestroyedActivitiesSize > MAX_DESTROYED_ACTIVITIES) {
+ mRecentDestroyedActivities.remove(recentDestroyedActivitiesSize - 1);
+ }
StrictMode.decrementExpectedActivityCount(activityClass);
return r;
}
@@ -4482,9 +4517,9 @@ public final class ActivityThread extends ClientTransactionHandler {
@Override
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
- boolean getNonConfigInstance) {
+ boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
- configChanges, getNonConfigInstance);
+ configChanges, getNonConfigInstance, reason);
if (r != null) {
cleanUpPendingRemoveWindows(r, finishing);
WindowManager wm = r.activity.getWindowManager();
@@ -4709,7 +4744,7 @@ public final class ActivityThread extends ClientTransactionHandler {
callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity");
}
- handleDestroyActivity(r.token, false, configChanges, true);
+ handleDestroyActivity(r.token, false, configChanges, true, "handleRelaunchActivity");
r.activity = null;
r.window = null;
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 114d18b9a996..310965e475b8 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -61,7 +61,7 @@ public abstract class ClientTransactionHandler {
/** Destroy the activity. */
public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
- boolean getNonConfigInstance);
+ boolean getNonConfigInstance, String reason);
/** Pause the activity. */
public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 1d3459534f0c..e297719f9e4c 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -380,7 +380,7 @@ public class LocalActivityManager {
}
if (localLOGV) Log.v(TAG, r.id + ": destroying");
mActivityThread.performDestroyActivity(r, finish, 0 /* configChanges */,
- false /* getNonConfigInstance */);
+ false /* getNonConfigInstance */, "LocalActivityManager::performDestroy");
r.activity = null;
r.window = null;
if (finish) {
@@ -645,7 +645,7 @@ public class LocalActivityManager {
LocalActivityRecord r = mActivityArray.get(i);
if (localLOGV) Log.v(TAG, r.id + ": destroying");
mActivityThread.performDestroyActivity(r, finishing, 0 /* configChanges */,
- false /* getNonConfigInstance */);
+ false /* getNonConfigInstance */, "LocalActivityManager::dispatchDestroy");
}
mActivities.clear();
mActivityArray.clear();
diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java
index cbcf6c750fed..48a79f79dae1 100644
--- a/core/java/android/app/servertransaction/DestroyActivityItem.java
+++ b/core/java/android/app/servertransaction/DestroyActivityItem.java
@@ -37,7 +37,7 @@ public class DestroyActivityItem extends ActivityLifecycleItem {
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
client.handleDestroyActivity(token, mFinished, mConfigChanges,
- false /* getNonConfigInstance */);
+ false /* getNonConfigInstance */, getDescription());
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 78b393a831f9..840fef80a5ff 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -194,7 +194,9 @@ public class TransactionExecutor {
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
- 0 /* configChanges */, false /* getNonConfigInstance */);
+ 0 /* configChanges */, false /* getNonConfigInstance */,
+ "performLifecycleSequence. cycling to:"
+ + mLifecycleSequence.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r.token, false /* start */);
diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
index 00f3c36d0361..1aa2557f92a2 100644
--- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java
+++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
@@ -47,6 +47,11 @@ public final class AmbientBrightnessDayStats implements Parcelable {
private final float[] mStats;
/**
+ * Initialize day stats from the given state. The time spent in each of the bucket is
+ * initialized to 0.
+ *
+ * @param localDate The date for which stats are being tracked
+ * @param bucketBoundaries Bucket boundaries used from creating the buckets from
* @hide
*/
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@@ -55,6 +60,11 @@ public final class AmbientBrightnessDayStats implements Parcelable {
}
/**
+ * Initialize day stats from the given state
+ *
+ * @param localDate The date for which stats are being tracked
+ * @param bucketBoundaries Bucket boundaries used from creating the buckets from
+ * @param stats Time spent in each of the buckets (in seconds)
* @hide
*/
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@@ -81,14 +91,26 @@ public final class AmbientBrightnessDayStats implements Parcelable {
mStats = stats;
}
+ /**
+ * @return The {@link LocalDate} for which brightness stats are being tracked.
+ */
public LocalDate getLocalDate() {
return mLocalDate;
}
+ /**
+ * @return Aggregated stats of time spent (in seconds) in various buckets.
+ */
public float[] getStats() {
return mStats;
}
+ /**
+ * Returns the bucket boundaries (in lux) used for creating buckets. For eg., if the bucket
+ * boundaries array is {b1, b2, b3}, the buckets will be [b1, b2), [b2, b3), [b3, inf).
+ *
+ * @return The list of bucket boundaries.
+ */
public float[] getBucketBoundaries() {
return mBucketBoundaries;
}
@@ -169,7 +191,14 @@ public final class AmbientBrightnessDayStats implements Parcelable {
dest.writeFloatArray(mStats);
}
- /** @hide */
+ /**
+ * Updates the stats by incrementing the time spent for the appropriate bucket based on ambient
+ * brightness reading.
+ *
+ * @param ambientBrightness Ambient brightness reading (in lux)
+ * @param durationSec Time spent with the given reading (in seconds)
+ * @hide
+ */
public void log(float ambientBrightness, float durationSec) {
int bucketIndex = getBucketIndex(ambientBrightness);
if (bucketIndex >= 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index bfb3a6ea55f7..092f3d241d6c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -64,7 +64,7 @@ public class DozeFactory {
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
- new DozeScreenState(wrappedService, handler),
+ new DozeScreenState(wrappedService, handler, params),
createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
new DozeWallpaperState(context)
});
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 8ec6afc326e1..6ff8e3db25e5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -24,6 +24,7 @@ import android.view.Display;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -87,12 +88,11 @@ public class DozeMachine {
}
}
- int screenState() {
+ int screenState(DozeParameters parameters) {
switch (this) {
case UNINITIALIZED:
case INITIALIZED:
case DOZE:
- case DOZE_REQUEST_PULSE:
case DOZE_AOD_PAUSED:
return Display.STATE_OFF;
case DOZE_PULSING:
@@ -100,6 +100,9 @@ public class DozeMachine {
case DOZE_AOD:
case DOZE_AOD_PAUSING:
return Display.STATE_DOZE_SUSPEND;
+ case DOZE_REQUEST_PULSE:
+ return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF
+ : Display.STATE_ON;
default:
return Display.STATE_UNKNOWN;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index bef9cb38180f..3053de366be5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -19,6 +19,8 @@ package com.android.systemui.doze;
import android.os.Handler;
import android.view.Display;
+import com.android.systemui.statusbar.phone.DozeParameters;
+
/**
* Controls the screen when dozing.
*/
@@ -26,17 +28,20 @@ public class DozeScreenState implements DozeMachine.Part {
private final DozeMachine.Service mDozeService;
private final Handler mHandler;
private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
+ private final DozeParameters mParameters;
private int mPendingScreenState = Display.STATE_UNKNOWN;
- public DozeScreenState(DozeMachine.Service service, Handler handler) {
+ public DozeScreenState(DozeMachine.Service service, Handler handler,
+ DozeParameters parameters) {
mDozeService = service;
mHandler = handler;
+ mParameters = parameters;
}
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
- int screenState = newState.screenState();
+ int screenState = newState.screenState(mParameters);
if (newState == DozeMachine.State.FINISH) {
// Make sure not to apply the screen state after DozeService was destroyed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 2b16e740d0ba..14387631f64d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -166,7 +166,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private boolean mScreenBlankingCallbackCalled;
private Callback mCallback;
private boolean mWallpaperSupportsAmbientMode;
+
+ // Scrim blanking callbacks
private Choreographer.FrameCallback mPendingFrameCallback;
+ private Runnable mBlankingTransitionRunnable;
private final WakeLock mWakeLock;
private boolean mWakeLockHeld;
@@ -249,10 +252,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mCurrentInFrontAlpha = state.getFrontAlpha();
mCurrentBehindAlpha = state.getBehindAlpha();
+ // Cancel blanking transitions that were pending before we requested a new state
if (mPendingFrameCallback != null) {
Choreographer.getInstance().removeFrameCallback(mPendingFrameCallback);
mPendingFrameCallback = null;
}
+ if (getHandler().hasCallbacks(mBlankingTransitionRunnable)) {
+ getHandler().removeCallbacks(mBlankingTransitionRunnable);
+ mBlankingTransitionRunnable = null;
+ }
// Showing/hiding the keyguard means that scrim colors have to be switched, not necessary
// to do the same when you're just showing the brightness mirror.
@@ -767,7 +775,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mScreenBlankingCallbackCalled = true;
}
- Runnable blankingCallback = () -> {
+ mBlankingTransitionRunnable = () -> {
+ mBlankingTransitionRunnable = null;
mPendingFrameCallback = null;
mBlankScreen = false;
// Try again.
@@ -776,7 +785,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
// Setting power states can happen after we push out the frame. Make sure we
// stay fully opaque until the power state request reaches the lower levels.
- getHandler().postDelayed(blankingCallback, 100);
+ if (DEBUG) {
+ Log.d(TAG, "Waiting for the screen to turn on...");
+ }
+ getHandler().postDelayed(mBlankingTransitionRunnable, 500);
};
doOnTheNextFrame(mPendingFrameCallback);
}
@@ -888,6 +900,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
}
+ /**
+ * Interrupts blanking transitions once the display notifies that it's already on.
+ */
+ public void onScreenTurnedOn() {
+ final Handler handler = getHandler();
+ if (handler.hasCallbacks(mBlankingTransitionRunnable)) {
+ if (DEBUG) {
+ Log.d(TAG, "Shorter blanking because screen turned on. All good.");
+ }
+ handler.removeCallbacks(mBlankingTransitionRunnable);
+ mBlankingTransitionRunnable.run();
+ }
+ }
+
public interface Callback {
default void onStart() {
}
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 8c112a623e18..458518c41c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4407,6 +4407,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onScreenTurnedOn() {
+ mScrimController.onScreenTurnedOn();
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 521d2e342218..8c4fd7386d6d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -28,6 +28,7 @@ import static com.android.systemui.utils.os.FakeHandler.Mode.QUEUEING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
import android.os.Looper;
import android.support.test.filters.SmallTest;
@@ -35,11 +36,14 @@ import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.utils.os.FakeHandler;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -48,12 +52,16 @@ public class DozeScreenStateTest extends SysuiTestCase {
DozeServiceFake mServiceFake;
DozeScreenState mScreen;
FakeHandler mHandlerFake;
+ @Mock
+ DozeParameters mDozeParameters;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
mServiceFake = new DozeServiceFake();
mHandlerFake = new FakeHandler(Looper.getMainLooper());
- mScreen = new DozeScreenState(mServiceFake, mHandlerFake);
+ mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeParameters);
}
@Test
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 220014fff4ab..608352b50bb0 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -657,6 +657,26 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
return false;
}
+ void remove() {
+ final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
+ while (getChildCount() > 0) {
+ final ActivityStack stack = getChildAt(0);
+ if (destroyContentOnRemoval) {
+ mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
+ false /* onTop */);
+ stack.finishAllActivitiesLocked(true /* immediately */);
+ } else {
+ // Moving all tasks to fullscreen stack, because it's guaranteed to be
+ // a valid launch stack for all activities. This way the task history from
+ // external display will be preserved on primary after move.
+ mSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+ }
+ }
+
+ mWindowContainerController.removeContainer();
+ mWindowContainerController = null;
+ }
+
/** Update and get all UIDs that are present on the display and have access to it. */
IntArray getPresentUIDs() {
mDisplayAccessUIDs.clear();
@@ -666,7 +686,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
return mDisplayAccessUIDs;
}
- boolean shouldDestroyContentOnRemove() {
+ private boolean shouldDestroyContentOnRemove() {
return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4bb18e2b0f01..9838851a56cf 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -380,7 +380,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
String getLifecycleDescription(String reason) {
- return "packageName=" + packageName + ", state=" + state + ", reason=" + reason;
+ return "component:" + intent.getComponent().flattenToShortString() + ", state=" + state
+ + ", reason=" + reason + ", time=" + System.currentTimeMillis();
}
void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index f3deb8dc5164..055a1aa4bbca 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4217,7 +4217,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)
- .setDescription(r.getLifecycleDescription("destroyActivityLocked")));
+ .setDescription(
+ r.getLifecycleDescription("destroyActivityLocked:" + reason)));
} catch (Exception e) {
// We can just ignore exceptions here... if the process
// has crashed, our death notification will clean things
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 831f89a1bdfa..4928e908ce44 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -4092,25 +4092,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (activityDisplay == null) {
return;
}
- final boolean destroyContentOnRemoval
- = activityDisplay.shouldDestroyContentOnRemove();
- while (activityDisplay.getChildCount() > 0) {
- final ActivityStack stack = activityDisplay.getChildAt(0);
- if (destroyContentOnRemoval) {
- moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, false /* onTop */);
- stack.finishAllActivitiesLocked(true /* immediately */);
- } else {
- // Moving all tasks to fullscreen stack, because it's guaranteed to be
- // a valid launch stack for all activities. This way the task history from
- // external display will be preserved on primary after move.
- moveTasksToFullscreenStackLocked(stack, true /* onTop */);
- }
- }
+
+ activityDisplay.remove();
releaseSleepTokens(activityDisplay);
mActivityDisplays.remove(displayId);
- mWindowManager.onDisplayRemoved(displayId);
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 6b4666a679ed..524de91b694e 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -115,12 +115,10 @@ public class BrightnessTracker {
= new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS);
@GuardedBy("mEventsLock")
private boolean mEventsDirty;
- private final Runnable mEventsWriter = () -> writeEvents();
- private volatile boolean mWriteEventsScheduled;
+
+ private volatile boolean mWriteBrightnessTrackerStateScheduled;
private AmbientBrightnessStatsTracker mAmbientBrightnessStatsTracker;
- private final Runnable mAmbientBrightnessStatsWriter = () -> writeAmbientBrightnessStats();
- private volatile boolean mWriteBrightnessStatsScheduled;
private UserManager mUserManager;
private final Context mContext;
@@ -167,13 +165,7 @@ public class BrightnessTracker {
}
mBgHandler = new TrackerHandler(mInjector.getBackgroundHandler().getLooper());
mUserManager = mContext.getSystemService(UserManager.class);
- try {
- final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack();
- mCurrentUserId = focusedStack.userId;
- } catch (RemoteException e) {
- // Really shouldn't be possible.
- return;
- }
+ mCurrentUserId = ActivityManager.getCurrentUser();
mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget();
}
@@ -355,18 +347,17 @@ public class BrightnessTracker {
}
private void scheduleWriteBrightnessTrackerState() {
- if (!mWriteEventsScheduled) {
- mBgHandler.post(mEventsWriter);
- mWriteEventsScheduled = true;
- }
- if (!mWriteBrightnessStatsScheduled) {
- mBgHandler.post(mAmbientBrightnessStatsWriter);
- mWriteBrightnessStatsScheduled = true;
+ if (!mWriteBrightnessTrackerStateScheduled) {
+ mBgHandler.post(() -> {
+ mWriteBrightnessTrackerStateScheduled = false;
+ writeEvents();
+ writeAmbientBrightnessStats();
+ });
+ mWriteBrightnessTrackerStateScheduled = true;
}
}
private void writeEvents() {
- mWriteEventsScheduled = false;
synchronized (mEventsLock) {
if (!mEventsDirty) {
// Nothing to write
@@ -398,7 +389,6 @@ public class BrightnessTracker {
}
private void writeAmbientBrightnessStats() {
- mWriteBrightnessStatsScheduled = false;
final AtomicFile writeTo = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE);
if (writeTo == null) {
return;
@@ -642,6 +632,7 @@ public class BrightnessTracker {
}
}
if (mAmbientBrightnessStatsTracker != null) {
+ pw.println();
mAmbientBrightnessStatsTracker.dump(pw);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index b27f1ec3c653..23de592f27bd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -51,7 +51,6 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
import android.util.Slog;
-import android.util.Spline;
import android.util.TimeUtils;
import android.view.Display;
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 961a45177897..3cc4d83267cf 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -187,6 +187,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
*/
@VisibleForTesting
public static long multiplySafe(long value, long num, long den) {
+ if (den == 0) den = 1;
long x = value;
long y = num;
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 30088dd9b12f..fb81ebfec67e 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -274,7 +274,7 @@ class InstantAppRegistry {
}
// Propagate permissions before removing any state
- propagateInstantAppPermissionsIfNeeded(pkg.packageName, userId);
+ propagateInstantAppPermissionsIfNeeded(pkg, userId);
// Track instant apps
if (ps.getInstantApp(userId)) {
@@ -869,10 +869,10 @@ class InstantAppRegistry {
return uninstalledApps;
}
- private void propagateInstantAppPermissionsIfNeeded(@NonNull String packageName,
+ private void propagateInstantAppPermissionsIfNeeded(@NonNull PackageParser.Package pkg,
@UserIdInt int userId) {
InstantAppInfo appInfo = peekOrParseUninstalledInstantAppInfo(
- packageName, userId);
+ pkg.packageName, userId);
if (appInfo == null) {
return;
}
@@ -884,8 +884,8 @@ class InstantAppRegistry {
for (String grantedPermission : appInfo.getGrantedPermissions()) {
final boolean propagatePermission =
mService.mSettings.canPropagatePermissionToInstantApp(grantedPermission);
- if (propagatePermission) {
- mService.grantRuntimePermission(packageName, grantedPermission, userId);
+ if (propagatePermission && pkg.requestedPermissions.contains(grantedPermission)) {
+ mService.grantRuntimePermission(pkg.packageName, grantedPermission, userId);
}
}
} finally {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2512dbd6a12b..41a6e2ba7e69 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -725,8 +725,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* wallpaper windows in the window list.
*/
DisplayContent(Display display, WindowManagerService service,
- WallpaperController wallpaperController) {
+ WallpaperController wallpaperController, DisplayWindowController controller) {
super(service);
+ setController(controller);
if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
+ " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
@@ -1941,6 +1942,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
} finally {
mRemovingDisplay = false;
}
+
+ mService.onDisplayRemoved(mDisplayId);
}
/** Returns true if a removal action is still being deferred. */
@@ -1950,7 +1953,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (!stillDeferringRemoval && mDeferredRemoval) {
removeImmediately();
- mService.onDisplayRemoved(mDisplayId);
return false;
}
return true;
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index ad4957e4fc6f..0e1283899eea 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -16,11 +16,14 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.content.res.Configuration;
+import android.os.Binder;
import android.util.Slog;
+import android.view.Display;
/**
* Controller for the display container. This is created by activity manager to link activity
@@ -36,9 +39,16 @@ public class DisplayWindowController
mDisplayId = displayId;
synchronized (mWindowMap) {
- // TODO: Convert to setContainer() from DisplayContent once everything is hooked up.
- // Currently we are not setup to register for config changes.
- mContainer = mRoot.getDisplayContentOrCreate(displayId);
+ final Display display = mService.mDisplayManager.getDisplay(displayId);
+ if (display != null) {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mRoot.createDisplayContent(display, this /* controller */);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
if (mContainer == null) {
throw new IllegalArgumentException("Trying to add displayId=" + displayId);
}
@@ -47,14 +57,22 @@ public class DisplayWindowController
@Override
public void removeContainer() {
- // TODO: Pipe through from ActivityDisplay to remove the display
- throw new UnsupportedOperationException("To be implemented");
+ synchronized (mWindowMap) {
+ if(mContainer == null) {
+ if (DEBUG_DISPLAY) Slog.i(TAG_WM, "removeDisplay: could not find displayId="
+ + mDisplayId);
+ return;
+ }
+ mContainer.removeIfPossible();
+ super.removeContainer();
+ }
}
@Override
public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
- // TODO: Pipe through from ActivityDisplay to update the configuration for the display
- throw new UnsupportedOperationException("To be implemented");
+ // TODO: The container receives override configuration changes through other means. enabling
+ // callbacks through the controller causes layout issues. Investigate consolidating
+ // override configuration propagation to just here.
}
/**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c535fe5f7ddc..f5760e593f37 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -193,30 +193,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
}
}
- /**
- * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
- * there is a Display for the displayId.
- *
- * @param displayId The display the caller is interested in.
- * @return The DisplayContent associated with displayId or null if there is no Display for it.
- */
- DisplayContent getDisplayContentOrCreate(int displayId) {
- DisplayContent dc = getDisplayContent(displayId);
-
- if (dc == null) {
- final Display display = mService.mDisplayManager.getDisplay(displayId);
- if (display != null) {
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- dc = createDisplayContent(display);
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
- }
- }
- }
- return dc;
- }
-
DisplayContent getDisplayContent(int displayId) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final DisplayContent current = mChildren.get(i);
@@ -227,9 +203,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
return null;
}
- private DisplayContent createDisplayContent(final Display display) {
- final DisplayContent dc = new DisplayContent(display, mService,
- mWallpaperController);
+ DisplayContent createDisplayContent(final Display display, DisplayWindowController controller) {
+ final DisplayContent dc =
+ new DisplayContent(display, mService, mWallpaperController, controller);
final int displayId = display.getDisplayId();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
@@ -748,19 +724,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
(mSustainedPerformanceModeEnabled ? 1 : 0));
}
- if (mService.mTurnOnScreen) {
- if (mService.mAllowTheaterModeWakeFromLayout
- || Settings.Global.getInt(mService.mContext.getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0) == 0) {
- if (DEBUG_VISIBILITY || DEBUG_POWER) {
- Slog.v(TAG, "Turning screen on after layout!");
- }
- mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
- "android.server.wm:TURN_ON");
- }
- mService.mTurnOnScreen = false;
- }
-
if (mUpdateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
// TODO(multi-display): Update rotation for different displays separately.
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index cec13abd823d..49a30d5382c3 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -161,7 +161,7 @@ public class WindowAnimator {
final int numDisplays = mDisplayContentsAnimators.size();
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
final ScreenRotationAnimation screenRotationAnimation =
@@ -195,7 +195,7 @@ public class WindowAnimator {
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
dc.checkAppWindowsReadyToShow();
@@ -228,7 +228,7 @@ public class WindowAnimator {
final int numDisplays = mDisplayContentsAnimators.size();
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
dc.onPendingTransactionApplied();
}
@@ -305,7 +305,7 @@ public class WindowAnimator {
pw.println(":");
final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
final DisplayContent dc =
- mService.mRoot.getDisplayContentOrCreate(mDisplayContentsAnimators.keyAt(i));
+ mService.mRoot.getDisplayContent(mDisplayContentsAnimators.keyAt(i));
dc.dumpWindowAnimators(pw, subPrefix);
if (displayAnimator.mScreenRotationAnimation != null) {
pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
@@ -339,7 +339,7 @@ public class WindowAnimator {
if (displayId < 0) {
return 0;
}
- final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
}
@@ -347,7 +347,7 @@ public class WindowAnimator {
if (displayId < 0) {
return;
}
- final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
if (displayContent != null) {
displayContent.pendingLayoutChanges |= changes;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 676fb9f2d208..c2ed2ae30227 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -737,7 +737,6 @@ public class WindowManagerService extends IWindowManager.Stub
final InputManagerService mInputManager;
final DisplayManagerInternal mDisplayManagerInternal;
final DisplayManager mDisplayManager;
- private final Display[] mDisplays;
// Indicates whether this device supports wide color gamut rendering
private boolean mHasWideColorGamutSupport;
@@ -746,8 +745,6 @@ public class WindowManagerService extends IWindowManager.Stub
private Session mHoldingScreenOn;
private PowerManager.WakeLock mHoldingScreenWakeLock;
- boolean mTurnOnScreen;
-
// Whether or not a layout can cause a wake up when theater mode is enabled.
boolean mAllowTheaterModeWakeFromLayout;
@@ -915,7 +912,6 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
-
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
@@ -974,10 +970,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- mDisplays = mDisplayManager.getDisplays();
- for (Display display : mDisplays) {
- createDisplayContentLocked(display);
- }
mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
@@ -1066,6 +1058,13 @@ public class WindowManagerService extends IWindowManager.Stub
mDragDropController = new DragDropController(this, mH.getLooper());
LocalServices.addService(WindowManagerInternal.class, new LocalService());
+ }
+
+ /**
+ * Called after all entities (such as the {@link ActivityManagerService}) have been set up and
+ * associated with the {@link WindowManagerService}.
+ */
+ public void onInitReady() {
initPolicy();
// Add ourself to the Watchdog monitors.
@@ -1081,6 +1080,7 @@ public class WindowManagerService extends IWindowManager.Stub
showEmulatorDisplayOverlayIfNeeded();
}
+
public InputMonitor getInputMonitor() {
return mInputMonitor;
}
@@ -1131,7 +1131,7 @@ public class WindowManagerService extends IWindowManager.Stub
throw new IllegalStateException("Display has not been initialialized");
}
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent == null) {
Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
+ displayId + ". Aborting.");
@@ -2277,7 +2277,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
synchronized(mWindowMap) {
- final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
WindowToken token = dc.getWindowToken(binder);
if (token != null) {
Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
@@ -3666,7 +3666,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean wallpaperOnly) {
final DisplayContent displayContent;
synchronized(mWindowMap) {
- displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ displayContent = mRoot.getDisplayContent(displayId);
if (displayContent == null) {
if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot returning null. No Display for "
+ "displayId=" + displayId);
@@ -3885,7 +3885,7 @@ public class WindowManagerService extends IWindowManager.Stub
public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
int displayId) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent == null) {
throw new IllegalArgumentException("Trying to register visibility event "
+ "for invalid display: " + displayId);
@@ -4442,10 +4442,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void displayReady() {
- for (Display display : mDisplays) {
+ final int displayCount = mRoot.mChildren.size();
+ for (int i = 0; i < displayCount; ++i) {
+ final DisplayContent display = mRoot.mChildren.get(i);
displayReady(display.getDisplayId());
}
+
synchronized(mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
if (mMaxUiWidth > 0) {
@@ -4476,7 +4479,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void displayReady(int displayId) {
synchronized(mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
mAnimator.addDisplayLocked(displayId);
displayContent.initializeDisplayBaseInfo();
@@ -5025,7 +5028,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void getInitialDisplaySize(int displayId, Point size) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
size.x = displayContent.mInitialDisplayWidth;
size.y = displayContent.mInitialDisplayHeight;
@@ -5036,7 +5039,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void getBaseDisplaySize(int displayId, Point size) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
size.x = displayContent.mBaseDisplayWidth;
size.y = displayContent.mBaseDisplayHeight;
@@ -5063,7 +5066,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int MIN_WIDTH = 200;
final int MIN_HEIGHT = 200;
final int MAX_SCALE = 2;
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
width = Math.min(Math.max(width, MIN_WIDTH),
displayContent.mInitialDisplayWidth * MAX_SCALE);
@@ -5093,7 +5096,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
if (mode < 0 || mode > 1) {
mode = 0;
@@ -5175,7 +5178,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
displayContent.mInitialDisplayHeight);
@@ -5191,7 +5194,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public int getInitialDisplayDensity(int displayId) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
return displayContent.mInitialDisplayDensity;
}
@@ -5202,7 +5205,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public int getBaseDisplayDensity(int displayId) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
return displayContent.mBaseDisplayDensity;
}
@@ -5228,7 +5231,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && mCurrentUserId == targetUserId) {
setForcedDisplayDensityLocked(displayContent, density);
}
@@ -5259,7 +5262,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && mCurrentUserId == callingUserId) {
setForcedDisplayDensityLocked(displayContent,
displayContent.mInitialDisplayDensity);
@@ -5351,7 +5354,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
synchronized(mWindowMap) {
- DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
setOverscanLocked(displayContent, left, top, right, bottom);
}
@@ -6614,19 +6617,11 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mWindowMap) { }
}
- // TODO: All the display method below should probably be moved into the RootWindowContainer...
- private void createDisplayContentLocked(final Display display) {
- if (display == null) {
- throw new IllegalArgumentException("getDisplayContent: display must not be null");
- }
- mRoot.getDisplayContentOrCreate(display.getDisplayId());
- }
-
// There is an inherent assumption that this will never return null.
// TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
// support non-default display.
DisplayContent getDefaultDisplayContentLocked() {
- return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
+ return mRoot.getDisplayContent(DEFAULT_DISPLAY);
}
public void onDisplayAdded(int displayId) {
@@ -6641,10 +6636,6 @@ public class WindowManagerService extends IWindowManager.Stub
public void onDisplayRemoved(int displayId) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
- if (displayContent != null) {
- displayContent.removeIfPossible();
- }
mAnimator.removeDisplayLocked(displayId);
mWindowPlacerLocked.requestTraversal();
}
@@ -6660,7 +6651,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void onDisplayChanged(int displayId) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null) {
displayContent.updateDisplayInfo();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b6712c097e23..21b436112fda 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.SurfaceControl.Transaction;
@@ -167,6 +168,7 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
@@ -285,7 +287,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
int mLayer;
boolean mHaveFrame;
boolean mObscured;
- boolean mTurnOnScreen;
int mLayoutSeq = -1;
@@ -635,6 +636,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private TapExcludeRegionHolder mTapExcludeRegionHolder;
/**
+ * Used for testing because the real PowerManager is final.
+ */
+ private PowerManagerWrapper mPowerManagerWrapper;
+
+ /**
* Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
* of z-order and 1 otherwise.
*/
@@ -663,9 +669,34 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
+ interface PowerManagerWrapper {
+ void wakeUp(long time, String reason);
+
+ boolean isInteractive();
+
+ }
+
+ WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
+ WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
+ int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
+ this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
+ ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
+ @Override
+ public void wakeUp(long time, String reason) {
+ service.mPowerManager.wakeUp(time, reason);
+ }
+
+ @Override
+ public boolean isInteractive() {
+ return service.mPowerManager.isInteractive();
+ }
+ });
+ }
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
- WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
- int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
+ WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
+ int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
+ PowerManagerWrapper powerManagerWrapper) {
super(service);
mSession = s;
mClient = c;
@@ -682,6 +713,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
+ mPowerManagerWrapper = powerManagerWrapper;
if (localLOGV) Slog.v(
TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -2275,9 +2307,34 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
// We need to turn on screen regardless of visibility.
- if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
- mTurnOnScreen = true;
+ boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
+ boolean allowTheaterMode =
+ mService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
+ mService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
+ == 0;
+ boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
+
+ // The screen will turn on if the following conditions are met
+ // 1. The window has the flag FLAG_TURN_SCREEN_ON
+ // 2. The WMS allows theater mode.
+ // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
+ // per resume to prevent the screen getting getting turned on for each relayout. Set
+ // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
+ // during this resume.
+ // 4. When the screen is not interactive. This is because when the screen is already
+ // interactive, the value may persist until the next animation, which could potentially
+ // be occurring while turning off the screen. This would lead to the screen incorrectly
+ // turning back on.
+ if (hasTurnScreenOnFlag && allowTheaterMode && canTurnScreenOn
+ && !mPowerManagerWrapper.isInteractive()) {
+ if (DEBUG_VISIBILITY || DEBUG_POWER) {
+ Slog.v(TAG, "Relayout window turning screen on: " + this);
+ }
+ mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
+ "android.server.wm:TURN_ON");
+ }
+ if (mAppToken != null) {
+ mAppToken.setCanTurnScreenOn(false);
}
// If we were already visible, skip rest of preparation.
@@ -2571,8 +2628,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// in wake lock statistics. So in particular, we don't want to include the
// window's hash code as in toString().
final CharSequence tag = getWindowTag();
- mDrawLock = mService.mPowerManager.newWakeLock(
- PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
+ mDrawLock = mService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
mDrawLock.setReferenceCounted(false);
mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
}
@@ -3327,15 +3383,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
pw.print(" mDestroying="); pw.print(mDestroying);
pw.print(" mRemoved="); pw.println(mRemoved);
}
- if (getOrientationChanging() || mAppFreezing || mTurnOnScreen
- || mReportOrientationChanged) {
+ if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
pw.print(prefix); pw.print("mOrientationChanging=");
pw.print(mOrientationChanging);
pw.print(" configOrientationChanging=");
pw.print(getLastReportedConfiguration().orientation
!= getConfiguration().orientation);
pw.print(" mAppFreezing="); pw.print(mAppFreezing);
- pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen);
pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
}
if (mLastFreezeDuration != 0) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index dd23b6f25630..9621ee527cac 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1108,31 +1108,6 @@ class WindowStateAnimator {
w.setOrientationChanging(false);
}
}
- // We process mTurnOnScreen even for windows which have already
- // been shown, to handle cases where windows are not necessarily
- // hidden while the screen is turning off.
- // TODO(b/63773439): These cases should be eliminated, though we probably still
- // want to process mTurnOnScreen in this way for clarity.
- if (mWin.mTurnOnScreen &&
- (mWin.mAppToken == null || mWin.mAppToken.canTurnScreenOn())) {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin);
- mWin.mTurnOnScreen = false;
-
- // The window should only turn the screen on once per resume, but
- // prepareSurfaceLocked can be called multiple times. Set canTurnScreenOn to
- // false so the window doesn't turn the screen on again during this resume.
- if (mWin.mAppToken != null) {
- mWin.mAppToken.setCanTurnScreenOn(false);
- }
-
- // We do not add {@code SET_TURN_ON_SCREEN} when the screen is already
- // interactive as the value may persist until the next animation, which could
- // potentially occurring while turning off the screen. This would lead to the
- // screen incorrectly turning back on.
- if (!mService.mPowerManager.isInteractive()) {
- mService.mTurnOnScreen = true;
- }
- }
}
if (hasSurface()) {
w.mToken.hasVisible = true;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5ea113b801b5..75bb5e4f8a6b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -842,6 +842,14 @@ public final class SystemServer {
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
+ traceBeginAndSlog("SetWindowManagerService");
+ mActivityManagerService.setWindowManager(wm);
+ traceEnd();
+
+ traceBeginAndSlog("WindowManagerServiceOnInitReady");
+ wm.onInitReady();
+ traceEnd();
+
// Start receiving calls from HIDL services. Start in in a separate thread
// because it need to connect to SensorManager. This have to start
// after START_SENSOR_SERVICE is done.
@@ -859,10 +867,6 @@ public final class SystemServer {
traceEnd();
}
- traceBeginAndSlog("SetWindowManagerService");
- mActivityManagerService.setWindowManager(wm);
- traceEnd();
-
traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 000cf38aceae..7a559046f7b8 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -107,6 +108,13 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
sWm = WindowManagerService.main(context, ims, true, false,
false, new TestWindowManagerPolicy());
+
+ sWm.onInitReady();
+
+ // Display creation is driven by the ActivityManagerService via ActivityStackSupervisor.
+ // We emulate those steps here.
+ sWm.mRoot.createDisplayContent(sWm.mDisplayManager.getDisplay(DEFAULT_DISPLAY),
+ mock(DisplayWindowController.class));
}
return sWm;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 4d41718e4da0..74c72bf2ae0d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -41,6 +41,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
/**
* Tests for the {@link WindowState} class.
@@ -240,11 +244,11 @@ public class WindowStateTests extends WindowTestsBase {
}
private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
+ reset(mPowerManagerWrapper);
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
- root.mTurnOnScreen = false;
root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
- assertTrue(root.mTurnOnScreen);
+ verify(mPowerManagerWrapper).wakeUp(anyLong(), anyString());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 69b13787ef93..91d5ea463bbe 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -29,6 +29,7 @@ import android.view.DisplayInfo;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import android.content.Context;
@@ -84,6 +85,9 @@ class WindowTestsBase {
WindowState mChildAppWindowBelow;
HashSet<WindowState> mCommonWindows;
+ @Mock
+ static WindowState.PowerManagerWrapper mPowerManagerWrapper;
+
@Before
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
@@ -245,7 +249,7 @@ class WindowTestsBase {
attrs.setTitle(name);
final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
- 0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow);
+ 0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow, mPowerManagerWrapper);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);
@@ -284,7 +288,8 @@ class WindowTestsBase {
final int displayId = sNextDisplayId++;
final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
mDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
- return new DisplayContent(display, sWm, new WallpaperController(sWm));
+ return new DisplayContent(display, sWm, new WallpaperController(sWm),
+ mock(DisplayWindowController.class));
}
/** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 669afe18af88..734a5ab8aab4 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4848,6 +4848,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
const String16 pathInterpolator16("pathInterpolator");
const String16 objectAnimator16("objectAnimator");
const String16 gradient16("gradient");
+ const String16 animatedSelector16("animated-selector");
const int minSdk = getMinSdkVersion(bundle);
if (minSdk >= SDK_LOLLIPOP_MR1) {
@@ -4876,7 +4877,8 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
node->getElementName() == animatedVector16 ||
node->getElementName() == objectAnimator16 ||
node->getElementName() == pathInterpolator16 ||
- node->getElementName() == gradient16)) {
+ node->getElementName() == gradient16 ||
+ node->getElementName() == animatedSelector16)) {
// We were told not to version vector tags, so skip the children here.
continue;
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 1afd283a430a..15c5eaecd102 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -450,7 +450,7 @@ static bool IsTransitionElement(const std::string& name) {
static bool IsVectorElement(const std::string& name) {
return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
- name == "objectAnimator" || name == "gradient";
+ name == "objectAnimator" || name == "gradient" || name == "animated-selector";
}
template <typename T>