• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
20 import static android.app.ActivityManager.processStateAmToProto;
21 
22 import android.app.IApplicationThread;
23 import android.content.pm.ApplicationInfo;
24 import android.os.Debug;
25 import android.os.SystemClock;
26 import android.util.DebugUtils;
27 import android.util.TimeUtils;
28 
29 import com.android.internal.annotations.CompositeRWLock;
30 import com.android.internal.annotations.GuardedBy;
31 import com.android.internal.app.procstats.ProcessState;
32 import com.android.internal.app.procstats.ProcessStats;
33 import com.android.internal.os.BatteryStatsImpl;
34 import com.android.internal.util.FrameworkStatsLog;
35 import com.android.server.am.ProcessList.ProcStateMemTracker;
36 
37 import java.io.PrintWriter;
38 import java.util.concurrent.atomic.AtomicLong;
39 
40 /**
41  * Profiling info of the process, such as PSS, cpu, etc.
42  */
43 final class ProcessProfileRecord {
44     final ProcessRecord mApp;
45 
46     private final ActivityManagerService mService;
47 
48     final Object mProfilerLock;
49 
50     @GuardedBy("mProfilerLock")
51     private final ProcessList.ProcStateMemTracker mProcStateMemTracker =
52             new ProcessList.ProcStateMemTracker();
53 
54     /**
55      * Stats of pss, cpu, etc.
56      */
57     @GuardedBy("mService.mProcessStats.mLock")
58     private ProcessState mBaseProcessTracker;
59 
60     /**
61      * Last time we retrieved PSS data.
62      */
63     @GuardedBy("mProfilerLock")
64     private long mLastPssTime;
65 
66     /**
67      * Next time we want to request PSS data.
68      */
69     @GuardedBy("mProfilerLock")
70     private long mNextPssTime;
71 
72     /**
73      * Initial memory pss of process for idle maintenance.
74      */
75     @GuardedBy("mProfilerLock")
76     private long mInitialIdlePss;
77 
78     /**
79      * Last computed memory pss.
80      */
81     @GuardedBy("mProfilerLock")
82     private long mLastPss;
83 
84     /**
85      * Last computed SwapPss.
86      */
87     @GuardedBy("mProfilerLock")
88     private long mLastSwapPss;
89 
90     /**
91      * Last computed pss when in cached state.
92      */
93     @GuardedBy("mProfilerLock")
94     private long mLastCachedPss;
95 
96     /**
97      * Last computed SwapPss when in cached state.
98      */
99     @GuardedBy("mProfilerLock")
100     private long mLastCachedSwapPss;
101 
102     /**
103      * Last computed memory rss.
104      */
105     @GuardedBy("mProfilerLock")
106     private long mLastRss;
107 
108     /**
109      * Cache of last retrieve memory info, to throttle how frequently apps can request it.
110      */
111     @GuardedBy("mProfilerLock")
112     private Debug.MemoryInfo mLastMemInfo;
113 
114     /**
115      * Cache of last retrieve memory uptime, to throttle how frequently apps can request it.
116      */
117     @GuardedBy("mProfilerLock")
118     private long mLastMemInfoTime;
119 
120     /**
121      * Currently requesting pss for.
122      */
123     @GuardedBy("mProfilerLock")
124     private int mPssProcState = PROCESS_STATE_NONEXISTENT;
125 
126     /**
127      * The type of stat collection that we are currently requesting.
128      */
129     @GuardedBy("mProfilerLock")
130     private int mPssStatType;
131 
132     /**
133      * How long proc has run CPU at last check.
134      */
135     final AtomicLong mLastCpuTime = new AtomicLong(0);
136 
137     /**
138      * How long proc has run CPU most recently.
139      */
140     final AtomicLong mCurCpuTime = new AtomicLong(0);
141 
142     /**
143      * Last selected memory trimming level.
144      */
145     @CompositeRWLock({"mService", "mProcLock"})
146     private int mTrimMemoryLevel;
147 
148     /**
149      * Want to clean up resources from showing UI?
150      */
151     @GuardedBy("mProcLock")
152     private boolean mPendingUiClean;
153 
154     /**
155      * Pointer to the battery stats of this process.
156      */
157     private BatteryStatsImpl.Uid.Proc mCurProcBatteryStats;
158 
159     /**
160      * When we last asked the app to do a gc.
161      */
162     @GuardedBy("mProfilerLock")
163     private long mLastRequestedGc;
164 
165     /**
166      * When we last told the app that memory is low.
167      */
168     @CompositeRWLock({"mService", "mProfilerLock"})
169     private long mLastLowMemory;
170 
171     /**
172      * Set to true when waiting to report low mem.
173      */
174     @GuardedBy("mProfilerLock")
175     private boolean mReportLowMemory;
176 
177     // ========================================================================
178     // Local copies of some process info, to avoid holding global AMS lock
179     @GuardedBy("mProfilerLock")
180     private int mPid;
181 
182     @GuardedBy("mProfilerLock")
183     private IApplicationThread mThread;
184 
185     @GuardedBy("mProfilerLock")
186     private int mSetProcState;
187 
188     @GuardedBy("mProfilerLock")
189     private int mSetAdj;
190 
191     @GuardedBy("mProfilerLock")
192     private int mCurRawAdj;
193 
194     @GuardedBy("mProfilerLock")
195     private long mLastStateTime;
196 
197     private final ActivityManagerGlobalLock mProcLock;
198 
ProcessProfileRecord(final ProcessRecord app)199     ProcessProfileRecord(final ProcessRecord app) {
200         mApp = app;
201         mService = app.mService;
202         mProcLock = mService.mProcLock;
203         mProfilerLock = mService.mAppProfiler.mProfilerLock;
204     }
205 
init(long now)206     void init(long now) {
207         mLastPssTime = mNextPssTime = now;
208     }
209 
210     @GuardedBy("mService.mProcessStats.mLock")
getBaseProcessTracker()211     ProcessState getBaseProcessTracker() {
212         return mBaseProcessTracker;
213     }
214 
215     @GuardedBy("mService.mProcessStats.mLock")
setBaseProcessTracker(ProcessState baseProcessTracker)216     void setBaseProcessTracker(ProcessState baseProcessTracker) {
217         mBaseProcessTracker = baseProcessTracker;
218     }
219 
onProcessActive(IApplicationThread thread, ProcessStatsService tracker)220     void onProcessActive(IApplicationThread thread, ProcessStatsService tracker) {
221         if (mThread == null) {
222             synchronized (mProfilerLock) {
223                 synchronized (tracker.mLock) {
224                     final ProcessState origBase = getBaseProcessTracker();
225                     final PackageList pkgList = mApp.getPkgList();
226                     if (origBase != null) {
227                         synchronized (pkgList) {
228                             origBase.setState(ProcessStats.STATE_NOTHING,
229                                     tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
230                                     pkgList.getPackageListLocked());
231                             pkgList.forEachPackage((pkgName, holder) ->
232                                     FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
233                                         mApp.uid, mApp.processName, pkgName,
234                                         processStateAmToProto(ProcessStats.STATE_NOTHING),
235                                         holder.appVersion)
236                             );
237                         }
238                         origBase.makeInactive();
239                     }
240                     final ApplicationInfo info = mApp.info;
241                     final ProcessState baseProcessTracker = tracker.getProcessStateLocked(
242                             info.packageName, info.uid, info.longVersionCode, mApp.processName);
243                     setBaseProcessTracker(baseProcessTracker);
244                     baseProcessTracker.makeActive();
245                     pkgList.forEachPackage((pkgName, holder) -> {
246                         if (holder.state != null && holder.state != origBase) {
247                             holder.state.makeInactive();
248                         }
249                         tracker.updateProcessStateHolderLocked(holder, pkgName, mApp.info.uid,
250                                 mApp.info.longVersionCode, mApp.processName);
251                         if (holder.state != baseProcessTracker) {
252                             holder.state.makeActive();
253                         }
254                     });
255                     mThread = thread;
256                 }
257             }
258         } else {
259             synchronized (mProfilerLock) {
260                 mThread = thread;
261             }
262         }
263     }
264 
onProcessInactive(ProcessStatsService tracker)265     void onProcessInactive(ProcessStatsService tracker) {
266         synchronized (mProfilerLock) {
267             synchronized (tracker.mLock) {
268                 final ProcessState origBase = getBaseProcessTracker();
269                 if (origBase != null) {
270                     final PackageList pkgList = mApp.getPkgList();
271                     synchronized (pkgList) {
272                         origBase.setState(ProcessStats.STATE_NOTHING,
273                                 tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
274                                 pkgList.getPackageListLocked());
275                         pkgList.forEachPackage((pkgName, holder) ->
276                                 FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
277                                     mApp.uid, mApp.processName, pkgName,
278                                     processStateAmToProto(ProcessStats.STATE_NOTHING),
279                                     holder.appVersion)
280                         );
281                     }
282                     origBase.makeInactive();
283                     setBaseProcessTracker(null);
284                     pkgList.forEachPackageProcessStats(holder -> {
285                         if (holder.state != null && holder.state != origBase) {
286                             holder.state.makeInactive();
287                         }
288                         holder.pkg = null;
289                         holder.state = null;
290                     });
291                 }
292                 mThread = null;
293             }
294         }
295     }
296 
297     @GuardedBy("mProfilerLock")
getLastPssTime()298     long getLastPssTime() {
299         return mLastPssTime;
300     }
301 
302     @GuardedBy("mProfilerLock")
setLastPssTime(long lastPssTime)303     void setLastPssTime(long lastPssTime) {
304         mLastPssTime = lastPssTime;
305     }
306 
307     @GuardedBy("mProfilerLock")
getNextPssTime()308     long getNextPssTime() {
309         return mNextPssTime;
310     }
311 
312     @GuardedBy("mProfilerLock")
setNextPssTime(long nextPssTime)313     void setNextPssTime(long nextPssTime) {
314         mNextPssTime = nextPssTime;
315     }
316 
317     @GuardedBy("mProfilerLock")
getInitialIdlePss()318     long getInitialIdlePss() {
319         return mInitialIdlePss;
320     }
321 
322     @GuardedBy("mProfilerLock")
setInitialIdlePss(long initialIdlePss)323     void setInitialIdlePss(long initialIdlePss) {
324         mInitialIdlePss = initialIdlePss;
325     }
326 
327     @GuardedBy("mProfilerLock")
getLastPss()328     long getLastPss() {
329         return mLastPss;
330     }
331 
332     @GuardedBy("mProfilerLock")
setLastPss(long lastPss)333     void setLastPss(long lastPss) {
334         mLastPss = lastPss;
335     }
336 
337     @GuardedBy("mProfilerLock")
getLastCachedPss()338     long getLastCachedPss() {
339         return mLastCachedPss;
340     }
341 
342     @GuardedBy("mProfilerLock")
setLastCachedPss(long lastCachedPss)343     void setLastCachedPss(long lastCachedPss) {
344         mLastCachedPss = lastCachedPss;
345     }
346 
347     @GuardedBy("mProfilerLock")
getLastSwapPss()348     long getLastSwapPss() {
349         return mLastSwapPss;
350     }
351 
352     @GuardedBy("mProfilerLock")
setLastSwapPss(long lastSwapPss)353     void setLastSwapPss(long lastSwapPss) {
354         mLastSwapPss = lastSwapPss;
355     }
356 
357     @GuardedBy("mProfilerLock")
getLastCachedSwapPss()358     long getLastCachedSwapPss() {
359         return mLastCachedSwapPss;
360     }
361 
362     @GuardedBy("mProfilerLock")
setLastCachedSwapPss(long lastCachedSwapPss)363     void setLastCachedSwapPss(long lastCachedSwapPss) {
364         mLastCachedSwapPss = lastCachedSwapPss;
365     }
366 
367     @GuardedBy("mProfilerLock")
getLastRss()368     long getLastRss() {
369         return mLastRss;
370     }
371 
372     @GuardedBy("mProfilerLock")
setLastRss(long lastRss)373     void setLastRss(long lastRss) {
374         mLastRss = lastRss;
375     }
376 
377     @GuardedBy("mProfilerLock")
getLastMemInfo()378     Debug.MemoryInfo getLastMemInfo() {
379         return mLastMemInfo;
380     }
381 
382     @GuardedBy("mProfilerLock")
setLastMemInfo(Debug.MemoryInfo lastMemInfo)383     void setLastMemInfo(Debug.MemoryInfo lastMemInfo) {
384         mLastMemInfo = lastMemInfo;
385     }
386 
387     @GuardedBy("mProfilerLock")
getLastMemInfoTime()388     long getLastMemInfoTime() {
389         return mLastMemInfoTime;
390     }
391 
392     @GuardedBy("mProfilerLock")
setLastMemInfoTime(long lastMemInfoTime)393     void setLastMemInfoTime(long lastMemInfoTime) {
394         mLastMemInfoTime = lastMemInfoTime;
395     }
396 
397     @GuardedBy("mProfilerLock")
getPssProcState()398     int getPssProcState() {
399         return mPssProcState;
400     }
401 
402     @GuardedBy("mProfilerLock")
setPssProcState(int pssProcState)403     void setPssProcState(int pssProcState) {
404         mPssProcState = pssProcState;
405     }
406 
407     @GuardedBy("mProfilerLock")
getPssStatType()408     int getPssStatType() {
409         return mPssStatType;
410     }
411 
412     @GuardedBy("mProfilerLock")
setPssStatType(int pssStatType)413     void setPssStatType(int pssStatType) {
414         mPssStatType = pssStatType;
415     }
416 
417     @GuardedBy(anyOf = {"mService", "mProcLock"})
getTrimMemoryLevel()418     int getTrimMemoryLevel() {
419         return mTrimMemoryLevel;
420     }
421 
422     @GuardedBy({"mService", "mProcLock"})
setTrimMemoryLevel(int trimMemoryLevel)423     void setTrimMemoryLevel(int trimMemoryLevel) {
424         mTrimMemoryLevel = trimMemoryLevel;
425     }
426 
427     @GuardedBy("mProcLock")
hasPendingUiClean()428     boolean hasPendingUiClean() {
429         return mPendingUiClean;
430     }
431 
432     @GuardedBy("mProcLock")
setPendingUiClean(boolean pendingUiClean)433     void setPendingUiClean(boolean pendingUiClean) {
434         mPendingUiClean = pendingUiClean;
435         mApp.getWindowProcessController().setPendingUiClean(pendingUiClean);
436     }
437 
getCurProcBatteryStats()438     BatteryStatsImpl.Uid.Proc getCurProcBatteryStats() {
439         return mCurProcBatteryStats;
440     }
441 
setCurProcBatteryStats(BatteryStatsImpl.Uid.Proc curProcBatteryStats)442     void setCurProcBatteryStats(BatteryStatsImpl.Uid.Proc curProcBatteryStats) {
443         mCurProcBatteryStats = curProcBatteryStats;
444     }
445 
446     @GuardedBy("mProfilerLock")
getLastRequestedGc()447     long getLastRequestedGc() {
448         return mLastRequestedGc;
449     }
450 
451     @GuardedBy("mProfilerLock")
setLastRequestedGc(long lastRequestedGc)452     void setLastRequestedGc(long lastRequestedGc) {
453         mLastRequestedGc = lastRequestedGc;
454     }
455 
456     @GuardedBy(anyOf = {"mService", "mProfilerLock"})
getLastLowMemory()457     long getLastLowMemory() {
458         return mLastLowMemory;
459     }
460 
461     @GuardedBy({"mService", "mProfilerLock"})
setLastLowMemory(long lastLowMemory)462     void setLastLowMemory(long lastLowMemory) {
463         mLastLowMemory = lastLowMemory;
464     }
465 
466     @GuardedBy("mProfilerLock")
getReportLowMemory()467     boolean getReportLowMemory() {
468         return mReportLowMemory;
469     }
470 
471     @GuardedBy("mProfilerLock")
setReportLowMemory(boolean reportLowMemory)472     void setReportLowMemory(boolean reportLowMemory) {
473         mReportLowMemory = reportLowMemory;
474     }
475 
addPss(long pss, long uss, long rss, boolean always, int type, long duration)476     void addPss(long pss, long uss, long rss, boolean always, int type, long duration) {
477         synchronized (mService.mProcessStats.mLock) {
478             final ProcessState tracker = mBaseProcessTracker;
479             if (tracker != null) {
480                 final PackageList pkgList = mApp.getPkgList();
481                 synchronized (pkgList) {
482                     tracker.addPss(pss, uss, rss, always, type, duration,
483                             pkgList.getPackageListLocked());
484                 }
485             }
486         }
487     }
488 
reportExcessiveCpu()489     void reportExcessiveCpu() {
490         synchronized (mService.mProcessStats.mLock) {
491             final ProcessState tracker = mBaseProcessTracker;
492             if (tracker != null) {
493                 final PackageList pkgList = mApp.getPkgList();
494                 synchronized (pkgList) {
495                     tracker.reportExcessiveCpu(pkgList.getPackageListLocked());
496                 }
497             }
498         }
499     }
500 
reportCachedKill()501     void reportCachedKill() {
502         synchronized (mService.mProcessStats.mLock) {
503             final ProcessState tracker = mBaseProcessTracker;
504             if (tracker != null) {
505                 final PackageList pkgList = mApp.getPkgList();
506                 synchronized (pkgList) {
507                     tracker.reportCachedKill(pkgList.getPackageListLocked(), mLastCachedPss);
508                     pkgList.forEachPackageProcessStats(holder ->
509                             FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
510                                 mApp.info.uid,
511                                 holder.state.getName(),
512                                 holder.state.getPackage(),
513                                 mLastCachedPss,
514                                 holder.appVersion)
515                     );
516                 }
517             }
518         }
519     }
520 
setProcessTrackerState(int procState, int memFactor, long now)521     void setProcessTrackerState(int procState, int memFactor, long now) {
522         synchronized (mService.mProcessStats.mLock) {
523             final ProcessState tracker = mBaseProcessTracker;
524             if (tracker != null) {
525                 if (procState != PROCESS_STATE_NONEXISTENT) {
526                     final PackageList pkgList = mApp.getPkgList();
527                     synchronized (pkgList) {
528                         tracker.setState(procState, memFactor, now,
529                                 pkgList.getPackageListLocked());
530                     }
531                 }
532             }
533         }
534     }
535 
536     @GuardedBy("mProfilerLock")
commitNextPssTime()537     void commitNextPssTime() {
538         commitNextPssTime(mProcStateMemTracker);
539     }
540 
541     @GuardedBy("mProfilerLock")
abortNextPssTime()542     void abortNextPssTime() {
543         abortNextPssTime(mProcStateMemTracker);
544     }
545 
546     @GuardedBy("mProfilerLock")
computeNextPssTime(int procState, boolean test, boolean sleeping, long now)547     long computeNextPssTime(int procState, boolean test, boolean sleeping, long now) {
548         return ProcessList.computeNextPssTime(procState, mProcStateMemTracker, test, sleeping, now);
549     }
550 
commitNextPssTime(ProcStateMemTracker tracker)551     private static void commitNextPssTime(ProcStateMemTracker tracker) {
552         if (tracker.mPendingMemState >= 0) {
553             tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
554             tracker.mScalingFactor[tracker.mPendingMemState] = tracker.mPendingScalingFactor;
555             tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
556             tracker.mPendingMemState = -1;
557         }
558     }
559 
abortNextPssTime(ProcStateMemTracker tracker)560     private static void abortNextPssTime(ProcStateMemTracker tracker) {
561         tracker.mPendingMemState = -1;
562     }
563 
564     @GuardedBy("mProfilerLock")
getPid()565     int getPid() {
566         return mPid;
567     }
568 
569     @GuardedBy("mProfilerLock")
setPid(int pid)570     void setPid(int pid) {
571         mPid = pid;
572     }
573 
574     @GuardedBy("mProfilerLock")
getThread()575     IApplicationThread getThread() {
576         return mThread;
577     }
578 
579     @GuardedBy("mProfilerLock")
getSetProcState()580     int getSetProcState() {
581         return mSetProcState;
582     }
583 
584     @GuardedBy("mProfilerLock")
getSetAdj()585     int getSetAdj() {
586         return mSetAdj;
587     }
588 
589     @GuardedBy("mProfilerLock")
getCurRawAdj()590     int getCurRawAdj() {
591         return mCurRawAdj;
592     }
593 
594     @GuardedBy("mProfilerLock")
getLastStateTime()595     long getLastStateTime() {
596         return mLastStateTime;
597     }
598 
599     @GuardedBy({"mService", "mProfilerLock"})
updateProcState(ProcessStateRecord state)600     void updateProcState(ProcessStateRecord state) {
601         mSetProcState = state.getCurProcState();
602         mSetAdj = state.getCurAdj();
603         mCurRawAdj = state.getCurRawAdj();
604         mLastStateTime = state.getLastStateTime();
605     }
606 
607     @GuardedBy("mService")
dumpPss(PrintWriter pw, String prefix, long nowUptime)608     void dumpPss(PrintWriter pw, String prefix, long nowUptime) {
609         synchronized (mProfilerLock) {
610             pw.print(prefix);
611             pw.print("lastPssTime=");
612             TimeUtils.formatDuration(mLastPssTime, nowUptime, pw);
613             pw.print(" pssProcState=");
614             pw.print(mPssProcState);
615             pw.print(" pssStatType=");
616             pw.print(mPssStatType);
617             pw.print(" nextPssTime=");
618             TimeUtils.formatDuration(mNextPssTime, nowUptime, pw);
619             pw.println();
620             pw.print(prefix);
621             pw.print("lastPss=");
622             DebugUtils.printSizeValue(pw, mLastPss * 1024);
623             pw.print(" lastSwapPss=");
624             DebugUtils.printSizeValue(pw, mLastSwapPss * 1024);
625             pw.print(" lastCachedPss=");
626             DebugUtils.printSizeValue(pw, mLastCachedPss * 1024);
627             pw.print(" lastCachedSwapPss=");
628             DebugUtils.printSizeValue(pw, mLastCachedSwapPss * 1024);
629             pw.print(" lastRss=");
630             DebugUtils.printSizeValue(pw, mLastRss * 1024);
631             pw.println();
632             pw.print(prefix);
633             pw.print("trimMemoryLevel=");
634             pw.println(mTrimMemoryLevel);
635             pw.print(prefix); pw.print("procStateMemTracker: ");
636             mProcStateMemTracker.dumpLine(pw);
637             pw.print(prefix);
638             pw.print("lastRequestedGc=");
639             TimeUtils.formatDuration(mLastRequestedGc, nowUptime, pw);
640             pw.print(" lastLowMemory=");
641             TimeUtils.formatDuration(mLastLowMemory, nowUptime, pw);
642             pw.print(" reportLowMemory=");
643             pw.println(mReportLowMemory);
644         }
645     }
646 
dumpCputime(PrintWriter pw, String prefix)647     void dumpCputime(PrintWriter pw, String prefix) {
648         final long lastCpuTime = mLastCpuTime.get();
649         pw.print(prefix);
650         pw.print("lastCpuTime=");
651         pw.print(lastCpuTime);
652         if (lastCpuTime > 0) {
653             pw.print(" timeUsed=");
654             TimeUtils.formatDuration(mCurCpuTime.get() - lastCpuTime, pw);
655         }
656         pw.println();
657     }
658 }
659