• 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 android.annotation.UptimeMillisLong;
20 import android.app.ActivityManagerInternal.OomAdjReason;
21 import android.util.TimeUtils;
22 
23 import com.android.internal.annotations.GuardedBy;
24 import com.android.internal.annotations.VisibleForTesting;
25 
26 import java.io.PrintWriter;
27 
28 import dalvik.annotation.optimization.NeverCompile;
29 
30 /**
31  * The state info of app when it's cached, used by the optimizer.
32  */
33 final class ProcessCachedOptimizerRecord {
34     private final ProcessRecord mApp;
35 
36     private final ActivityManagerGlobalLock mProcLock;
37 
38     @VisibleForTesting
39     static final String IS_FROZEN = "isFrozen";
40 
41     /**
42      * The last time that this process was compacted.
43      */
44     @GuardedBy("mProcLock")
45     private long mLastCompactTime;
46 
47     /**
48      * The most recent compaction profile requested for this app.
49      */
50     @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mReqCompactProfile;
51 
52     /**
53      * Source that requested the latest compaction for this app.
54      */
55     @GuardedBy("mProcLock") private CachedAppOptimizer.CompactSource mReqCompactSource;
56 
57     /**
58      * Last oom adjust change reason for this app.
59      */
60     @GuardedBy("mProcLock") private @OomAdjReason int mLastOomAdjChangeReason;
61 
62     /**
63      * The most recent compaction action performed for this app.
64      */
65     @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mLastCompactProfile;
66 
67     /**
68      * This process has been scheduled for a memory compaction.
69      */
70     @GuardedBy("mProcLock")
71     private boolean mPendingCompact;
72 
73     @GuardedBy("mProcLock") private boolean mForceCompact;
74 
75     /**
76      * True when the process is frozen.
77      */
78     @GuardedBy("mProcLock")
79     private boolean mFrozen;
80 
81     /**
82      * If set to true it will make the (un)freeze decision sticky which means that the freezer
83      * decision will remain the same unless a freeze is forced via {@link #mForceFreezeOps}.
84      * This property is usually set to true when external user wants to maintain a (un)frozen state
85      * after being applied.
86      */
87     @GuardedBy("mProcLock")
88     private boolean mFreezeSticky;
89 
90     /**
91      * Set to false after the process has been frozen.
92      * Set to true after we have collected PSS for the frozen process.
93      */
94     private boolean mHasCollectedFrozenPSS;
95 
96     /**
97      * An override on the freeze state is in progress.
98      */
99     @GuardedBy("mProcLock")
100     boolean mFreezerOverride;
101 
102     /**
103      * Last time the app was (un)frozen, 0 for never.
104      */
105     @GuardedBy("mProcLock")
106     private long mFreezeUnfreezeTime;
107 
108     /**
109      * True if a process has a WPRI binding from an unfrozen process.
110      */
111     @GuardedBy("mProcLock")
112     private boolean mShouldNotFreeze;
113 
114     /**
115      * Exempt from freezer (now for system apps with INSTALL_PACKAGES permission)
116      */
117     @GuardedBy("mProcLock")
118     private boolean mFreezeExempt;
119 
120     /**
121      * This process has been scheduled for freezing
122      */
123     @GuardedBy("mProcLock")
124     private boolean mPendingFreeze;
125 
126     /**
127      * This is the soonest the process can be allowed to freeze, in uptime millis
128      */
129     @GuardedBy("mProcLock")
130     private @UptimeMillisLong long mEarliestFreezableTimeMillis;
131 
132     /**
133      * This is the most recently used timeout for freezing the app in millis
134      */
135     @GuardedBy("mProcLock")
136     private long mLastUsedTimeout;
137 
138     @GuardedBy("mProcLock")
getLastCompactTime()139     long getLastCompactTime() {
140         return mLastCompactTime;
141     }
142 
143     @GuardedBy("mProcLock")
setLastCompactTime(long lastCompactTime)144     void setLastCompactTime(long lastCompactTime) {
145         mLastCompactTime = lastCompactTime;
146     }
147 
148     @GuardedBy("mProcLock")
getReqCompactProfile()149     CachedAppOptimizer.CompactProfile getReqCompactProfile() {
150         return mReqCompactProfile;
151     }
152 
153     @GuardedBy("mProcLock")
setReqCompactProfile(CachedAppOptimizer.CompactProfile reqCompactProfile)154     void setReqCompactProfile(CachedAppOptimizer.CompactProfile reqCompactProfile) {
155         mReqCompactProfile = reqCompactProfile;
156     }
157 
158     @GuardedBy("mProcLock")
getReqCompactSource()159     CachedAppOptimizer.CompactSource getReqCompactSource() {
160         return mReqCompactSource;
161     }
162 
163     @GuardedBy("mProcLock")
setReqCompactSource(CachedAppOptimizer.CompactSource stat)164     void setReqCompactSource(CachedAppOptimizer.CompactSource stat) {
165         mReqCompactSource = stat;
166     }
167 
168     @GuardedBy("mProcLock")
setLastOomAdjChangeReason(@omAdjReason int reason)169     void setLastOomAdjChangeReason(@OomAdjReason int reason) {
170         mLastOomAdjChangeReason = reason;
171     }
172 
173     @GuardedBy("mProcLock")
174     @OomAdjReason
getLastOomAdjChangeReason()175     int getLastOomAdjChangeReason() {
176         return mLastOomAdjChangeReason;
177     }
178 
179     @GuardedBy("mProcLock")
getLastCompactProfile()180     CachedAppOptimizer.CompactProfile getLastCompactProfile() {
181         if (mLastCompactProfile == null) {
182             // The first compaction won't have a previous one, so assign one to avoid crashing.
183             mLastCompactProfile = CachedAppOptimizer.CompactProfile.SOME;
184         }
185 
186         return mLastCompactProfile;
187     }
188 
189     @GuardedBy("mProcLock")
setLastCompactProfile(CachedAppOptimizer.CompactProfile lastCompactProfile)190     void setLastCompactProfile(CachedAppOptimizer.CompactProfile lastCompactProfile) {
191         mLastCompactProfile = lastCompactProfile;
192     }
193 
194     @GuardedBy("mProcLock")
hasPendingCompact()195     boolean hasPendingCompact() {
196         return mPendingCompact;
197     }
198 
199     @GuardedBy("mProcLock")
setHasPendingCompact(boolean pendingCompact)200     void setHasPendingCompact(boolean pendingCompact) {
201         mPendingCompact = pendingCompact;
202     }
203 
204     @GuardedBy("mProcLock")
isForceCompact()205     boolean isForceCompact() {
206         return mForceCompact;
207     }
208 
209     @GuardedBy("mProcLock")
setForceCompact(boolean forceCompact)210     void setForceCompact(boolean forceCompact) {
211         mForceCompact = forceCompact;
212     }
213 
214     @GuardedBy("mProcLock")
isFrozen()215     boolean isFrozen() {
216         return mFrozen;
217     }
218 
219     @GuardedBy("mProcLock")
setFrozen(boolean frozen)220     void setFrozen(boolean frozen) {
221         mFrozen = frozen;
222     }
223     @GuardedBy("mProcLock")
setFreezeSticky(boolean sticky)224     void setFreezeSticky(boolean sticky) {
225         mFreezeSticky = sticky;
226     }
227 
228     @GuardedBy("mProcLock")
isFreezeSticky()229     boolean isFreezeSticky() {
230         return mFreezeSticky;
231     }
232 
skipPSSCollectionBecauseFrozen()233     boolean skipPSSCollectionBecauseFrozen() {
234         boolean collected = mHasCollectedFrozenPSS;
235 
236         // This check is racy but it isn't critical to PSS collection that we have the most up to
237         // date idea of whether a task is frozen.
238         if (!mFrozen) {
239             // not frozen == always ask to collect PSS
240             return false;
241         }
242 
243         // We don't want to count PSS for a frozen process more than once.
244         mHasCollectedFrozenPSS = true;
245         return collected;
246     }
247 
setHasCollectedFrozenPSS(boolean collected)248     void setHasCollectedFrozenPSS(boolean collected) {
249         mHasCollectedFrozenPSS = collected;
250     }
251 
252     @GuardedBy("mProcLock")
hasFreezerOverride()253     boolean hasFreezerOverride() {
254         return mFreezerOverride;
255     }
256 
257     @GuardedBy("mProcLock")
setFreezerOverride(boolean freezerOverride)258     void setFreezerOverride(boolean freezerOverride) {
259         mFreezerOverride = freezerOverride;
260     }
261 
262     @GuardedBy("mProcLock")
getFreezeUnfreezeTime()263     long getFreezeUnfreezeTime() {
264         return mFreezeUnfreezeTime;
265     }
266 
267     @GuardedBy("mProcLock")
setFreezeUnfreezeTime(long freezeUnfreezeTime)268     void setFreezeUnfreezeTime(long freezeUnfreezeTime) {
269         mFreezeUnfreezeTime = freezeUnfreezeTime;
270     }
271 
272     @GuardedBy("mProcLock")
shouldNotFreeze()273     boolean shouldNotFreeze() {
274         return mShouldNotFreeze;
275     }
276 
277     @GuardedBy("mProcLock")
setShouldNotFreeze(boolean shouldNotFreeze)278     void setShouldNotFreeze(boolean shouldNotFreeze) {
279         setShouldNotFreeze(shouldNotFreeze, false);
280     }
281 
282     /**
283      * @return {@code true} if it's a dry run and it's going to unfreeze the process
284      * if it was a real run.
285      */
286     @GuardedBy("mProcLock")
setShouldNotFreeze(boolean shouldNotFreeze, boolean dryRun)287     boolean setShouldNotFreeze(boolean shouldNotFreeze, boolean dryRun) {
288         if (dryRun) {
289             return mFrozen && !shouldNotFreeze;
290         }
291         mShouldNotFreeze = shouldNotFreeze;
292         return false;
293     }
294 
295     @GuardedBy("mProcLock")
getEarliestFreezableTime()296     @UptimeMillisLong long getEarliestFreezableTime() {
297         return mEarliestFreezableTimeMillis;
298     }
299 
300     @GuardedBy("mProcLock")
setEarliestFreezableTime(@ptimeMillisLong long earliestFreezableTimeMillis)301     void setEarliestFreezableTime(@UptimeMillisLong long earliestFreezableTimeMillis) {
302         mEarliestFreezableTimeMillis = earliestFreezableTimeMillis;
303     }
304 
305     @GuardedBy("mProcLock")
getLastUsedTimeout()306     long getLastUsedTimeout() {
307         return mLastUsedTimeout;
308     }
309 
310     @GuardedBy("mProcLock")
setLastUsedTimeout(long lastUsedTimeout)311     void setLastUsedTimeout(long lastUsedTimeout) {
312         mLastUsedTimeout = lastUsedTimeout;
313     }
314 
315     @GuardedBy("mProcLock")
isFreezeExempt()316     boolean isFreezeExempt() {
317         return mFreezeExempt;
318     }
319 
320     @GuardedBy("mProcLock")
setPendingFreeze(boolean freeze)321     void setPendingFreeze(boolean freeze) {
322         mPendingFreeze = freeze;
323     }
324 
325     @GuardedBy("mProcLock")
isPendingFreeze()326     boolean isPendingFreeze() {
327         return mPendingFreeze;
328     }
329 
330     @GuardedBy("mProcLock")
setFreezeExempt(boolean exempt)331     void setFreezeExempt(boolean exempt) {
332         mFreezeExempt = exempt;
333     }
334 
ProcessCachedOptimizerRecord(ProcessRecord app)335     ProcessCachedOptimizerRecord(ProcessRecord app) {
336         mApp = app;
337         mProcLock = app.mService.mProcLock;
338     }
339 
init(long nowUptime)340     void init(long nowUptime) {
341         mFreezeUnfreezeTime = nowUptime;
342     }
343 
344     @GuardedBy("mProcLock")
345     @NeverCompile
dump(PrintWriter pw, String prefix, long nowUptime)346     void dump(PrintWriter pw, String prefix, long nowUptime) {
347         pw.print(prefix); pw.print("lastCompactTime="); pw.print(mLastCompactTime);
348         pw.print(" lastCompactProfile=");
349         pw.println(mLastCompactProfile);
350         pw.print(prefix);
351         pw.print("hasPendingCompaction=");
352         pw.print(mPendingCompact);
353         pw.print(prefix); pw.print("isFreezeExempt="); pw.print(mFreezeExempt);
354         pw.print(" isPendingFreeze="); pw.print(mPendingFreeze);
355         pw.print(" " + IS_FROZEN + "="); pw.println(mFrozen);
356         pw.print(prefix); pw.print("earliestFreezableTimeMs=");
357         TimeUtils.formatDuration(mEarliestFreezableTimeMillis, nowUptime, pw);
358         pw.println();
359     }
360 }
361