diff options
16 files changed, 370 insertions, 300 deletions
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 9cc550daa5a7..d1b56e9afa4e 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -43,6 +43,7 @@ import android.util.Slog; import com.android.internal.os.ZygoteConnectionConstants; import com.android.server.am.ActivityManagerService; +import com.android.server.wm.SurfaceAnimationThread; import java.io.File; import java.io.FileWriter; @@ -280,6 +281,12 @@ public class Watchdog extends Thread { // And the display thread. mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), "display thread", DEFAULT_TIMEOUT)); + // And the animation thread. + mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(), + "animation thread", DEFAULT_TIMEOUT)); + // And the surface animation thread. + mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(), + "surface animation thread", DEFAULT_TIMEOUT)); // Initialize monitor for Binder threads. addMonitor(new BinderThreadMonitor()); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 7ea7e1a8241e..c45eaf67d3dc 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1134,9 +1134,46 @@ public class ActivityManagerService extends IActivityManager.Stub boolean mOrigWaitForDebugger = false; boolean mAlwaysFinishActivities = false; - String mProfileApp = null; - ProcessRecord mProfileProc = null; - ProfilerInfo mProfilerInfo = null; + class ProfileData { + private String mProfileApp = null; + private ProcessRecord mProfileProc = null; + private ProfilerInfo mProfilerInfo = null; + + void setProfileApp(String profileApp) { + mProfileApp = profileApp; + if (mAtmInternal != null) { + mAtmInternal.setProfileApp(profileApp); + } + } + + String getProfileApp() { + return mProfileApp; + } + + void setProfileProc(ProcessRecord profileProc) { + mProfileProc = profileProc; + if (mAtmInternal != null) { + mAtmInternal.setProfileProc( + profileProc.getWindowProcessController()); + } + } + + ProcessRecord getProfileProc() { + return mProfileProc; + } + + void setProfilerInfo(ProfilerInfo profilerInfo) { + mProfilerInfo = profilerInfo; + if (mAtmInternal != null) { + mAtmInternal.setProfilerInfo(profilerInfo); + } + } + + ProfilerInfo getProfilerInfo() { + return mProfilerInfo; + } + } + final ProfileData mProfileData = new ProfileData(); /** * Stores a map of process name -> agent string. When a process is started and mAgentAppMap @@ -2225,8 +2262,7 @@ public class ActivityManagerService extends IActivityManager.Stub mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler); mActivityTaskManager = atm; - mActivityTaskManager.setActivityManagerService(this, mHandlerThread.getLooper(), - mIntentFirewall, mPendingIntentController); + mActivityTaskManager.setActivityManagerService(mIntentFirewall, mPendingIntentController); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mProcessCpuThread = new Thread("CpuTracker") { @@ -3129,7 +3165,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } - if (mProfileProc == app) { + if (mProfileData.getProfileProc() == app) { clearProfilerLocked(); } @@ -4410,16 +4446,18 @@ public class ActivityManagerService extends IActivityManager.Stub ProfilerInfo profilerInfo = null; String preBindAgent = null; - if (mProfileApp != null && mProfileApp.equals(processName)) { - mProfileProc = app; - if (mProfilerInfo != null) { + if (mProfileData.getProfileApp() != null + && mProfileData.getProfileApp().equals(processName)) { + mProfileData.setProfileProc(app); + if (mProfileData.getProfilerInfo() != null) { // Send a profiler info object to the app if either a file is given, or // an agent should be loaded at bind-time. - boolean needsInfo = mProfilerInfo.profileFile != null - || mProfilerInfo.attachAgentDuringBind; - profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null; - if (mProfilerInfo.agent != null) { - preBindAgent = mProfilerInfo.agent; + boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null + || mProfileData.getProfilerInfo().attachAgentDuringBind; + profilerInfo = needsInfo + ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null; + if (mProfileData.getProfilerInfo().agent != null) { + preBindAgent = mProfileData.getProfilerInfo().agent; } } } else if (instr != null && instr.mProfileFile != null) { @@ -4443,7 +4481,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (profilerInfo != null && profilerInfo.profileFd != null) { profilerInfo.profileFd = profilerInfo.profileFd.dup(); - if (TextUtils.equals(mProfileApp, processName) && mProfilerInfo != null) { + if (TextUtils.equals(mProfileData.getProfileApp(), processName) + && mProfileData.getProfilerInfo() != null) { clearProfilerLocked(); } } @@ -7444,17 +7483,17 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException("Process not debuggable: " + app.packageName); } } - mProfileApp = processName; + mProfileData.setProfileApp(processName); - if (mProfilerInfo != null) { - if (mProfilerInfo.profileFd != null) { + if (mProfileData.getProfilerInfo() != null) { + if (mProfileData.getProfilerInfo().profileFd != null) { try { - mProfilerInfo.profileFd.close(); + mProfileData.getProfilerInfo().profileFd.close(); } catch (IOException e) { } } } - mProfilerInfo = new ProfilerInfo(profilerInfo); + mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo)); mProfileType = 0; } } @@ -9971,20 +10010,25 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(" mTrackAllocationApp=" + mTrackAllocationApp); } } - if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null && - (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) { - if (dumpPackage == null || dumpPackage.equals(mProfileApp)) { + if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null + || (mProfileData.getProfilerInfo() != null && + (mProfileData.getProfilerInfo().profileFile != null + || mProfileData.getProfilerInfo().profileFd != null))) { + if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) { if (needSep) { pw.println(); needSep = false; } - pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc); - if (mProfilerInfo != null) { - pw.println(" mProfileFile=" + mProfilerInfo.profileFile + " mProfileFd=" + - mProfilerInfo.profileFd); - pw.println(" mSamplingInterval=" + mProfilerInfo.samplingInterval + - " mAutoStopProfiler=" + mProfilerInfo.autoStopProfiler + - " mStreamingOutput=" + mProfilerInfo.streamingOutput); + pw.println(" mProfileApp=" + mProfileData.getProfileApp() + + " mProfileProc=" + mProfileData.getProfileProc()); + if (mProfileData.getProfilerInfo() != null) { + pw.println(" mProfileFile=" + mProfileData.getProfilerInfo().profileFile + + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd); + pw.println(" mSamplingInterval=" + + mProfileData.getProfilerInfo().samplingInterval + + " mAutoStopProfiler=" + + mProfileData.getProfilerInfo().autoStopProfiler + + " mStreamingOutput=" + mProfileData.getProfilerInfo().streamingOutput); pw.println(" mProfileType=" + mProfileType); } } @@ -10264,19 +10308,26 @@ public class ActivityManagerService extends IActivityManager.Stub if (mTrackAllocationApp != null) { if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) { - proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp); + proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP, + mTrackAllocationApp); } } - if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null && - (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) { - if (dumpPackage == null || dumpPackage.equals(mProfileApp)) { + if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null + || (mProfileData.getProfilerInfo() != null && + (mProfileData.getProfilerInfo().profileFile != null + || mProfileData.getProfilerInfo().profileFd != null))) { + if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) { final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE); - proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, mProfileApp); - mProfileProc.writeToProto(proto,ActivityManagerServiceDumpProcessesProto.Profile.PROC); - if (mProfilerInfo != null) { - mProfilerInfo.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Profile.INFO); - proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, mProfileType); + proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, + mProfileData.getProfileApp()); + mProfileData.getProfileProc().writeToProto(proto, + ActivityManagerServiceDumpProcessesProto.Profile.PROC); + if (mProfileData.getProfilerInfo() != null) { + mProfileData.getProfilerInfo().writeToProto(proto, + ActivityManagerServiceDumpProcessesProto.Profile.INFO); + proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, + mProfileType); } proto.end(token); } @@ -18033,8 +18084,8 @@ public class ActivityManagerService extends IActivityManager.Stub } private void stopProfilerLocked(ProcessRecord proc, int profileType) { - if (proc == null || proc == mProfileProc) { - proc = mProfileProc; + if (proc == null || proc == mProfileData.getProfileProc()) { + proc = mProfileData.getProfileProc(); profileType = mProfileType; clearProfilerLocked(); } @@ -18049,15 +18100,16 @@ public class ActivityManagerService extends IActivityManager.Stub } void clearProfilerLocked() { - if (mProfilerInfo !=null && mProfilerInfo.profileFd != null) { + if (mProfileData.getProfilerInfo() != null + && mProfileData.getProfilerInfo().profileFd != null) { try { - mProfilerInfo.profileFd.close(); + mProfileData.getProfilerInfo().profileFd.close(); } catch (IOException e) { } } - mProfileApp = null; - mProfileProc = null; - mProfilerInfo = null; + mProfileData.setProfileApp(null); + mProfileData.setProfileProc(null); + mProfileData.setProfilerInfo(null); } public boolean profileControl(String process, int userId, boolean start, @@ -18089,7 +18141,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (start) { stopProfilerLocked(null, 0); setProfileApp(proc.info, proc.processName, profilerInfo); - mProfileProc = proc; + mProfileData.setProfileProc(proc); mProfileType = profileType; ParcelFileDescriptor fd = profilerInfo.profileFd; try { @@ -18101,10 +18153,10 @@ public class ActivityManagerService extends IActivityManager.Stub proc.thread.profilerControl(start, profilerInfo, profileType); fd = null; try { - mProfilerInfo.profileFd.close(); + mProfileData.getProfilerInfo().profileFd.close(); } catch (IOException e) { } - mProfilerInfo.profileFd = null; + mProfileData.getProfilerInfo().profileFd = null; if (proc.pid == MY_PID) { // When profiling the system server itself, avoid closing the file diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index bb87ad031ad5..8a3f139858c8 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -1123,8 +1123,9 @@ final class ProcessRecord implements WindowProcessListener { @Override public void clearProfilerIfNeeded() { synchronized (mService) { - if (mService.mProfileProc == null || mService.mProfilerInfo == null - || mService.mProfileProc != this) { + if (mService.mProfileData.getProfileProc() == null + || mService.mProfileData.getProfilerInfo() == null + || mService.mProfileData.getProfileProc() != this) { return; } mService.clearProfilerLocked(); @@ -1198,32 +1199,15 @@ final class ProcessRecord implements WindowProcessListener { } @Override - public ProfilerInfo onStartActivity(int topProcessState) { + public void onStartActivity(int topProcessState, boolean setProfileProc) { synchronized (mService) { - ProfilerInfo profilerInfo = null; - if (mService.mProfileApp != null && mService.mProfileApp.equals(processName)) { - if (mService.mProfileProc == null || mService.mProfileProc == this) { - mService.mProfileProc = this; - final ProfilerInfo profilerInfoSvc = mService.mProfilerInfo; - if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) { - if (profilerInfoSvc.profileFd != null) { - try { - profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup(); - } catch (IOException e) { - profilerInfoSvc.closeFd(); - } - } - - profilerInfo = new ProfilerInfo(profilerInfoSvc); - } - } + if (setProfileProc) { + mService.mProfileData.setProfileProc(this); } hasShownUi = true; setPendingUiClean(true); forceProcessStateUpTo(topProcessState); - - return profilerInfo; } } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index a8b4a9d43ebb..341a777e6d45 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2679,136 +2679,129 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai || (lastFocusedStack.mLastPausedActivity != null && !lastFocusedStack.mLastPausedActivity.fullscreen)); - // The contained logic must be synchronized, since we are both changing the visibility - // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will - // ultimately cause the client code to schedule a layout. Since layouts retrieve the - // current {@link Configuration}, we must ensure that the below code updates it before - // the layout can occur. - synchronized(mWindowManager.getWindowManagerLock()) { - // This activity is now becoming visible. - if (!next.visible || next.stopped || lastActivityTranslucent) { - next.setVisibility(true); + // This activity is now becoming visible. + if (!next.visible || next.stopped || lastActivityTranslucent) { + next.setVisibility(true); + } + + // schedule launch ticks to collect information about slow apps. + next.startLaunchTickingLocked(); + + ActivityRecord lastResumedActivity = + lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; + final ActivityState lastState = next.getState(); + + mService.updateCpuStats(); + + if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + + " (in existing)"); + + next.setState(RESUMED, "resumeTopActivityInnerLocked"); + + next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, + true /* updateLru */, true /* activityChange */, true /* updateOomAdj */); + updateLRUListLocked(next); + + // Have the window manager re-evaluate the orientation of + // the screen based on the new activity order. + boolean notUpdated = true; + + if (isFocusedStackOnDisplay()) { + // We have special rotation behavior when here is some active activity that + // requests specific orientation or Keyguard is locked. Make sure all activity + // visibilities are set correctly as well as the transition is updated if needed + // to get the correct rotation behavior. Otherwise the following call to update + // the orientation may cause incorrect configurations delivered to client as a + // result of invisible window resize. + // TODO: Remove this once visibilities are set correctly immediately when + // starting an activity. + notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId, + true /* markFrozenIfConfigChanged */, false /* deferResume */); + } + + if (notUpdated) { + // The configuration update wasn't able to keep the existing + // instance of the activity, and instead started a new one. + // We should be all done, but let's just make sure our activity + // is still at the top and schedule another run if something + // weird happened. + ActivityRecord nextNext = topRunningActivityLocked(); + if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, + "Activity config changed during resume: " + next + + ", new next: " + nextNext); + if (nextNext != next) { + // Do over! + mStackSupervisor.scheduleResumeTopActivities(); } - - // schedule launch ticks to collect information about slow apps. - next.startLaunchTickingLocked(); - - ActivityRecord lastResumedActivity = - lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; - final ActivityState lastState = next.getState(); - - mService.updateCpuStats(); - - if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next - + " (in existing)"); - - next.setState(RESUMED, "resumeTopActivityInnerLocked"); - - next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, - true /* updateLru */, true /* activityChange */, true /* updateOomAdj */); - updateLRUListLocked(next); - - // Have the window manager re-evaluate the orientation of - // the screen based on the new activity order. - boolean notUpdated = true; - - if (isFocusedStackOnDisplay()) { - // We have special rotation behavior when here is some active activity that - // requests specific orientation or Keyguard is locked. Make sure all activity - // visibilities are set correctly as well as the transition is updated if needed - // to get the correct rotation behavior. Otherwise the following call to update - // the orientation may cause incorrect configurations delivered to client as a - // result of invisible window resize. - // TODO: Remove this once visibilities are set correctly immediately when - // starting an activity. - notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId, - true /* markFrozenIfConfigChanged */, false /* deferResume */); + if (!next.visible || next.stopped) { + next.setVisibility(true); } + next.completeResumeLocked(); + if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); + return true; + } - if (notUpdated) { - // The configuration update wasn't able to keep the existing - // instance of the activity, and instead started a new one. - // We should be all done, but let's just make sure our activity - // is still at the top and schedule another run if something - // weird happened. - ActivityRecord nextNext = topRunningActivityLocked(); - if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, - "Activity config changed during resume: " + next - + ", new next: " + nextNext); - if (nextNext != next) { - // Do over! - mStackSupervisor.scheduleResumeTopActivities(); - } - if (!next.visible || next.stopped) { - next.setVisibility(true); + try { + final ClientTransaction transaction = + ClientTransaction.obtain(next.app.getThread(), next.appToken); + // Deliver all pending results. + ArrayList<ResultInfo> a = next.results; + if (a != null) { + final int N = a.size(); + if (!next.finishing && N > 0) { + if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, + "Delivering results to " + next + ": " + a); + transaction.addCallback(ActivityResultItem.obtain(a)); } - next.completeResumeLocked(); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - return true; } - try { - final ClientTransaction transaction = - ClientTransaction.obtain(next.app.getThread(), next.appToken); - // Deliver all pending results. - ArrayList<ResultInfo> a = next.results; - if (a != null) { - final int N = a.size(); - if (!next.finishing && N > 0) { - if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, - "Delivering results to " + next + ": " + a); - transaction.addCallback(ActivityResultItem.obtain(a)); - } - } - - if (next.newIntents != null) { - transaction.addCallback(NewIntentItem.obtain(next.newIntents, - false /* andPause */)); - } + if (next.newIntents != null) { + transaction.addCallback(NewIntentItem.obtain(next.newIntents, + false /* andPause */)); + } - // Well the app will no longer be stopped. - // Clear app token stopped state in window manager if needed. - next.notifyAppResumed(next.stopped); - - EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, - System.identityHashCode(next), next.getTask().taskId, - next.shortComponentName); - - next.sleeping = false; - mService.getAppWarningsLocked().onResumeActivity(next); - next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState); - next.clearOptionsLocked(); - transaction.setLifecycleStateRequest( - ResumeActivityItem.obtain(next.app.getReportedProcState(), - getDisplay().getWindowContainerController() - .isNextTransitionForward())); - mService.getLifecycleManager().scheduleTransaction(transaction); - - if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " - + next); - } catch (Exception e) { - // Whoops, need to restart this activity! - if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " - + lastState + ": " + next); - next.setState(lastState, "resumeTopActivityInnerLocked"); - - // lastResumedActivity being non-null implies there is a lastStack present. - if (lastResumedActivity != null) { - lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); - } + // Well the app will no longer be stopped. + // Clear app token stopped state in window manager if needed. + next.notifyAppResumed(next.stopped); + + EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, + System.identityHashCode(next), next.getTask().taskId, + next.shortComponentName); + + next.sleeping = false; + mService.getAppWarningsLocked().onResumeActivity(next); + next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState); + next.clearOptionsLocked(); + transaction.setLifecycleStateRequest( + ResumeActivityItem.obtain(next.app.getReportedProcState(), + getDisplay().getWindowContainerController() + .isNextTransitionForward())); + mService.getLifecycleManager().scheduleTransaction(transaction); + + if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + + next); + } catch (Exception e) { + // Whoops, need to restart this activity! + if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " + + lastState + ": " + next); + next.setState(lastState, "resumeTopActivityInnerLocked"); + + // lastResumedActivity being non-null implies there is a lastStack present. + if (lastResumedActivity != null) { + lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); + } - Slog.i(TAG, "Restarting because process died: " + next); - if (!next.hasBeenLaunched) { - next.hasBeenLaunched = true; - } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null - && lastFocusedStack.isTopStackOnDisplay()) { - next.showStartingWindow(null /* prev */, false /* newTask */, - false /* taskSwitch */); - } - mStackSupervisor.startSpecificActivityLocked(next, true, false); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - return true; + Slog.i(TAG, "Restarting because process died: " + next); + if (!next.hasBeenLaunched) { + next.hasBeenLaunched = true; + } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null + && lastFocusedStack.isTopStackOnDisplay()) { + next.showStartingWindow(null /* prev */, false /* newTask */, + false /* taskSwitch */); } + mStackSupervisor.startSpecificActivityLocked(next, true, false); + if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); + return true; } // From this point on, if something goes wrong there is no way @@ -4841,35 +4834,33 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mTmpBounds.clear(); mTmpInsetBounds.clear(); - synchronized (mWindowManager.getWindowManagerLock()) { - for (int i = mTaskHistory.size() - 1; i >= 0; i--) { - final TaskRecord task = mTaskHistory.get(i); - if (task.isResizeable()) { - if (inFreeformWindowingMode()) { - // TODO(b/71028874): Can be removed since each freeform task is its own - // stack. - // For freeform stack we don't adjust the size of the tasks to match that - // of the stack, but we do try to make sure the tasks are still contained - // with the bounds of the stack. - if (task.getOverrideBounds() != null) { - mTmpRect2.set(task.getOverrideBounds()); - fitWithinBounds(mTmpRect2, bounds); - task.updateOverrideConfiguration(mTmpRect2); - } - } else { - task.updateOverrideConfiguration(taskBounds, insetBounds); + for (int i = mTaskHistory.size() - 1; i >= 0; i--) { + final TaskRecord task = mTaskHistory.get(i); + if (task.isResizeable()) { + if (inFreeformWindowingMode()) { + // TODO(b/71028874): Can be removed since each freeform task is its own + // stack. + // For freeform stack we don't adjust the size of the tasks to match that + // of the stack, but we do try to make sure the tasks are still contained + // with the bounds of the stack. + if (task.getOverrideBounds() != null) { + mTmpRect2.set(task.getOverrideBounds()); + fitWithinBounds(mTmpRect2, bounds); + task.updateOverrideConfiguration(mTmpRect2); } - } - - mTmpBounds.put(task.taskId, task.getOverrideBounds()); - if (tempTaskInsetBounds != null) { - mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds); + } else { + task.updateOverrideConfiguration(taskBounds, insetBounds); } } - mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds); - setBounds(bounds); + mTmpBounds.put(task.taskId, task.getOverrideBounds()); + if (tempTaskInsetBounds != null) { + mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds); + } } + + mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds); + setBounds(bounds); } void onPipAnimationEndResize() { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 9bcee8a3ab23..76278d826b97 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -2051,7 +2051,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - mService.mAmInternal.trimApplications(); + mService.mH.post(() -> mService.mAmInternal.trimApplications()); //dump(); //mWindowManager.dump(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index dcc7bc577396..d6655928105e 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -22,6 +22,7 @@ import android.annotation.UserIdInt; import android.app.AppProtoEnums; import android.app.IActivityManager; import android.app.IApplicationThread; +import android.app.ProfilerInfo; import android.content.ComponentName; import android.content.IIntentSender; import android.content.Intent; @@ -468,4 +469,8 @@ public abstract class ActivityTaskManagerInternal { public abstract void clearLockedTasks(String reason); public abstract void updateUserConfiguration(); public abstract boolean canShowErrorDialogs(); + + public abstract void setProfileApp(String profileApp); + public abstract void setProfileProc(WindowProcessController wpc); + public abstract void setProfilerInfo(ProfilerInfo profilerInfo); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 3359eac880c7..faf9531f8f2a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -190,7 +190,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.IUserManager; import android.os.LocaleList; -import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; import android.os.PowerManager; @@ -247,9 +246,11 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AppOpsService; import com.android.server.AttributeCache; +import com.android.server.DisplayThread; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; +import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService; import com.android.server.am.ActivityManagerServiceDumpActivitiesProto; @@ -347,7 +348,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { IntentFirewall mIntentFirewall; /* Global service lock used by the package the owns this service. */ - Object mGlobalLock; + final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock(); ActivityStackSupervisor mStackSupervisor; WindowManagerService mWindowManager; private UserManagerService mUserManager; @@ -466,6 +467,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { String mTopAction = Intent.ACTION_MAIN; String mTopData; + /** Profiling app information. */ + String mProfileApp = null; + WindowProcessController mProfileProc = null; + ProfilerInfo mProfilerInfo = null; + /** * Dump of the activity state at the time of the last ANR. Cleared after * {@link WindowManagerService#LAST_ANR_LIFETIME_DURATION_MSECS} @@ -716,11 +722,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - // TODO: Will be converted to WM lock once transition is complete. - public void setActivityManagerService(Object globalLock, Looper looper, - IntentFirewall intentFirewall, PendingIntentController intentController) { - mGlobalLock = globalLock; - mH = new H(looper); + public WindowManagerGlobalLock getGlobalLock() { + return mGlobalLock; + } + + public void setActivityManagerService(IntentFirewall intentFirewall, + PendingIntentController intentController) { + mH = new H(); mUiHandler = new UiHandler(); mIntentFirewall = intentFirewall; final File systemDir = SystemServiceManager.ensureSystemDir(); @@ -5487,8 +5495,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_SUPERVISOR_STACK_MSG = 200; - public H(Looper looper) { - super(looper, null, true); + public H() { + super(DisplayThread.get().getLooper()); } @Override @@ -5506,7 +5514,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { static final int DISMISS_DIALOG_UI_MSG = 1; public UiHandler() { - super(com.android.server.UiThread.get().getLooper(), null, true); + super(UiThread.get().getLooper(), null, true); } @Override @@ -6762,5 +6770,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { && mAmInternal.getCurrentUser().isDemo()); } } + + @Override + public void setProfileApp(String profileApp) { + synchronized (mGlobalLock) { + mProfileApp = profileApp; + } + } + + @Override + public void setProfileProc(WindowProcessController wpc) { + synchronized (mGlobalLock) { + mProfileProc = wpc; + } + } + + @Override + public void setProfilerInfo(ProfilerInfo profilerInfo) { + synchronized (mGlobalLock) { + mProfilerInfo = profilerInfo; + } + } } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 9aeb0253250a..067b01a1b6ad 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -42,7 +42,6 @@ import android.os.Trace; import android.util.Slog; import android.view.IRecentsAnimationRunner; -import com.android.server.wm.AssistDataReceiverProxy; import com.android.server.am.AssistDataRequester; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; @@ -124,7 +123,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); - mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true); + mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true)); mWindowManager.deferSurfaceLayout(); try { @@ -234,7 +233,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, mStackSupervisor.sendPowerHintForLaunchEndIfNeeded(); } - mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false); + mService.mH.post( + () -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false)); mWindowManager.inSurfaceTransaction(() -> { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a641f75221d3..56d96aa134c4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -441,7 +441,7 @@ public class WindowManagerService extends IWindowManager.Stub final WindowHashMap mWindowMap = new WindowHashMap(); /** Global service lock used by the package the owns this service. */ - WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock(); + final WindowManagerGlobalLock mGlobalLock; /** * List of app window tokens that are waiting for replacing windows. If the @@ -855,9 +855,11 @@ public class WindowManagerService extends IWindowManager.Stub } public static WindowManagerService main(final Context context, final InputManagerService im, - final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy) { + final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, + final WindowManagerGlobalLock globalLock) { DisplayThread.getHandler().runWithScissors(() -> - sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy), + sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, + globalLock), 0); return sInstance; } @@ -879,8 +881,10 @@ public class WindowManagerService extends IWindowManager.Stub } private WindowManagerService(Context context, InputManagerService inputManager, - boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy) { + boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, + WindowManagerGlobalLock globalLock) { installLock(this, INDEX_WINDOW); + mGlobalLock = globalLock; mContext = context; mAllowBootMessages = showBootMsgs; mOnlyCore = onlyCore; @@ -2629,21 +2633,16 @@ public class WindowManagerService extends IWindowManager.Stub /** * Starts deferring layout passes. Useful when doing multiple changes but to optimize * performance, only one layout pass should be done. This can be called multiple times, and - * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout} + * layouting will be resumed once the last caller has called + * {@link #continueSurfaceLayout}. */ - public void deferSurfaceLayout() { - synchronized (mGlobalLock) { - mWindowPlacerLocked.deferLayout(); - } + void deferSurfaceLayout() { + mWindowPlacerLocked.deferLayout(); } - /** - * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} - */ - public void continueSurfaceLayout() { - synchronized (mGlobalLock) { - mWindowPlacerLocked.continueLayout(); - } + /** Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} */ + void continueSurfaceLayout() { + mWindowPlacerLocked.continueLayout(); } /** @@ -6902,7 +6901,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_DISPLAY) { Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId); } - synchronized (WindowManagerService.this) { + synchronized (mGlobalLock) { mVr2dDisplayId = vr2dDisplayId; } } @@ -7027,10 +7026,6 @@ public class WindowManagerService extends IWindowManager.Stub * WARNING: This interrupts surface updates, be careful! Don't * execute within the transaction for longer than you would * execute on an animation thread. - * WARNING: This holds the WindowManager lock, so if exec will acquire - * the ActivityManager lock, you should hold it BEFORE calling this - * otherwise there is a risk of deadlock if another thread holding the AM - * lock waits on the WM lock. * WARNING: This method contains locks known to the State of California * to cause Deadlocks and other conditions. * @@ -7051,19 +7046,12 @@ public class WindowManagerService extends IWindowManager.Stub * deferSurfaceLayout may be a little too broad, in particular the total * enclosure of startActivityUnchecked which could run for quite some time. */ - public void inSurfaceTransaction(Runnable exec) { - // We hold the WindowManger lock to ensure relayoutWindow - // does not return while a Surface transaction is opening. - // The client depends on us to have resized the surface - // by that point (b/36462635) - - synchronized (mGlobalLock) { - SurfaceControl.openTransaction(); - try { - exec.run(); - } finally { - SurfaceControl.closeTransaction(); - } + void inSurfaceTransaction(Runnable exec) { + SurfaceControl.openTransaction(); + try { + exec.run(); + } finally { + SurfaceControl.closeTransaction(); } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index bb1725477ac0..4c9788db7c3c 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -56,6 +56,7 @@ import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.Watchdog; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; @@ -690,24 +691,52 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } void addPackage(String pkg, long versionCode) { - // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are - // using WM lock. Need to figure-out if it is okay to do this asynchronously. if (mListener == null) return; - mListener.addPackage(pkg, versionCode); + // Posting on handler so WM lock isn't held when we call into AM. + final Message m = PooledLambda.obtainMessage( + WindowProcessListener::addPackage, mListener, pkg, versionCode); + mAtm.mH.sendMessage(m); } ProfilerInfo onStartActivity(int topProcessState) { - // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are - // using WM lock. Need to figure-out if it is okay to do this asynchronously. - if (mListener == null) return null; - return mListener.onStartActivity(topProcessState); + ProfilerInfo profilerInfo = null; + boolean setProfileProc = false; + if (mAtm.mProfileApp != null + && mAtm.mProfileApp.equals(mName)) { + if (mAtm.mProfileProc == null || mAtm.mProfileProc == this) { + setProfileProc = true; + final ProfilerInfo profilerInfoSvc = mAtm.mProfilerInfo; + if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) { + if (profilerInfoSvc.profileFd != null) { + try { + profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup(); + } catch (IOException e) { + profilerInfoSvc.closeFd(); + } + } + + profilerInfo = new ProfilerInfo(profilerInfoSvc); + } + } + } + + + if (mListener != null) { + // Posting on handler so WM lock isn't held when we call into AM. + final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity, + mListener, topProcessState, setProfileProc); + mAtm.mH.sendMessage(m); + } + + return profilerInfo; } public void appDied() { - // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are - // using WM lock. Need to figure-out if it is okay to do this asynchronously. if (mListener == null) return; - mListener.appDied(); + // Posting on handler so WM lock isn't held when we call into AM. + final Message m = PooledLambda.obtainMessage( + WindowProcessListener::appDied, mListener); + mAtm.mH.sendMessage(m); } void registerDisplayConfigurationListenerLocked(ActivityDisplay activityDisplay) { diff --git a/services/core/java/com/android/server/wm/WindowProcessListener.java b/services/core/java/com/android/server/wm/WindowProcessListener.java index 7f20f4b0add9..bce5e2dfeb44 100644 --- a/services/core/java/com/android/server/wm/WindowProcessListener.java +++ b/services/core/java/com/android/server/wm/WindowProcessListener.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import android.app.ProfilerInfo; import android.util.proto.ProtoOutputStream; /** @@ -58,7 +57,7 @@ public interface WindowProcessListener { void addPackage(String pkg, long versionCode); /** Called when we are in the process on starting an activity. */ - ProfilerInfo onStartActivity(int topProcessState); + void onStartActivity(int topProcessState, boolean setProfileProc); /** App died :(...oh well */ void appDied(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 54a140dec713..88111ac7354b 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -134,6 +134,7 @@ import com.android.server.usage.UsageStatsService; import com.android.server.vr.VrManagerService; import com.android.server.webkit.WebViewUpdateService; import com.android.server.wm.ActivityTaskManagerService; +import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; @@ -275,6 +276,7 @@ public final class SystemServer { // TODO: remove all of these references by improving dependency resolution and boot phases private PowerManagerService mPowerManagerService; private ActivityManagerService mActivityManagerService; + private WindowManagerGlobalLock mWindowManagerGlobalLock; private WebViewUpdateService mWebViewUpdateService; private DisplayManagerService mDisplayManagerService; private PackageManagerService mPackageManagerService; @@ -597,6 +599,7 @@ public final class SystemServer { mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); + mWindowManagerGlobalLock = atm.getGlobalLock(); traceEnd(); // Power manager needs to be started early because other services need it. @@ -921,7 +924,7 @@ public final class SystemServer { ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE); mSensorServiceStart = null; wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, - new PhoneWindowManager()); + new PhoneWindowManager(), mWindowManagerGlobalLock); ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); ServiceManager.addService(Context.INPUT_SERVICE, inputManager, diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java index 4e75ec9e8348..9a13efb4c58b 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java @@ -124,9 +124,10 @@ public class WindowManagerServiceRule implements TestRule { doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt()); } - mService = WindowManagerService.main(context, ims, false, - false, mPolicy = new TestWindowManagerPolicy( - WindowManagerServiceRule.this::getWindowManagerService)); + mService = WindowManagerService.main(context, ims, false, false, + mPolicy = new TestWindowManagerPolicy( + WindowManagerServiceRule.this::getWindowManagerService), + new WindowManagerGlobalLock()); mService.mTransactionFactory = () -> { final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); mSurfaceTransactions.add(new WeakReference<>(transaction)); diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 9e12f020d06e..b318b9190249 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -53,14 +53,6 @@ import org.mockito.invocation.InvocationOnMock; public class WindowTestUtils { private static int sNextTaskId = 0; - /** Retrieves an instance of a mock {@link WindowManagerService}. */ - static WindowManagerService getMockWindowManagerService() { - final WindowManagerService service = mock(WindowManagerService.class); - final WindowManagerGlobalLock lock = new WindowManagerGlobalLock(); - doReturn(lock).when(service).getWindowManagerLock(); - return service; - } - /** An extension of {@link DisplayContent} to gain package scoped access. */ public static class TestDisplayContent extends DisplayContent { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 9d28c5754040..c35e4d6766a9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -153,8 +153,7 @@ class ActivityTestsBase { void setupActivityManagerService( TestActivityManagerService am, TestActivityTaskManagerService atm) { - atm.setActivityManagerService(am, am.mHandlerThread.getLooper(), am.mIntentFirewall, - am.mPendingIntentController); + atm.setActivityManagerService(am.mIntentFirewall, am.mPendingIntentController); atm.mAmInternal = am.getLocalService(); am.mAtmInternal = atm.getLocalService(); // Makes sure the supervisor is using with the spy object. @@ -629,7 +628,7 @@ class ActivityTestsBase { } private static WindowManagerService prepareMockWindowManager() { - final WindowManagerService service = WindowTestUtils.getMockWindowManagerService(); + final WindowManagerService service = mock(WindowManagerService.class); doAnswer((InvocationOnMock invocationOnMock) -> { final Runnable runnable = invocationOnMock.<Runnable>getArgument(0); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java index 115bcb1f44a2..3b4ab3839146 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java @@ -38,15 +38,6 @@ import org.mockito.invocation.InvocationOnMock; * to WindowManager related test functionality. */ public class WindowTestUtils { - private static int sNextTaskId = 0; - - /** Retrieves an instance of a mock {@link WindowManagerService}. */ - static WindowManagerService getMockWindowManagerService() { - final WindowManagerService service = mock(WindowManagerService.class); - final WindowManagerGlobalLock lock = new WindowManagerGlobalLock(); - doReturn(lock).when(service).getWindowManagerLock(); - return service; - } /** An extension of {@link DisplayContent} to gain package scoped access. */ public static class TestDisplayContent extends DisplayContent { |