diff options
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> |