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